diff --git a/.github/actions/setup-appium-server/action.yml b/.github/actions/setup-appium-server/action.yml new file mode 100644 index 000000000..a9177d4e8 --- /dev/null +++ b/.github/actions/setup-appium-server/action.yml @@ -0,0 +1,65 @@ +name: 'Start Appium Server' +description: 'Start Appium server with configurable arguments and wait for startup' + +inputs: + port: + description: 'Appium server port' + required: false + default: '4723' + host: + description: 'Appium server host' + required: false + default: '127.0.0.1' + timeout: + description: 'Timeout in seconds to wait for server startup' + required: false + default: '25' + server_args: + description: 'Additional server arguments (space-separated)' + required: false + default: '' + log_file: + description: 'Log file name' + required: false + default: 'appium.log' + +runs: + using: 'composite' + steps: + - name: Start Appium server + shell: bash + run: | + nohup appium server \ + --port=${{ inputs.port }} \ + --address=${{ inputs.host }} \ + --log-no-colors \ + --log-timestamp \ + --keep-alive-timeout 1200 \ + ${{ inputs.server_args }} \ + 2>&1 > ${{ inputs.log_file }} & + + - name: Wait for Appium server to start + shell: bash + run: | + TIMEOUT_SEC=${{ inputs.timeout }} + INTERVAL_SEC=1 + + start_time=$(date +%s) + while true; do + current_time=$(date +%s) + elapsed=$((current_time - start_time)) + + if nc -z ${{ inputs.host }} ${{ inputs.port }}; then + echo "Appium server is running after $elapsed seconds" + cat ${{ inputs.log_file }} + exit 0 + fi + + if [[ "$elapsed" -ge "$TIMEOUT_SEC" ]]; then + echo "${elapsed} seconds timeout reached: Appium server is NOT running" + exit 1 + fi + + echo "Waiting $elapsed seconds for Appium server to start..." + sleep "$INTERVAL_SEC" + done diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 13a08e874..140328bc4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,17 @@ version: 2 updates: -- package-ecosystem: pip +- package-ecosystem: uv directory: "/" schedule: interval: daily time: "11:00" open-pull-requests-limit: 10 +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + time: "11:00" + open-pull-requests-limit: 10 + commit-message: + prefix: "ci" + include: "scope" diff --git a/.github/issue_template.md b/.github/issue_template.md index 6251abfd0..09aaff213 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -21,4 +21,3 @@ If necessary, describe the problem you have been experiencing in more detail. Create a [GIST](https://gist.github.com) which is a paste of your _full_ Appium logs, and link them here. ## Code To reproduce issue - diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index e049fe833..f5a47a131 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -3,8 +3,6 @@ name: Functional Tests on: # Run by manual at this time workflow_dispatch: - push: - branches: [ master ] pull_request: branches: [ master ] @@ -12,6 +10,11 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +env: + APPIUM_TEST_SERVER_PORT: '4723' + APPIUM_TEST_SERVER_HOST: '127.0.0.1' + PYTHONUNBUFFERED: 1 + jobs: ios_test: strategy: @@ -26,15 +29,16 @@ jobs: # Please make sure the available Xcode versions and iOS versions # on the runner images. https://github.com/actions/runner-images env: - XCODE_VERSION: 16.4 - IOS_VERSION: 18.5 - IPHONE_MODEL: iPhone 16 Plus + XCODE_VERSION: '16.4' + IOS_VERSION: '18.5' + IPHONE_MODEL: 'iPhone 16 Plus' + PREBUILT_WDA_PATH: ${{ github.workspace }}/wda/WebDriverAgentRunner-Runner.app steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version: 'lts/*' @@ -42,43 +46,63 @@ jobs: uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: ${{ env.XCODE_VERSION }} - - run: defaults write com.apple.iphonesimulator PasteboardAutomaticSync -bool false - - uses: futureware-tech/simulator-action@v3 + - name: Install Appium and drivers + run: | + npm install -g appium + appium driver install xcuitest + appium driver run xcuitest download-wda-sim --platform=ios --outdir=$(dirname "$PREBUILT_WDA_PATH") + + - name: Start Appium server + uses: ./.github/actions/setup-appium-server + with: + port: ${{ env.APPIUM_TEST_SERVER_PORT }} + host: ${{ env.APPIUM_TEST_SERVER_HOST }} + server_args: '--relaxed-security' + + - name: Start iOS Simulator UI + run: | + defaults write com.apple.iphonesimulator PasteboardAutomaticSync -bool false + open -Fn "$(xcode-select --print-path)/Applications/Simulator.app" + - name: Prepare iOS simulator + uses: futureware-tech/simulator-action@v5 with: - # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md model: ${{ env.IPHONE_MODEL }} os_version: ${{ env.IOS_VERSION }} + wait_for_boot: true + shutdown_after_job: false - # needed? - - run: brew install ffmpeg + - name: Finalize iOS simulator boot + run: xcrun --sdk iphonesimulator --show-sdk-version - # Start Appium - - run: npm install -g appium - - run: | - appium driver install xcuitest - appium driver run xcuitest build-wda --sdk=${{ env.IOS_VERSION }} --name='${{ env.IPHONE_MODEL }}' - appium plugin install images - appium plugin install execute-driver - nohup appium --use-plugins=images,execute-driver --relaxed-security --log-timestamp --log-no-colors > appium.log & - - - run: | - appium driver run xcuitest download-wda-sim --platform=ios --outdir=${{ github.workspace }}/wda - name: Downloading prebuilt WDA + - name: Set up Python + uses: actions/setup-python@v7 + with: + python-version: 3.14 - - name: Set up Python 3.12 - uses: actions/setup-python@v5 + - name: Cache uv modules + uses: actions/cache@v6 with: - python-version: 3.12 + path: | + ~/.cache/uv + .venv + key: ${{ runner.os }}-uv-shared-${{ hashFiles('**/uv.lock') }} + restore-keys: | + ${{ runner.os }}-uv-shared- - name: Install uv run: make install-uv - name: Run Tests run: | - uv run pytest ${{ matrix.test_targets.target}} --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html + uv run pytest -v ${{ matrix.test_targets.target}} \ + --doctest-modules \ + --junitxml=junit/test-results.xml \ + --cov=com \ + --cov-report=xml \ + --cov-report=html env: - LOCAL_PREBUILT_WDA: ${{ github.workspace }}/wda/WebDriverAgentRunner-Runner.app + LOCAL_PREBUILT_WDA: ${{ env.PREBUILT_WDA_PATH }} - name: Save server output if: ${{ always() }} @@ -103,25 +127,36 @@ jobs: ARCH: x86 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5.7.0 with: distribution: 'temurin' java-version: '17' + - name: Install ffmpeg + run: | + sudo apt-get update + sudo apt-get install -y ffmpeg + - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version: 'lts/*' - # Start Appium - - run: npm install -g appium - - run: | + - name: Install Appium and drivers + run: | + npm install -g appium appium driver install uiautomator2 appium driver install espresso appium plugin install execute-driver - nohup appium --use-plugins=execute-driver --relaxed-security --log-timestamp --log-no-colors 2>&1 > appium.log & + + - name: Start Appium server + uses: ./.github/actions/setup-appium-server + with: + port: ${{ env.APPIUM_TEST_SERVER_PORT }} + host: ${{ env.APPIUM_TEST_SERVER_HOST }} + server_args: '--relaxed-security --use-plugins=execute-driver' - name: Enable KVM group perms run: | @@ -130,14 +165,14 @@ jobs: sudo udevadm trigger --name-match=kvm - name: AVD cache - uses: actions/cache@v3 + uses: actions/cache@v6 id: avd-cache with: path: | ~/.android/avd/* ~/.android/adb* key: avd-${{ env.API_LEVEL }} - - name: create AVD and generate snapshot for caching + - name: Create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' uses: reactivecircus/android-emulator-runner@v2 with: @@ -149,19 +184,29 @@ jobs: disable-animations: false script: echo "Generated AVD snapshot for caching." - - name: Set up Python 3.12 - uses: actions/setup-python@v5 + - name: Set up Python 3.14 + uses: actions/setup-python@v7 with: - python-version: 3.12 + python-version: 3.14 - - name: run tests + - name: Cache uv modules + uses: actions/cache@v6 + with: + path: | + ~/.cache/uv + .venv + key: ${{ runner.os }}-uv-shared-${{ hashFiles('**/uv.lock') }} + restore-keys: | + ${{ runner.os }}-uv-shared- + + - name: Run tests uses: reactivecircus/android-emulator-runner@v2 with: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} script: | make install-uv - uv run pytest ${{ matrix.test_targets.target}} --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html + uv run pytest -v ${{ matrix.test_targets.target}} --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html target: google_apis profile: Nexus 5X disable-spellchecker: true @@ -202,12 +247,13 @@ jobs: IPHONE_MODEL: iPhone 16 FLUTTER_ANDROID_APP: "https://github.com/AppiumTestDistribution/appium-flutter-server/releases/latest/download/app-debug.apk" FLUTTER_IOS_APP: "https://github.com/AppiumTestDistribution/appium-flutter-server/releases/latest/download/ios.zip" + PREBUILT_WDA_PATH: ${{ github.workspace }}/wda/WebDriverAgentRunner-Runner.app steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v5.7.0 if: matrix.e2e-tests == 'flutter-android' with: distribution: 'zulu' @@ -220,25 +266,54 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - - name: Set up Python 3.12 - uses: actions/setup-python@v5 + - name: Set up Python 3.14 + uses: actions/setup-python@v7 with: - python-version: 3.12 + python-version: 3.14 - name: Install Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v7 with: node-version: 'lts/*' - - name: Install Appium - run: npm install --location=global appium@2.19.0 + - name: Select Xcode + if: matrix.e2e-tests == 'flutter-ios' + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: ${{ env.XCODE_VERSION }} - - name: Install Android drivers and Run Appium + - name: Install Appium and drivers if: matrix.e2e-tests == 'flutter-android' run: | - appium driver install uiautomator2@4.2.9 + npm install --location=global appium + appium driver install uiautomator2 appium driver install appium-flutter-integration-driver --source npm - nohup appium --allow-insecure=adb_shell --relaxed-security --log-timestamp --log-no-colors 2>&1 > appium_flutter_android.log & + + - name: Install Appium and drivers + if: matrix.e2e-tests == 'flutter-ios' + run: | + npm install --location=global appium + appium driver install xcuitest + appium driver run xcuitest download-wda-sim --platform=ios --outdir=$(dirname "$PREBUILT_WDA_PATH") + appium driver install appium-flutter-integration-driver --source npm + + - name: Start Appium server + uses: ./.github/actions/setup-appium-server + with: + port: ${{ env.APPIUM_TEST_SERVER_PORT }} + host: ${{ env.APPIUM_TEST_SERVER_HOST }} + server_args: '--relaxed-security' + log_file: appium-${{ matrix.e2e-tests }}.log + + - name: Cache uv modules + uses: actions/cache@v6 + with: + path: | + ~/.cache/uv + .venv + key: ${{ runner.os }}-uv-shared-${{ hashFiles('**/uv.lock') }} + restore-keys: | + ${{ runner.os }}-uv-shared- - name: Run Android tests if: matrix.e2e-tests == 'flutter-android' @@ -247,46 +322,47 @@ jobs: api-level: ${{ env.API_LEVEL }} script: | make install-uv - uv run pytest test/functional/flutter_integration/*_test.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html + uv run pytest -v test/functional/flutter_integration/*_test.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html target: default disable-spellchecker: true disable-animations: true - - name: Save server output - if: always() && matrix.e2e-tests == 'flutter-android' - uses: actions/upload-artifact@master - with: - name: appium-flutter-android.log - path: appium_flutter_android.log - - - name: Select Xcode + - name: Start iOS Simulator UI if: matrix.e2e-tests == 'flutter-ios' - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: ${{ env.XCODE_VERSION }} + run: | + defaults write com.apple.iphonesimulator PasteboardAutomaticSync -bool false + open -Fn "$(xcode-select --print-path)/Applications/Simulator.app" - - uses: futureware-tech/simulator-action@v3 + - uses: futureware-tech/simulator-action@v5 if: matrix.e2e-tests == 'flutter-ios' with: # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md model: ${{ env.IPHONE_MODEL }} os_version: ${{ env.IOS_VERSION }} + wait_for_boot: true + shutdown_after_job: false - - name: install dependencies + - name: Finalize iOS simulator boot if: matrix.e2e-tests == 'flutter-ios' - run: brew install ffmpeg - - - name: Install IOS drivers and Run Appium - if: matrix.e2e-tests == 'flutter-ios' - run: | - appium driver install xcuitest@9.10.5 - appium driver install appium-flutter-integration-driver --source npm - appium driver run xcuitest build-wda - nohup appium --allow-insecure=adb_shell --relaxed-security --log-timestamp --log-no-colors 2>&1 > appium_ios.log & + run: xcrun --sdk iphonesimulator --show-sdk-version - name: Run IOS tests if: matrix.e2e-tests == 'flutter-ios' run: | make install-uv export PLATFORM=ios - uv run pytest test/functional/flutter_integration/*_test.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html + uv run pytest -v test/functional/flutter_integration/*_test.py \ + --doctest-modules \ + --junitxml=junit/test-results.xml \ + --cov=com \ + --cov-report=xml \ + --cov-report=html + env: + LOCAL_PREBUILT_WDA: ${{ env.PREBUILT_WDA_PATH }} + + - name: Save server output + if: ${{ always() }} + uses: actions/upload-artifact@master + with: + name: appium-${{ matrix.e2e-tests }}.log + path: appium-${{ matrix.e2e-tests }}.log diff --git a/.github/workflows/lock-update.yml b/.github/workflows/lock-update.yml index 9d50ac2a4..8af24642e 100644 --- a/.github/workflows/lock-update.yml +++ b/.github/workflows/lock-update.yml @@ -15,17 +15,17 @@ jobs: if: github.actor == 'dependabot[bot]' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: token: ${{ secrets.GITHUB_TOKEN }} ref: ${{ github.head_ref }} - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v7 with: python-version: '3.12' - name: Install uv run: make install-uv - run: uv lock - - uses: stefanzweifel/git-auto-commit-action@v5 + - uses: stefanzweifel/git-auto-commit-action@v7 with: commit_message: "chore: Refresh uv.lock" diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index 51c3a5065..929df1336 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -3,14 +3,8 @@ on: pull_request: types: [opened, edited, synchronize, reopened] - jobs: lint: - name: https://www.conventionalcommits.org - runs-on: ubuntu-latest - steps: - - uses: beemojs/conventional-pr-action@v3 - with: - config-preset: angular - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: appium/appium-workflows/.github/workflows/pr-title.yml@main + with: + config-preset: angular diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..8df3ca7f3 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,50 @@ +name: Release + +on: + workflow_dispatch: + push: + branches: [ master ] + +permissions: + contents: write + id-token: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - name: Set up Python + uses: actions/setup-python@v7 + with: + python-version: '3.12' + + - name: Install uv + run: make install-uv + + - name: Semantic Release Version + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: uv run semantic-release version + + - name: Check if dist directory exists + id: check_dist + run: | + if [ -d "dist" ]; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Publish to PyPI + if: steps.check_dist.outputs.exists == 'true' + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/ + + - name: Publish GitHub Release + if: steps.check_dist.outputs.exists == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: uv run semantic-release publish diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index de0fc07bd..37cfa1624 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -12,13 +12,22 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} + - name: Cache uv modules + uses: actions/cache@v6 + with: + path: | + ~/.cache/uv + .venv + key: ${{ runner.os }}-uv-shared-${{ hashFiles('**/uv.lock') }} + restore-keys: | + ${{ runner.os }}-uv-shared- - name: Install uv run: make install-uv - name: Run Checks diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 17b86e2a6..b40175c99 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,10 +1,15 @@ repos: -- repo: https://github.com/astral-sh/ruff-pre-commit - # Ruff version. - rev: v0.9.0 - hooks: - # Run the linter. - - id: ruff - args: [ --fix ] - # Run the formatter. - - id: ruff-format + - repo: local + hooks: + - id: ruff-check + name: ruff check + entry: uv run ruff check + language: system + types_or: [python, pyi] + args: [--fix, --show-fixes] + + - id: ruff-format + name: ruff format + entry: uv run ruff format + language: system + types_or: [python, pyi] diff --git a/.ruff.toml b/.ruff.toml index 96cebc8fc..46e769858 100644 --- a/.ruff.toml +++ b/.ruff.toml @@ -3,18 +3,17 @@ indent-width = 4 [lint] select = [ - # Pyflakes - "F", - # Pylint - "PL", - # isort - "I", + "F", # Pyflakes + "PL", # Pylint + "I", # isort + "PERF", # perflint + "FURB", # Refurb + "SIM", # Simplify + "UP", # Upgrade ] [lint.per-file-ignores] "__init__.py" = [ - # unused-import - "F401", # import violations "E402" ] @@ -24,7 +23,6 @@ select = [ ] [lint.pylint] - max-args = 6 [format] diff --git a/CHANGELOG.md b/CHANGELOG.md index ef58dcd30..a462457ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,453 @@ +## v6.0.0 (2026-08-08) + +### Breaking Changes + +- Removed legacy Appium endpoint calls from commands which can be replaced with extensions + - This should not affect anything for users who use newer Appium such as Appium v2/3 based drivers + - References: [#1258](https://github.com/appium/python-client/pull/1258), [#1233](https://github.com/appium/python-client/pull/1233), [#1258](https://github.com/appium/python-client/pull/1258), [#1224](https://github.com/appium/python-client/pull/1224), [#1220](https://github.com/appium/python-client/pull/1220), [#1225](https://github.com/appium/python-client/pull/1225), [#1267](https://github.com/appium/python-client/pull/1267) +- Removed CanRememberExtensionPresence used only for the legacy endpoint support [#1269](https://github.com/appium/python-client/pull/1269) + +### Bug Fixes + +- Return int bitmask from set_network_connection + ([#1258](https://github.com/appium/python-client/pull/1258), + [`9097a5a`](https://github.com/appium/python-client/commit/9097a5ab864140b5374d800cf9e60036a1e63a68)) + +### Chores + +- Add a blank line before version v5.2.7 in CHANGELOG.md + ([`dc47ec4`](https://github.com/appium/python-client/commit/dc47ec414f4ae0ffadfdeb02147458f2fe90260a)) + +- Remove setup.py ([#1218](https://github.com/appium/python-client/pull/1218), + [`0f549c3`](https://github.com/appium/python-client/commit/0f549c3d2addbf0c8cc2853731de6e17a85e522f)) + +- Unify ruff version in pyproject.toml and pre-commit-config.yaml + ([#1241](https://github.com/appium/python-client/pull/1241), + [`16a3429`](https://github.com/appium/python-client/commit/16a34294af3fad32fc2bd5578b6331a6bf918f92)) + +- **deps**: Bump gitpython from 3.1.46 to 3.1.47 + ([#1222](https://github.com/appium/python-client/pull/1222), + [`a712427`](https://github.com/appium/python-client/commit/a71242723b1847c53c8d99fc477afa85bff35df4)) + +- **deps**: Bump gitpython from 3.1.54 to 3.1.57 + ([#1270](https://github.com/appium/python-client/pull/1270), + [`ad193d1`](https://github.com/appium/python-client/commit/ad193d168f151d16ca74dc1a0a028138d15b58b0)) + +- **deps**: Bump idna from 3.11 to 3.15 ([#1229](https://github.com/appium/python-client/pull/1229), + [`f268e84`](https://github.com/appium/python-client/commit/f268e84784289c7490a68b4ccd4dbe019e652930)) + +- **deps**: Bump pygments from 2.19.2 to 2.20.0 + ([#1213](https://github.com/appium/python-client/pull/1213), + [`064aeaf`](https://github.com/appium/python-client/commit/064aeaf03b1f287debfdf744c9e6ecf3a07a01c1)) + +- **deps-dev**: Bump ruff from 0.15.11 to 0.15.12 + ([#1223](https://github.com/appium/python-client/pull/1223), + [`15b94bd`](https://github.com/appium/python-client/commit/15b94bd450af92b1abb30850752150edaab52eab)) + +- **deps-dev**: Bump ruff from 0.15.12 to 0.15.13 + ([#1228](https://github.com/appium/python-client/pull/1228), + [`afbface`](https://github.com/appium/python-client/commit/afbface1ea1494d7f0a4bbb6330926b70bd8b216)) + +- **deps-dev**: Bump ruff from 0.15.13 to 0.15.14 + ([#1231](https://github.com/appium/python-client/pull/1231), + [`e374b78`](https://github.com/appium/python-client/commit/e374b78068b6165b68e80c6e0499dff2a2e37da3)) + +- **deps-dev**: Bump ruff from 0.15.14 to 0.15.15 + ([#1232](https://github.com/appium/python-client/pull/1232), + [`2a05afc`](https://github.com/appium/python-client/commit/2a05afce980e5cf4465f9d8705669780962f2469)) + +- **deps-dev**: Bump ruff from 0.15.15 to 0.15.16 + ([#1234](https://github.com/appium/python-client/pull/1234), + [`5389384`](https://github.com/appium/python-client/commit/53893843f75fc66edfe3c71555d1fe3bc9a60249)) + +- **deps-dev**: Bump ruff from 0.15.16 to 0.15.17 + ([#1235](https://github.com/appium/python-client/pull/1235), + [`00325db`](https://github.com/appium/python-client/commit/00325dbcfa29620a818929e69f764ce6fc16cb37)) + +- **deps-dev**: Bump ruff from 0.16.0 to 0.16.1 + ([#1268](https://github.com/appium/python-client/pull/1268), + [`a65dc2b`](https://github.com/appium/python-client/commit/a65dc2b5372dab3cce8ac7db87f9eda45a0342b8)) + +### Continuous Integration + +- Disable auto release to release breaking changes in one release + ([`9034ad6`](https://github.com/appium/python-client/commit/9034ad65517b2659f4df1c8aa82eaa2e848a4814)) + +- **deps**: Bump actions/cache from 5 to 6 + ([#1240](https://github.com/appium/python-client/pull/1240), + [`e4e7a79`](https://github.com/appium/python-client/commit/e4e7a798e281dae431f91cd4f21a682fbed788d8)) + +- **deps**: Bump actions/checkout from 6 to 7 + ([#1237](https://github.com/appium/python-client/pull/1237), + [`c3c844f`](https://github.com/appium/python-client/commit/c3c844f01ace39089be6559c1f84c3fa259fe074)) + +- **deps**: Bump actions/setup-java from 5 to 5.6.0 + ([#1265](https://github.com/appium/python-client/pull/1265), + [`e3cf4f5`](https://github.com/appium/python-client/commit/e3cf4f507976817a23dfc54aaa06cef722e92543)) + +- **deps**: Bump actions/setup-node from 6 to 7 + ([#1250](https://github.com/appium/python-client/pull/1250), + [`48201f7`](https://github.com/appium/python-client/commit/48201f753c80cab0e79bcf7fd64cc2f7d77535ca)) + +- **deps**: Bump actions/setup-python from 6 to 7 + ([#1264](https://github.com/appium/python-client/pull/1264), + [`247bfba`](https://github.com/appium/python-client/commit/247bfbaf39106c79fb347861a354283129767873)) + +- **deps**: Bump gitpython from 3.1.47 to 3.1.54 + ([#1262](https://github.com/appium/python-client/pull/1262), + [`3b0ae42`](https://github.com/appium/python-client/commit/3b0ae42c85930df775c23808fae47cbf8671ce02)) + +- **deps**: Bump requests from 2.32.5 to 2.33.0 + ([#1266](https://github.com/appium/python-client/pull/1266), + [`f119477`](https://github.com/appium/python-client/commit/f119477ec64323bec2d32e107a25bac7f4734c70)) + +- **deps**: Bump selenium from 4.40.0 to 4.46.0 + ([#1251](https://github.com/appium/python-client/pull/1251), + [`37b5118`](https://github.com/appium/python-client/commit/37b51180de2f49deb4dc160b5e3f36879e441d97)) + +- **deps**: Bump setuptools from 80.10.1 to 83.0.0 + ([#1263](https://github.com/appium/python-client/pull/1263), + [`f92311d`](https://github.com/appium/python-client/commit/f92311d26df3b14fcff5cd0ed18d41b5e468d7df)) + +- **deps**: Bump typing-extensions from 4.15.0 to 4.16.0 + ([#1242](https://github.com/appium/python-client/pull/1242), + [`ceb843a`](https://github.com/appium/python-client/commit/ceb843af03ce0158179252d7ed97d8c83d3924a0)) + +- **deps**: Bump urllib3 from 2.6.3 to 2.7.0 + ([#1257](https://github.com/appium/python-client/pull/1257), + [`e155a73`](https://github.com/appium/python-client/commit/e155a736982e9890471b04f2ce8fe016732017d6)) + +- **deps-dev**: Bump mypy from 1.19.1 to 2.3.0 + ([#1253](https://github.com/appium/python-client/pull/1253), + [`21f73eb`](https://github.com/appium/python-client/commit/21f73ebbb3f0ff6ae3145c58ccae1433a2a1c03a)) + +- **deps-dev**: Bump pre-commit from 4.5.1 to 4.6.0 + ([#1252](https://github.com/appium/python-client/pull/1252), + [`8480f9c`](https://github.com/appium/python-client/commit/8480f9c817605d16202f223230f8ff9e3c643ce7)) + +- **deps-dev**: Bump pre-commit from 4.6.0 to 4.6.1 + ([#1259](https://github.com/appium/python-client/pull/1259), + [`3439428`](https://github.com/appium/python-client/commit/34394283e9befc559e63fe470a20f361e975e576)) + +- **deps-dev**: Bump pytest from 8.4.2 to 9.1.1 + ([#1255](https://github.com/appium/python-client/pull/1255), + [`9e76329`](https://github.com/appium/python-client/commit/9e76329cd0a4d2924512449c8c6210239a64b87a)) + +- **deps-dev**: Bump python-semantic-release from 10.5.3 to 10.6.1 + ([#1244](https://github.com/appium/python-client/pull/1244), + [`0c14656`](https://github.com/appium/python-client/commit/0c146565685436bd32ba729012bc650f87b09f71)) + +- **deps-dev**: Bump ruff from 0.15.17 to 0.15.19 + ([#1238](https://github.com/appium/python-client/pull/1238), + [`b989a00`](https://github.com/appium/python-client/commit/b989a003a8dc8f0e51c0e3240c316fac87ffcc9a)) + +- **deps-dev**: Bump ruff from 0.15.19 to 0.15.20 + ([#1239](https://github.com/appium/python-client/pull/1239), + [`ef6b6f2`](https://github.com/appium/python-client/commit/ef6b6f2824ebe095ff3b50ae1e9613be90eabdb4)) + +- **deps-dev**: Bump ruff from 0.15.20 to 0.15.21 + ([#1245](https://github.com/appium/python-client/pull/1245), + [`bafdbf7`](https://github.com/appium/python-client/commit/bafdbf72ddfba0fc2d69841938462297b4b26bff)) + +- **deps-dev**: Bump ruff from 0.15.21 to 0.15.22 + ([#1249](https://github.com/appium/python-client/pull/1249), + [`136b1e4`](https://github.com/appium/python-client/commit/136b1e46abf1ee7c57d4ab29113e20424549cc7c)) + +- **deps-dev**: Bump ruff from 0.15.22 to 0.16.0 + ([#1261](https://github.com/appium/python-client/pull/1261), + [`7c741e6`](https://github.com/appium/python-client/commit/7c741e68a05dad0ee4a2d7adf932aee2a00b0fa7)) + +- **deps-dev**: Bump types-python-dateutil + ([#1254](https://github.com/appium/python-client/pull/1254), + [`c7c1240`](https://github.com/appium/python-client/commit/c7c1240a38594508e2814217626a70ce379e8df0)) + +### Documentation + +- Drop appiumpro links as the top domain no longer maintained + ([`34111e0`](https://github.com/appium/python-client/commit/34111e02d6fa1ce5466335363f490ff671e876d5)) + +- Move http -> https in Homepage url ([#1256](https://github.com/appium/python-client/pull/1256), + [`f1d0f1c`](https://github.com/appium/python-client/commit/f1d0f1c6aee4e4257e6f2b1d9c6af6e903c2a881)) + +### Features + +- Drop CanRememberExtensionPresence ([#1269](https://github.com/appium/python-client/pull/1269), + [`e33851f`](https://github.com/appium/python-client/commit/e33851fcfae8f3aa96b1bd4a067ca5cf8a6d9c7c)) + +### Refactoring + +- Network extension to remove legacy command fallbacks + ([#1258](https://github.com/appium/python-client/pull/1258), + [`9097a5a`](https://github.com/appium/python-client/commit/9097a5ab864140b5374d800cf9e60036a1e63a68)) + +- Remove legacy command fallbacks in Applications extension + ([#1233](https://github.com/appium/python-client/pull/1233), + [`4707ff7`](https://github.com/appium/python-client/commit/4707ff7a9a362b4ff39b85a600432d8cfb3bc4a5)) + +- Remove legacy fallback for `mobile: getAppStrings` + ([`dc47ec4`](https://github.com/appium/python-client/commit/dc47ec414f4ae0ffadfdeb02147458f2fe90260a)) + +- Remove legacy fallback for network commands + ([#1258](https://github.com/appium/python-client/pull/1258), + [`9097a5a`](https://github.com/appium/python-client/commit/9097a5ab864140b5374d800cf9e60036a1e63a68)) + +- Remove legacy fallback in toggle_location_services + ([#1224](https://github.com/appium/python-client/pull/1224), + [`ed9eaff`](https://github.com/appium/python-client/commit/ed9eaff74dba57f9c700674bfde35bdca4096529)) + +- Remove legacy fallback logic for android extensions + ([#1220](https://github.com/appium/python-client/pull/1220), + [`23278d9`](https://github.com/appium/python-client/commit/23278d9571a5c301dfa607d6dd91172fb18e9b02)) + +- Remove legacy gsm fallback logic ([#1225](https://github.com/appium/python-client/pull/1225), + [`3b91340`](https://github.com/appium/python-client/commit/3b91340f0080003c82dbf22ec6e4de4c14594bdf)) + +- Remove legacy implementation ([#1267](https://github.com/appium/python-client/pull/1267), + [`5b7f352`](https://github.com/appium/python-client/commit/5b7f3527f7dcb2886c3af6ba5fa36d471b6aeb5b)) + +### Testing + +- Remove (object) inheritance to align with pytest style (#644) + ([#1246](https://github.com/appium/python-client/pull/1246), + [`d9b5cc9`](https://github.com/appium/python-client/commit/d9b5cc98c11ec188bf4578c65ee298462dfce8c5)) + + +## v5.3.1 (2026-04-19) + +### Bug Fixes + +- Replace assert with ValueError for state validation + ([#1219](https://github.com/appium/python-client/pull/1219), + [`2193837`](https://github.com/appium/python-client/commit/2193837fc0af579231f08315431c6a2347bc2b65)) + +### Chores + +- **deps-dev**: Bump ruff from 0.15.10 to 0.15.11 + ([#1217](https://github.com/appium/python-client/pull/1217), + [`30dad44`](https://github.com/appium/python-client/commit/30dad44a9ab991c14134119b876ca80c21d10e88)) + +- **deps-dev**: Bump ruff from 0.15.7 to 0.15.8 + ([#1210](https://github.com/appium/python-client/pull/1210), + [`7181b20`](https://github.com/appium/python-client/commit/7181b201d0cd94561fe5f07e8bcb0bf03b8ca0e0)) + +- **deps-dev**: Bump ruff from 0.15.8 to 0.15.9 + ([#1214](https://github.com/appium/python-client/pull/1214), + [`21fdecb`](https://github.com/appium/python-client/commit/21fdecbdf975515087e4c88e04c3356b288f5ac6)) + +- **deps-dev**: Bump ruff from 0.15.9 to 0.15.10 + ([#1216](https://github.com/appium/python-client/pull/1216), + [`9016e94`](https://github.com/appium/python-client/commit/9016e9431dd9e8c0218e1499c516dcf70642b7e4)) + + +## v5.3.0 (2026-03-28) + +### Bug Fixes + +- **test**: Simplify assertion for AndroidKeyMetastate in test_has_some_metastates + ([#1211](https://github.com/appium/python-client/pull/1211), + [`ad8c5c9`](https://github.com/appium/python-client/commit/ad8c5c9ce33e85d6b417f2545df83b32e56c7fd0)) + +### Chores + +- **deps-dev**: Bump pytest-cov from 7.0.0 to 7.1.0 + ([#1209](https://github.com/appium/python-client/pull/1209), + [`8466c27`](https://github.com/appium/python-client/commit/8466c27b8759fc18169a48d7f7ae49cc33fce0a9)) + +- **deps-dev**: Bump ruff from 0.15.4 to 0.15.5 + ([#1205](https://github.com/appium/python-client/pull/1205), + [`628a731`](https://github.com/appium/python-client/commit/628a73111c315860754a7e0cc88f3b68917f3fc2)) + +- **deps-dev**: Bump ruff from 0.15.5 to 0.15.6 + ([#1207](https://github.com/appium/python-client/pull/1207), + [`9b81d2a`](https://github.com/appium/python-client/commit/9b81d2a42fbca4d4c4c4f2d54ce183c627479f85)) + +- **deps-dev**: Bump ruff from 0.15.6 to 0.15.7 + ([#1208](https://github.com/appium/python-client/pull/1208), + [`339fff9`](https://github.com/appium/python-client/commit/339fff93d0ac7472140e7869790e203f5160ad60)) + +### Continuous Integration + +- **deps**: Bump futureware-tech/simulator-action from 4 to 5 + ([#1206](https://github.com/appium/python-client/pull/1206), + [`a3c13dc`](https://github.com/appium/python-client/commit/a3c13dc98e9d50fb19bd1e37bdbdf86887587144)) + +### Features + +- Add AndroidKeyMetastate class for keyboard metastate constants + ([#1211](https://github.com/appium/python-client/pull/1211), + [`ad8c5c9`](https://github.com/appium/python-client/commit/ad8c5c9ce33e85d6b417f2545df83b32e56c7fd0)) + +- **android**: Add AndroidKeyMetastate class for keyboard metastate constants + ([#1211](https://github.com/appium/python-client/pull/1211), + [`ad8c5c9`](https://github.com/appium/python-client/commit/ad8c5c9ce33e85d6b417f2545df83b32e56c7fd0)) + + +## v5.2.7 (2026-03-05) + +### Bug Fixes + +- Fix type checker errors for pyright ([#1203](https://github.com/appium/python-client/pull/1203), + [`cd4699a`](https://github.com/appium/python-client/commit/cd4699a786fe65edd0ce525eadf36d944c01c2d5)) + +### Chores + +- Modify metadata ([#1199](https://github.com/appium/python-client/pull/1199), + [`e993461`](https://github.com/appium/python-client/commit/e9934619131f757e51faf484bfdea3ca491b2ecf)) + +- Remove issac's email as invalid one ([#1199](https://github.com/appium/python-client/pull/1199), + [`e993461`](https://github.com/appium/python-client/commit/e9934619131f757e51faf484bfdea3ca491b2ecf)) + +- **deps-dev**: Bump ruff from 0.15.0 to 0.15.1 + ([#1200](https://github.com/appium/python-client/pull/1200), + [`13bf27b`](https://github.com/appium/python-client/commit/13bf27bc3247221fab9fdf173e30ba3b998dd9fa)) + +- **deps-dev**: Bump ruff from 0.15.1 to 0.15.2 + ([#1201](https://github.com/appium/python-client/pull/1201), + [`3c33eae`](https://github.com/appium/python-client/commit/3c33eae0ed5e5c2c555fd02e4a011c4377a1103d)) + +- **deps-dev**: Bump ruff from 0.15.2 to 0.15.4 + ([#1202](https://github.com/appium/python-client/pull/1202), + [`2a14455`](https://github.com/appium/python-client/commit/2a14455f0e85f99f6a520783b4e95dfcfc5abdb5)) + +### Continuous Integration + +- Enable auto release to master + ([`52203a4`](https://github.com/appium/python-client/commit/52203a4613e3a3694e1cba5c34a45fb7b2e2fda4)) + +- Update the trigger ([#1199](https://github.com/appium/python-client/pull/1199), + [`e993461`](https://github.com/appium/python-client/commit/e9934619131f757e51faf484bfdea3ca491b2ecf)) + + +## v5.2.6 (2026-02-12) + +### Bug Fixes + +- Update readme and to kick a release to test out auto release + ([`a4cda69`](https://github.com/appium/python-client/commit/a4cda696bc872f3879a2e7d36df852471f672211)) + +### Chores + +- **deps-dev**: Bump ruff from 0.14.14 to 0.15.0 + ([#1198](https://github.com/appium/python-client/pull/1198), + [`1114b10`](https://github.com/appium/python-client/commit/1114b1033865cf0112da0877f56f68e910daac28)) + +- **deps-dev**: Bump types-python-dateutil + ([#1197](https://github.com/appium/python-client/pull/1197), + [`ae2802e`](https://github.com/appium/python-client/commit/ae2802ef16d4337e81dd01cf6dcc4360a60a8509)) + +### Continuous Integration + +- Add skip to publish if not package was made + ([`bb8b4b3`](https://github.com/appium/python-client/commit/bb8b4b35cd3ece54c857568005168b9d0b6e19a8)) + +- Create automatic release action ([#1196](https://github.com/appium/python-client/pull/1196), + [`208c35c`](https://github.com/appium/python-client/commit/208c35c27da10b78bfd346c3ecdd34d78b920473)) + + +## v5.2.5 (2026-01-24) + +### Chores + +- Add a few new caps in the standard ([#1175](https://github.com/appium/python-client/pull/1175), + [`b22b031`](https://github.com/appium/python-client/commit/b22b0316b18e551695344d11e25e940a7f7ec297)) + +- Enable dependabot for uv ([#1181](https://github.com/appium/python-client/pull/1181), + [`fd138de`](https://github.com/appium/python-client/commit/fd138deb519b5ed7cd2a4a80a639294ec8b42ad4)) + +- Update iOS e2e tests ([#1178](https://github.com/appium/python-client/pull/1178), + [`3677e0c`](https://github.com/appium/python-client/commit/3677e0c3e347a457f3f72b204b0644403725be3b)) + +- **deps**: Bump actions/cache from 3 to 4 + ([#1184](https://github.com/appium/python-client/pull/1184), + [`936e146`](https://github.com/appium/python-client/commit/936e146c05216fe1c620efb7c5e34892ae7e7dcc)) + +- **deps**: Bump actions/cache from 4 to 5 + ([#1191](https://github.com/appium/python-client/pull/1191), + [`aa41b80`](https://github.com/appium/python-client/commit/aa41b80ebfd6c05f3f5b45dbc66ec41b12200040)) + +- **deps**: Bump actions/checkout from 4 to 6 + ([#1186](https://github.com/appium/python-client/pull/1186), + [`7ce850b`](https://github.com/appium/python-client/commit/7ce850bfff817a748dc63ea27c00774c333e76c6)) + +- **deps**: Bump actions/setup-java from 4 to 5 + ([#1183](https://github.com/appium/python-client/pull/1183), + [`91e1855`](https://github.com/appium/python-client/commit/91e18558f78f048a423ea69ededea97596685abe)) + +- **deps**: Bump actions/setup-node from 4 to 6 + ([#1188](https://github.com/appium/python-client/pull/1188), + [`3f8eeec`](https://github.com/appium/python-client/commit/3f8eeec1f499efbe7e82007b22bed7d8a687a316)) + +- **deps**: Bump actions/setup-python from 4 to 6 + ([#1187](https://github.com/appium/python-client/pull/1187), + [`7708ebe`](https://github.com/appium/python-client/commit/7708ebe35761969cb5fad80e9a1a709553a119d1)) + +- **deps**: Bump selenium from 4.33.0 to 4.36.0 + ([#1182](https://github.com/appium/python-client/pull/1182), + [`64c0119`](https://github.com/appium/python-client/commit/64c011926cf804dc8edf27e7c15ffeb2568a45f5)) + +- **deps**: Bump stefanzweifel/git-auto-commit-action from 5 to 7 + ([#1185](https://github.com/appium/python-client/pull/1185), + [`8389732`](https://github.com/appium/python-client/commit/8389732af5392254325a1616a00ea42df22b6bbe)) + +- **deps-dev**: Bump pytest-cov from 6.3.0 to 7.0.0 + ([#1194](https://github.com/appium/python-client/pull/1194), + [`32aca30`](https://github.com/appium/python-client/commit/32aca304057ee68bb2f1a3c0495054d245e4b955)) + +- **deps-dev**: Bump python-semantic-release from 10.3.2 to 10.5.3 + ([#1195](https://github.com/appium/python-client/pull/1195), + [`4844534`](https://github.com/appium/python-client/commit/48445348e313f6d256bdee5b9229772e87674470)) + +### Continuous Integration + +- Add commit message configuration for Dependabot + ([`b68fa61`](https://github.com/appium/python-client/commit/b68fa6158e7c1f7df5479b50af50b937b1d2511d)) + +- Add GitHub Actions to Dependabot configuration + ([`c2edb68`](https://github.com/appium/python-client/commit/c2edb6874da805f8a4e7ba345f31303a51ba4fb6)) + +- Use py 3.14 ([#1193](https://github.com/appium/python-client/pull/1193), + [`3bb2021`](https://github.com/appium/python-client/commit/3bb20212f67cdbe73d72ff8ff9541a5f57cc8393)) + +- Use the central repo's workflow + ([`e59b853`](https://github.com/appium/python-client/commit/e59b853497ae04706137cf252bfa3b92e6a1e229)) + +- Use the latest appium flutter integration driver on CI + ([#1176](https://github.com/appium/python-client/pull/1176), + [`f61c059`](https://github.com/appium/python-client/commit/f61c059d189f19e01ca6bd11670e6d07c550ec31)) + +### Documentation + +- Clean up CHANGELOG by removing old sections + ([`d4f3e16`](https://github.com/appium/python-client/commit/d4f3e16d33cdc22651e99f1f161ff8e79f78328e)) + +- Fix the units for bitRate value + ([`4634378`](https://github.com/appium/python-client/commit/4634378e8e1fe78b962b0d5280a6bf1b05b9b15d)) + +### Testing + +- Fix accidental missing deps + ([`b04f65e`](https://github.com/appium/python-client/commit/b04f65e58ca7d86bc3b5a2cf2d3a8f61dd225f81)) + +- Update Android tests to the canonical pytest format + ([#1180](https://github.com/appium/python-client/pull/1180), + [`b9564c7`](https://github.com/appium/python-client/commit/b9564c78bc22d1fc4b0e345199c9ede7584ad1c3)) + +- Update flutter tests to canonic pytest format + ([#1179](https://github.com/appium/python-client/pull/1179), + [`ed27b1f`](https://github.com/appium/python-client/commit/ed27b1fad14467b15779abb2942627373977f243)) + + +## v5.2.4 (2025-09-11) + +### Chores + +- Add an error handling in _adjust_image_payload + ([#1172](https://github.com/appium/python-client/pull/1172), + [`dc301ec`](https://github.com/appium/python-client/commit/dc301ec5303f6d5fa6af0ec4370d1ffe88ef1f1d)) + ## v5.2.3 (2025-09-09) ### Bug Fixes diff --git a/Makefile b/Makefile index ad2c96828..4ed823f49 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ install-uv: .PHONY: sync-dev sync-dev: - uv sync + uv sync --dev .PHONY: unittest unittest: ## Run unittest diff --git a/README.md b/README.md index ca14bac9d..f0a4ae250 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ download and unarchive the source tarball (Appium-Python-Client-X.X.tar.gz). ```shell tar -xvf Appium-Python-Client-X.X.tar.gz cd Appium-Python-Client-X.X - python setup.py install + pip install . ``` 3. Install from source via [GitHub](https://github.com/appium/python-client). @@ -34,22 +34,23 @@ download and unarchive the source tarball (Appium-Python-Client-X.X.tar.gz). ```shell git clone git@github.com:appium/python-client.git cd python-client - python setup.py install + pip install . ``` ## Compatibility Matrix -|Appium Python Client| Selenium binding| Python version | -|----|----|----| -|`5.1.1`+|`4.26.0`+ | 3.9+ | -|`4.5.0` - `5.1.0`|`4.26.0` - `4.31.0` | 3.9+ | -|`4.3.0` - `4.4.0`|`4.26.0` - `4.31.0` | 3.8+ | -|`3.0.0` - `4.2.1` |`4.12.0` - `4.25.0` | 3.8+ | -|`2.10.0` - `2.11.1` |`4.1.0` - `4.11.2` | 3.7+ | -|`2.2.0` - `2.9.0` |`4.1.0` - `4.9.0` | 3.7+ | -|`2.0.0` - `2.1.4` |`4.0.0` | 3.7+ | -|`1.0.0` - `1.3.0` |`3.x`| 3.7+ | -|`0.52` and below|`3.x`| 2.7, 3.4 - 3.7 | +| Appium Python Client | Selenium binding | Python version | +|----------------------|---------------------|----------------| +| `6.0.0`+ | `4.37.0`+ | 3.10+ | +| `5.1.1` - `5.3.1` | `4.26.0` - `4.46.0` | 3.9+ | +| `4.5.0` - `5.1.0` | `4.26.0` - `4.31.0` | 3.9+ | +| `4.3.0` - `4.4.0` | `4.26.0` - `4.31.0` | 3.8+ | +| `3.0.0` - `4.2.1` | `4.12.0` - `4.25.0` | 3.8+ | +| `2.10.0` - `2.11.1` | `4.1.0` - `4.11.2` | 3.7+ | +| `2.2.0` - `2.9.0` | `4.1.0` - `4.9.0` | 3.7+ | +| `2.0.0` - `2.1.4` | `4.0.0` | 3.7+ | +| `1.0.0` - `1.3.0` | `3.x` | 3.7+ | +| `0.52` and below | `3.x` | 2.7, 3.4 - 3.7 | The Appium Python Client depends on [Selenium Python binding](https://pypi.org/project/selenium/), thus the Selenium Python binding update might affect the Appium Python Client behavior. @@ -71,21 +72,19 @@ For example, some changes in the Selenium binding could break the Appium client. options=UiAutomator2Options().load_capabilities(desired_caps), direct_connection=True, keep_alive=False, - strict_ssl=False + strict_ssl=False, ) # after from appium.webdriver.client_config import AppiumClientConfig + client_config = AppiumClientConfig( remote_server_addr=SERVER_URL_BASE, direct_connection=True, keep_alive=False, ignore_certificates=True, ) - driver = webdriver.Remote( - options=UiAutomator2Options().load_capabilities(desired_caps), - client_config=client_config - ) + driver = webdriver.Remote(options=UiAutomator2Options().load_capabilities(desired_caps), client_config=client_config) ``` - Note that you can keep using `webdriver.Remote(url, options=options, client_config=client_config)` format as well. In such case the `remote_server_addr` argument of `AppiumClientConfig` constructor would have priority over the `url` argument of `webdriver.Remote` constructor. @@ -97,8 +96,6 @@ For example, some changes in the Selenium binding could break the Appium client. - [appium/webdriver/extensions/action_helpers.py](appium/webdriver/extensions/action_helpers.py) - https://www.selenium.dev/documentation/webdriver/actions_api/ - https://www.youtube.com/watch?v=oAJ7jwMNFVU - - https://appiumpro.com/editions/30-ios-specific-touch-action-methods - - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api - Deprecated `AppiumBy.WINDOWS_UI_AUTOMATION`, which has no usage right now. ### Quick migration guide from v2 to v3 @@ -140,7 +137,7 @@ from selenium.webdriver.common.actions.pointer_input import PointerInput actions = ActionChains(driver) # override as 'touch' pointer action -actions.w3c_actions = ActionBuilder(driver, mouse=PointerInput(interaction.POINTER_TOUCH, "touch")) +actions.w3c_actions = ActionBuilder(driver, mouse=PointerInput(interaction.POINTER_TOUCH, 'touch')) actions.w3c_actions.pointer_action.move_to_location(start_x, start_y) actions.w3c_actions.pointer_action.pointer_down() actions.w3c_actions.pointer_action.pause(2) @@ -175,6 +172,7 @@ environment: import pytest from appium import webdriver + # Options are only available since client version 2.3.0 # If you use an older client then switch to desired_capabilities # instead: https://github.com/appium/python-client/pull/720 @@ -202,7 +200,7 @@ def appium_service(): service.stop() -def create_ios_driver(custom_opts = None): +def create_ios_driver(custom_opts=None): options = XCUITestOptions() options.platformVersion = '13.4' options.udid = '123456789ABC' @@ -212,7 +210,7 @@ def create_ios_driver(custom_opts = None): return webdriver.Remote(f'http://{APPIUM_HOST}:{APPIUM_PORT}', options=options) -def create_android_driver(custom_opts = None): +def create_android_driver(custom_opts=None): options = UiAutomator2Options() options.platformVersion = '10' options.udid = '123456789ABC' @@ -251,9 +249,7 @@ def android_driver(): def test_ios_click(appium_service, ios_driver_factory): # Usage of the context manager ensures the driver session is closed properly # after the test completes. Otherwise, make sure to call `driver.quit()` on teardown. - with ios_driver_factory({ - 'appium:app': '/path/to/app/UICatalog.app.zip' - }) as driver: + with ios_driver_factory({'appium:app': '/path/to/app/UICatalog.app.zip'}) as driver: el = driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value='item') el.click() @@ -261,10 +257,12 @@ def test_ios_click(appium_service, ios_driver_factory): def test_android_click(appium_service, android_driver_factory): # Usage of the context manager ensures the driver session is closed properly # after the test completes. Otherwise, make sure to call `driver.quit()` on teardown. - with android_driver_factory({ - 'appium:app': '/path/to/app/test-app.apk', - 'appium:udid': '567890', - }) as driver: + with android_driver_factory( + { + 'appium:app': '/path/to/app/test-app.apk', + 'appium:udid': '567890', + } + ) as driver: el = driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value='item') el.click() ``` @@ -302,6 +300,7 @@ Then python client will switch its endpoint to the one specified by the values o ```python from appium import webdriver + # Options are only available since client version 2.3.0 # If you use an older client then switch to desired_capabilities # instead: https://github.com/appium/python-client/pull/720 @@ -310,22 +309,21 @@ from appium.webdriver.client_config import AppiumClientConfig # load_capabilities API could be used to # load options mapping stored in a dictionary -options = XCUITestOptions().load_capabilities({ - 'platformVersion': '13.4', - 'deviceName': 'iPhone Simulator', - 'app': '/full/path/to/app/UICatalog.app.zip', -}) - -client_config = AppiumClientConfig( - remote_server_addr='http://127.0.0.1:4723', - direct_connection=True +options = XCUITestOptions().load_capabilities( + { + 'platformVersion': '13.4', + 'deviceName': 'iPhone Simulator', + 'app': '/full/path/to/app/UICatalog.app.zip', + } ) +client_config = AppiumClientConfig(remote_server_addr='http://127.0.0.1:4723', direct_connection=True) + driver = webdriver.Remote( # Appium1 points to http://127.0.0.1:4723/wd/hub by default 'http://127.0.0.1:4723', options=options, - client_config=client_config + client_config=client_config, ) ``` @@ -335,6 +333,7 @@ driver = webdriver.Remote( ```python from appium import webdriver + # Options are only available since client version 2.3.0 # If you use an older client then switch to desired_capabilities # instead: https://github.com/appium/python-client/pull/720 @@ -359,10 +358,7 @@ from appium import webdriver from selenium.webdriver.remote.client_config import ClientConfig -client_config = ClientConfig( - remote_server_addr='http://127.0.0.1:4723', - ignore_certificates=True -) +client_config = ClientConfig(remote_server_addr='http://127.0.0.1:4723', ignore_certificates=True) driver = webdriver.Remote(client_config.remote_server_addr, options=options, client_config=client_config) ``` @@ -380,12 +376,9 @@ import urllib3 from appium.webdriver.appium_connection import AppiumConnection # Retry connection error up to 3 times. -init_args_for_pool_manage = { - 'retries': urllib3.util.retry.Retry(total=3, connect=3, read=False) -} +init_args_for_pool_manage = {'retries': urllib3.util.retry.Retry(total=3, connect=3, read=False)} appium_executor = AppiumConnection( - remote_server_addr='http://127.0.0.1:4723', - init_args_for_pool_manage=init_args_for_pool_manage + remote_server_addr='http://127.0.0.1:4723', init_args_for_pool_manage=init_args_for_pool_manage ) options = XCUITestOptions() @@ -404,19 +397,22 @@ from appium.options.ios import XCUITestOptions from appium.webdriver.appium_connection import AppiumConnection + class CustomAppiumConnection(AppiumConnection): # Can add your own methods for the custom class pass + custom_executor = CustomAppiumConnection(remote_server_addr='http://127.0.0.1:4723') -options = XCUITestOptions().load_capabilities({ - 'platformVersion': '13.4', - 'deviceName': 'iPhone Simulator', - 'app': '/full/path/to/app/UICatalog.app.zip', -}) +options = XCUITestOptions().load_capabilities( + { + 'platformVersion': '13.4', + 'deviceName': 'iPhone Simulator', + 'app': '/full/path/to/app/UICatalog.app.zip', + } +) driver = webdriver.Remote(custom_executor, options=options) - ``` The `AppiumConnection` can set `selenium.webdriver.remote.client_config.ClientConfig` as well. @@ -527,9 +523,7 @@ uv run pytest -n 2 test/functional/ios/search_context/find_by_ios_class_chain_te ## Release -Follow the below steps. - -Set `GH_TOKEN` env var to update the GitHub contents. +In case you need to release a version manually. ```bash rm -rf dist diff --git a/appium/common/helper.py b/appium/common/helper.py index 1565b96e9..821b7c9f8 100644 --- a/appium/common/helper.py +++ b/appium/common/helper.py @@ -13,12 +13,12 @@ # limitations under the License. import base64 -from typing import Any, Dict +from typing import Any from appium import version as appium_version -def extract_const_attributes(cls: type) -> Dict[str, Any]: +def extract_const_attributes(cls: type) -> dict[str, Any]: """Return dict with constants attributes and values in the class(e.g. {'VAL1': 1, 'VAL2': 2}) Args: diff --git a/appium/options/android/__init__.py b/appium/options/android/__init__.py index 8926c5a87..e4ab2bd1c 100644 --- a/appium/options/android/__init__.py +++ b/appium/options/android/__init__.py @@ -1,2 +1,4 @@ from .espresso.base import EspressoOptions from .uiautomator2.base import UiAutomator2Options + +__all__ = ['EspressoOptions', 'UiAutomator2Options'] diff --git a/appium/options/android/common/adb/adb_exec_timeout_option.py b/appium/options/android/common/adb/adb_exec_timeout_option.py index f0ea5b802..f89b140a6 100644 --- a/appium/options/android/common/adb/adb_exec_timeout_option.py +++ b/appium/options/android/common/adb/adb_exec_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class AdbExecTimeoutOption(SupportsCapabilities): @property - def adb_exec_timeout(self) -> Optional[timedelta]: + def adb_exec_timeout(self) -> timedelta | None: """ Maximum time to wait until single ADB command is executed. """ @@ -33,7 +32,7 @@ def adb_exec_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @adb_exec_timeout.setter - def adb_exec_timeout(self, value: Union[timedelta, int]) -> None: + def adb_exec_timeout(self, value: timedelta | int) -> None: """ Maximum time to wait until single ADB command is executed. 20000 ms by default. diff --git a/appium/options/android/common/adb/adb_port_option.py b/appium/options/android/common/adb/adb_port_option.py index 4685c7a0f..515d0ae6a 100644 --- a/appium/options/android/common/adb/adb_port_option.py +++ b/appium/options/android/common/adb/adb_port_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AdbPortOption(SupportsCapabilities): @property - def adb_port(self) -> Optional[int]: + def adb_port(self) -> int | None: """ Number of the port where ADB is running. """ diff --git a/appium/options/android/common/adb/allow_delay_adb_option.py b/appium/options/android/common/adb/allow_delay_adb_option.py index cafd6ff3c..578552699 100644 --- a/appium/options/android/common/adb/allow_delay_adb_option.py +++ b/appium/options/android/common/adb/allow_delay_adb_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AllowDelayAdbOption(SupportsCapabilities): @property - def allow_delay_adb(self) -> Optional[bool]: + def allow_delay_adb(self) -> bool | None: """ Whether to prevent the emulator to use -delay-adb feature. """ diff --git a/appium/options/android/common/adb/build_tools_version_option.py b/appium/options/android/common/adb/build_tools_version_option.py index a5cd96c71..6c1172eac 100644 --- a/appium/options/android/common/adb/build_tools_version_option.py +++ b/appium/options/android/common/adb/build_tools_version_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class BuildToolsVersionOption(SupportsCapabilities): @property - def build_tools_version(self) -> Optional[str]: + def build_tools_version(self) -> str | None: """ Version of Android build tools to use. """ diff --git a/appium/options/android/common/adb/clear_device_logs_on_start_option.py b/appium/options/android/common/adb/clear_device_logs_on_start_option.py index 050cc6a7d..42212dc6a 100644 --- a/appium/options/android/common/adb/clear_device_logs_on_start_option.py +++ b/appium/options/android/common/adb/clear_device_logs_on_start_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ClearDeviceLogsOnStartOption(SupportsCapabilities): @property - def clear_device_logs_on_start(self) -> Optional[bool]: + def clear_device_logs_on_start(self) -> bool | None: """ Makes the driver to delete all the existing logs in the device buffer before starting a new test. diff --git a/appium/options/android/common/adb/ignore_hidden_api_policy_error_option.py b/appium/options/android/common/adb/ignore_hidden_api_policy_error_option.py index 4813ed246..6f77685a7 100644 --- a/appium/options/android/common/adb/ignore_hidden_api_policy_error_option.py +++ b/appium/options/android/common/adb/ignore_hidden_api_policy_error_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class IgnoreHiddenApiPolicyErrorOption(SupportsCapabilities): @property - def ignore_hidden_api_policy_error(self) -> Optional[bool]: + def ignore_hidden_api_policy_error(self) -> bool | None: """ Whether to ignore a failure while changing hidden API access policies. """ diff --git a/appium/options/android/common/adb/logcat_filter_specs_option.py b/appium/options/android/common/adb/logcat_filter_specs_option.py index 8a464d350..16b9dd97c 100644 --- a/appium/options/android/common/adb/logcat_filter_specs_option.py +++ b/appium/options/android/common/adb/logcat_filter_specs_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class LogcatFilterSpecsOption(SupportsCapabilities): @property - def logcat_filter_specs(self) -> Optional[str]: + def logcat_filter_specs(self) -> str | None: """ Logcat filter format. """ diff --git a/appium/options/android/common/adb/logcat_format_option.py b/appium/options/android/common/adb/logcat_format_option.py index 363a6f5a7..74ba8fcfe 100644 --- a/appium/options/android/common/adb/logcat_format_option.py +++ b/appium/options/android/common/adb/logcat_format_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class LogcatFormatOption(SupportsCapabilities): @property - def logcat_format(self) -> Optional[str]: + def logcat_format(self) -> str | None: """ Log print format. """ diff --git a/appium/options/android/common/adb/mock_location_app_option.py b/appium/options/android/common/adb/mock_location_app_option.py index d263ea0e6..aa919ade5 100644 --- a/appium/options/android/common/adb/mock_location_app_option.py +++ b/appium/options/android/common/adb/mock_location_app_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class MockLocationAppOption(SupportsCapabilities): @property - def mock_location_app(self) -> Optional[str]: + def mock_location_app(self) -> str | None: """ Identifier of the app, which is used as a system mock location provider. """ diff --git a/appium/options/android/common/adb/remote_adb_host_option.py b/appium/options/android/common/adb/remote_adb_host_option.py index 1656e9bd5..3a7940565 100644 --- a/appium/options/android/common/adb/remote_adb_host_option.py +++ b/appium/options/android/common/adb/remote_adb_host_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class RemoteAdbHostOption(SupportsCapabilities): @property - def remote_adb_host(self) -> Optional[str]: + def remote_adb_host(self) -> str | None: """ Address of the host where ADB is running. """ diff --git a/appium/options/android/common/adb/skip_logcat_capture_option.py b/appium/options/android/common/adb/skip_logcat_capture_option.py index 2f9f9074f..a6998ca11 100644 --- a/appium/options/android/common/adb/skip_logcat_capture_option.py +++ b/appium/options/android/common/adb/skip_logcat_capture_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SkipLogcatCaptureOption(SupportsCapabilities): @property - def skip_logcat_capture(self) -> Optional[bool]: + def skip_logcat_capture(self) -> bool | None: """ Whether to delete all the existing logs in the device buffer before starting a new test. diff --git a/appium/options/android/common/adb/suppress_kill_server_option.py b/appium/options/android/common/adb/suppress_kill_server_option.py index fb7738994..ed54e99b4 100644 --- a/appium/options/android/common/adb/suppress_kill_server_option.py +++ b/appium/options/android/common/adb/suppress_kill_server_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SuppressKillServerOption(SupportsCapabilities): @property - def suppress_kill_server(self) -> Optional[bool]: + def suppress_kill_server(self) -> bool | None: """ Prevents the driver from ever killing the ADB server explicitly. """ diff --git a/appium/options/android/common/app/allow_test_packages_option.py b/appium/options/android/common/app/allow_test_packages_option.py index b09136932..ea66db61f 100644 --- a/appium/options/android/common/app/allow_test_packages_option.py +++ b/appium/options/android/common/app/allow_test_packages_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AllowTestPackagesOption(SupportsCapabilities): @property - def allow_test_packages(self) -> Optional[bool]: + def allow_test_packages(self) -> bool | None: """ Whether it is possible to use packages built with the test flag for the automated testing (literally adds -t flag to the adb install command). diff --git a/appium/options/android/common/app/android_install_timeout_option.py b/appium/options/android/common/app/android_install_timeout_option.py index 38a997648..cb53c833a 100644 --- a/appium/options/android/common/app/android_install_timeout_option.py +++ b/appium/options/android/common/app/android_install_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class AndroidInstallTimeoutOption(SupportsCapabilities): @property - def android_install_timeout(self) -> Optional[timedelta]: + def android_install_timeout(self) -> timedelta | None: """ Maximum amount of time to wait until the application under test is installed. """ @@ -33,7 +32,7 @@ def android_install_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @android_install_timeout.setter - def android_install_timeout(self, value: Union[timedelta, int]) -> None: + def android_install_timeout(self, value: timedelta | int) -> None: """ Maximum amount of time to wait until the application under test is installed. 90000 ms by default diff --git a/appium/options/android/common/app/app_activity_option.py b/appium/options/android/common/app/app_activity_option.py index 41f66eed8..1df540a95 100644 --- a/appium/options/android/common/app/app_activity_option.py +++ b/appium/options/android/common/app/app_activity_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppActivityOption(SupportsCapabilities): @property - def app_activity(self) -> Optional[str]: + def app_activity(self) -> str | None: """ Name of the main app activity. """ diff --git a/appium/options/android/common/app/app_package_option.py b/appium/options/android/common/app/app_package_option.py index a8c7b065c..ffcb1ad8d 100644 --- a/appium/options/android/common/app/app_package_option.py +++ b/appium/options/android/common/app/app_package_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppPackageOption(SupportsCapabilities): @property - def app_package(self) -> Optional[str]: + def app_package(self) -> str | None: """ App package identifier. """ diff --git a/appium/options/android/common/app/app_wait_activity_option.py b/appium/options/android/common/app/app_wait_activity_option.py index 5d72f311d..bbf726274 100644 --- a/appium/options/android/common/app/app_wait_activity_option.py +++ b/appium/options/android/common/app/app_wait_activity_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppWaitActivityOption(SupportsCapabilities): @property - def app_wait_activity(self) -> Optional[str]: + def app_wait_activity(self) -> str | None: """ Name of the app activity to wait for. """ diff --git a/appium/options/android/common/app/app_wait_duration_option.py b/appium/options/android/common/app/app_wait_duration_option.py index 362cb3725..428dd5df3 100644 --- a/appium/options/android/common/app/app_wait_duration_option.py +++ b/appium/options/android/common/app/app_wait_duration_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class AppWaitDurationOption(SupportsCapabilities): @property - def app_wait_duration(self) -> Optional[timedelta]: + def app_wait_duration(self) -> timedelta | None: """ Identifier of the app package to wait for. """ @@ -33,7 +32,7 @@ def app_wait_duration(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @app_wait_duration.setter - def app_wait_duration(self, value: Union[timedelta, int]) -> None: + def app_wait_duration(self, value: timedelta | int) -> None: """ Maximum amount of time to wait until the application under test is started (e.g. an activity returns the control to the caller). 20000 ms by default. diff --git a/appium/options/android/common/app/app_wait_for_launch_option.py b/appium/options/android/common/app/app_wait_for_launch_option.py index 5f5b48c51..3a34b4fb5 100644 --- a/appium/options/android/common/app/app_wait_for_launch_option.py +++ b/appium/options/android/common/app/app_wait_for_launch_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppWaitForLaunchOption(SupportsCapabilities): @property - def app_wait_for_launch(self) -> Optional[bool]: + def app_wait_for_launch(self) -> bool | None: """ Whether to block until the app under test returns the control to the caller after its activity has been started by Activity Manager. diff --git a/appium/options/android/common/app/app_wait_package_option.py b/appium/options/android/common/app/app_wait_package_option.py index 9df4fa0d0..8ba087205 100644 --- a/appium/options/android/common/app/app_wait_package_option.py +++ b/appium/options/android/common/app/app_wait_package_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppWaitPackageOption(SupportsCapabilities): @property - def app_wait_package(self) -> Optional[str]: + def app_wait_package(self) -> str | None: """ Identifier of the app package to wait for. """ diff --git a/appium/options/android/common/app/auto_grant_premissions_option.py b/appium/options/android/common/app/auto_grant_premissions_option.py index e276e7da4..2aa7e459b 100644 --- a/appium/options/android/common/app/auto_grant_premissions_option.py +++ b/appium/options/android/common/app/auto_grant_premissions_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AutoGrantPermissionsOption(SupportsCapabilities): @property - def auto_grant_permissions(self) -> Optional[bool]: + def auto_grant_permissions(self) -> bool | None: """ Whether to grant all the requested application permissions automatically when a test starts. diff --git a/appium/options/android/common/app/enforce_app_install_option.py b/appium/options/android/common/app/enforce_app_install_option.py index 85d128ed7..0056924b6 100644 --- a/appium/options/android/common/app/enforce_app_install_option.py +++ b/appium/options/android/common/app/enforce_app_install_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class EnforceAppInstallOption(SupportsCapabilities): @property - def enforce_app_install(self) -> Optional[bool]: + def enforce_app_install(self) -> bool | None: """ Whether the application under test is always reinstalled even if a newer version of it already exists on the device under test. diff --git a/appium/options/android/common/app/intent_action_option.py b/appium/options/android/common/app/intent_action_option.py index 8019bcc54..b44dfe781 100644 --- a/appium/options/android/common/app/intent_action_option.py +++ b/appium/options/android/common/app/intent_action_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class IntentActionOption(SupportsCapabilities): @property - def intent_action(self) -> Optional[str]: + def intent_action(self) -> str | None: """ Intent action to be applied when starting the given appActivity by Activity Manager. diff --git a/appium/options/android/common/app/intent_category_option.py b/appium/options/android/common/app/intent_category_option.py index f6f568c20..b39ef5131 100644 --- a/appium/options/android/common/app/intent_category_option.py +++ b/appium/options/android/common/app/intent_category_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class IntentCategoryOption(SupportsCapabilities): @property - def intent_category(self) -> Optional[str]: + def intent_category(self) -> str | None: """ Intent category to be applied when starting the given appActivity by Activity Manager. diff --git a/appium/options/android/common/app/intent_flags_option.py b/appium/options/android/common/app/intent_flags_option.py index 141e51c30..4cff2dc87 100644 --- a/appium/options/android/common/app/intent_flags_option.py +++ b/appium/options/android/common/app/intent_flags_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class IntentFlagsOption(SupportsCapabilities): @property - def intent_flags(self) -> Optional[str]: + def intent_flags(self) -> str | None: """ Intent flags to be applied when starting the given appActivity by Activity Manager. diff --git a/appium/options/android/common/app/optional_intent_arguments_option.py b/appium/options/android/common/app/optional_intent_arguments_option.py index 3411fe96c..66dcf2448 100644 --- a/appium/options/android/common/app/optional_intent_arguments_option.py +++ b/appium/options/android/common/app/optional_intent_arguments_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class OptionalIntentArgumentsOption(SupportsCapabilities): @property - def optional_intent_arguments(self) -> Optional[str]: + def optional_intent_arguments(self) -> str | None: """ Intent arguments to be applied when starting the given appActivity by Activity Manager. diff --git a/appium/options/android/common/app/remote_apps_cache_limit_option.py b/appium/options/android/common/app/remote_apps_cache_limit_option.py index 0f21ec782..a5bd612f5 100644 --- a/appium/options/android/common/app/remote_apps_cache_limit_option.py +++ b/appium/options/android/common/app/remote_apps_cache_limit_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class RemoteAppsCacheLimitOption(SupportsCapabilities): @property - def remote_apps_cache_limit(self) -> Optional[int]: + def remote_apps_cache_limit(self) -> int | None: """ Maximum amount of apps that could be cached on the remote device. """ diff --git a/appium/options/android/common/app/uninstall_other_packages_option.py b/appium/options/android/common/app/uninstall_other_packages_option.py index 2cd05cdf5..0ec72aa13 100644 --- a/appium/options/android/common/app/uninstall_other_packages_option.py +++ b/appium/options/android/common/app/uninstall_other_packages_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UninstallOtherPackagesOption(SupportsCapabilities): @property - def uninstall_other_packages(self) -> Optional[str]: + def uninstall_other_packages(self) -> str | None: """ Identifiers of packages to be uninstalled from the device before a test starts. """ diff --git a/appium/options/android/common/avd/avd_args_option.py b/appium/options/android/common/avd/avd_args_option.py index a8b7b7506..43e3542ef 100644 --- a/appium/options/android/common/avd/avd_args_option.py +++ b/appium/options/android/common/avd/avd_args_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AvdArgsOption(SupportsCapabilities): @property - def avd_args(self) -> Optional[str]: + def avd_args(self) -> str | None: """ Emulator command line arguments. """ diff --git a/appium/options/android/common/avd/avd_env_option.py b/appium/options/android/common/avd/avd_env_option.py index a673a95fd..06447da22 100644 --- a/appium/options/android/common/avd/avd_env_option.py +++ b/appium/options/android/common/avd/avd_env_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict, Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +23,14 @@ class AvdEnvOption(SupportsCapabilities): @property - def avd_env(self) -> Optional[Dict[str, str]]: + def avd_env(self) -> dict[str, str] | None: """ Mapping of emulator environment variables. """ return self.get_capability(AVD_ENV) @avd_env.setter - def avd_env(self, value: Dict[str, str]) -> None: + def avd_env(self, value: dict[str, str]) -> None: """ Set the mapping of emulator environment variables. """ diff --git a/appium/options/android/common/avd/avd_launch_timeout_option.py b/appium/options/android/common/avd/avd_launch_timeout_option.py index 017396ef0..94abb5d3a 100644 --- a/appium/options/android/common/avd/avd_launch_timeout_option.py +++ b/appium/options/android/common/avd/avd_launch_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class AvdLaunchTimeoutOption(SupportsCapabilities): @property - def avd_launch_timeout(self) -> Optional[timedelta]: + def avd_launch_timeout(self) -> timedelta | None: """ Timeout to wait until Android Emulator is started. """ @@ -33,7 +32,7 @@ def avd_launch_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @avd_launch_timeout.setter - def avd_launch_timeout(self, value: Union[timedelta, int]) -> None: + def avd_launch_timeout(self, value: timedelta | int) -> None: """ Maximum timeout to wait until Android Emulator is started. 60000 ms by default. diff --git a/appium/options/android/common/avd/avd_option.py b/appium/options/android/common/avd/avd_option.py index 42c543fc8..e263a2fcc 100644 --- a/appium/options/android/common/avd/avd_option.py +++ b/appium/options/android/common/avd/avd_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AvdOption(SupportsCapabilities): @property - def avd(self) -> Optional[str]: + def avd(self) -> str | None: """ Name of Android emulator to run the test on. """ diff --git a/appium/options/android/common/avd/avd_ready_timeout_option.py b/appium/options/android/common/avd/avd_ready_timeout_option.py index c074b3190..7148cda20 100644 --- a/appium/options/android/common/avd/avd_ready_timeout_option.py +++ b/appium/options/android/common/avd/avd_ready_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class AvdReadyTimeoutOption(SupportsCapabilities): @property - def avd_ready_timeout(self) -> Optional[timedelta]: + def avd_ready_timeout(self) -> timedelta | None: """ Timeout to wait until Android Emulator is fully booted and is ready for usage. """ @@ -33,7 +32,7 @@ def avd_ready_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @avd_ready_timeout.setter - def avd_ready_timeout(self, value: Union[timedelta, int]) -> None: + def avd_ready_timeout(self, value: timedelta | int) -> None: """ Maximum timeout to wait until Android Emulator is fully booted and is ready for usage. 60000 ms by default diff --git a/appium/options/android/common/avd/gps_enabled_option.py b/appium/options/android/common/avd/gps_enabled_option.py index c9b3c60b1..73d0f3cbe 100644 --- a/appium/options/android/common/avd/gps_enabled_option.py +++ b/appium/options/android/common/avd/gps_enabled_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class GpsEnabledOption(SupportsCapabilities): @property - def gps_enabled(self) -> Optional[bool]: + def gps_enabled(self) -> bool | None: """ State of the GPS service on emulator. """ diff --git a/appium/options/android/common/avd/network_speed_option.py b/appium/options/android/common/avd/network_speed_option.py index 1ab6c1cba..b748300c4 100644 --- a/appium/options/android/common/avd/network_speed_option.py +++ b/appium/options/android/common/avd/network_speed_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class NetworkSpeedOption(SupportsCapabilities): @property - def network_speed(self) -> Optional[str]: + def network_speed(self) -> str | None: """ Desired network speed limit for the emulator. """ diff --git a/appium/options/android/common/context/auto_webview_timeout_option.py b/appium/options/android/common/context/auto_webview_timeout_option.py index 774574313..6dd854ee5 100644 --- a/appium/options/android/common/context/auto_webview_timeout_option.py +++ b/appium/options/android/common/context/auto_webview_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class AutoWebviewTimeoutOption(SupportsCapabilities): @property - def auto_webview_timeout(self) -> Optional[timedelta]: + def auto_webview_timeout(self) -> timedelta | None: """ Set the maximum timeout to wait until a web view is available if autoWebview capability is set to true. 2000 ms by default. @@ -34,7 +33,7 @@ def auto_webview_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @auto_webview_timeout.setter - def auto_webview_timeout(self, value: Union[timedelta, int]) -> None: + def auto_webview_timeout(self, value: timedelta | int) -> None: """ Timeout to wait until a web view is available. """ diff --git a/appium/options/android/common/context/chrome_logging_prefs_option.py b/appium/options/android/common/context/chrome_logging_prefs_option.py index 0c2b69c4d..80dcf35d3 100644 --- a/appium/options/android/common/context/chrome_logging_prefs_option.py +++ b/appium/options/android/common/context/chrome_logging_prefs_option.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from typing import Any, Dict, Optional +from typing import Any from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +24,14 @@ class ChromeLoggingPrefsOption(SupportsCapabilities): @property - def chrome_logging_prefs(self) -> Optional[Dict[str, Any]]: + def chrome_logging_prefs(self) -> dict[str, Any] | None: """ Chrome logging preferences. """ return self.get_capability(CHROME_LOGGING_PREFS) @chrome_logging_prefs.setter - def chrome_logging_prefs(self, value: Dict[str, Any]) -> None: + def chrome_logging_prefs(self, value: dict[str, Any]) -> None: """ Chrome logging preferences mapping. Basically the same as [goog:loggingPrefs](https://newbedev.com/ diff --git a/appium/options/android/common/context/chrome_options_option.py b/appium/options/android/common/context/chrome_options_option.py index 3adb9cebb..8cb0200c0 100644 --- a/appium/options/android/common/context/chrome_options_option.py +++ b/appium/options/android/common/context/chrome_options_option.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from typing import Any, Dict, Optional +from typing import Any from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +24,14 @@ class ChromeOptionsOption(SupportsCapabilities): @property - def chrome_options(self) -> Optional[Dict[str, Any]]: + def chrome_options(self) -> dict[str, Any] | None: """ Chrome options. """ return self.get_capability(CHROME_OPTIONS) @chrome_options.setter - def chrome_options(self, value: Dict[str, Any]) -> None: + def chrome_options(self, value: dict[str, Any]) -> None: """ A mapping, that allows to customize chromedriver options. See https://chromedriver.chromium.org/capabilities for the list diff --git a/appium/options/android/common/context/chromedriver_args_option.py b/appium/options/android/common/context/chromedriver_args_option.py index b3633b105..7fa181301 100644 --- a/appium/options/android/common/context/chromedriver_args_option.py +++ b/appium/options/android/common/context/chromedriver_args_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import List, Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +23,14 @@ class ChromedriverArgsOption(SupportsCapabilities): @property - def chromedriver_args(self) -> Optional[List[str]]: + def chromedriver_args(self) -> list[str] | None: """ Array of chromedriver CLI arguments. """ return self.get_capability(CHROMEDRIVER_ARGS) @chromedriver_args.setter - def chromedriver_args(self, value: List[str]) -> None: + def chromedriver_args(self, value: list[str]) -> None: """ Array of chromedriver [command line arguments](http://www.assertselenium.com/java/list-of-chrome-driver-command-line-arguments/). diff --git a/appium/options/android/common/context/chromedriver_chrome_mapping_file_option.py b/appium/options/android/common/context/chromedriver_chrome_mapping_file_option.py index cc84bed1b..fddfa23b6 100644 --- a/appium/options/android/common/context/chromedriver_chrome_mapping_file_option.py +++ b/appium/options/android/common/context/chromedriver_chrome_mapping_file_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ChromedriverChromeMappingFileOption(SupportsCapabilities): @property - def chromedriver_chrome_mapping_file(self) -> Optional[str]: + def chromedriver_chrome_mapping_file(self) -> str | None: """ Full path to the chromedrivers mapping file is located. """ diff --git a/appium/options/android/common/context/chromedriver_disable_build_check_option.py b/appium/options/android/common/context/chromedriver_disable_build_check_option.py index 16886ab1c..e9831e70f 100644 --- a/appium/options/android/common/context/chromedriver_disable_build_check_option.py +++ b/appium/options/android/common/context/chromedriver_disable_build_check_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ChromedriverDisableBuildCheckOption(SupportsCapabilities): @property - def chromedriver_disable_build_check(self) -> Optional[bool]: + def chromedriver_disable_build_check(self) -> bool | None: """ Whether to disable the compatibility validation between the current chromedriver and the destination browser/web view. diff --git a/appium/options/android/common/context/chromedriver_executable_dir_option.py b/appium/options/android/common/context/chromedriver_executable_dir_option.py index 64e96c98e..e57eace0b 100644 --- a/appium/options/android/common/context/chromedriver_executable_dir_option.py +++ b/appium/options/android/common/context/chromedriver_executable_dir_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ChromedriverExecutableDirOption(SupportsCapabilities): @property - def chromedriver_executable_dir(self) -> Optional[str]: + def chromedriver_executable_dir(self) -> str | None: """ Full path to the folder where chromedriver executables are located. """ diff --git a/appium/options/android/common/context/chromedriver_executable_option.py b/appium/options/android/common/context/chromedriver_executable_option.py index 79f30ca14..f6e25f360 100644 --- a/appium/options/android/common/context/chromedriver_executable_option.py +++ b/appium/options/android/common/context/chromedriver_executable_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ChromedriverExecutableOption(SupportsCapabilities): @property - def chromedriver_executable(self) -> Optional[str]: + def chromedriver_executable(self) -> str | None: """ Path to the chromedriver executable on the server file system. """ diff --git a/appium/options/android/common/context/chromedriver_port_option.py b/appium/options/android/common/context/chromedriver_port_option.py index 8a7ef8ab7..fc6867487 100644 --- a/appium/options/android/common/context/chromedriver_port_option.py +++ b/appium/options/android/common/context/chromedriver_port_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ChromedriverPortOption(SupportsCapabilities): @property - def chromedriver_port(self) -> Optional[int]: + def chromedriver_port(self) -> int | None: """ Local port number to use for Chromedriver communication. """ diff --git a/appium/options/android/common/context/chromedriver_ports_option.py b/appium/options/android/common/context/chromedriver_ports_option.py index 5e13c987b..84fb30fab 100644 --- a/appium/options/android/common/context/chromedriver_ports_option.py +++ b/appium/options/android/common/context/chromedriver_ports_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import List, Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +23,14 @@ class ChromedriverPortsOption(SupportsCapabilities): @property - def chromedriver_ports(self) -> Optional[List[int]]: + def chromedriver_ports(self) -> list[int] | None: """ Local port numbers to use for Chromedriver communication. """ return self.get_capability(CHROMEDRIVER_PORTS) @chromedriver_ports.setter - def chromedriver_ports(self, value: List[int]) -> None: + def chromedriver_ports(self, value: list[int]) -> None: """ Array of possible port numbers to assign for Chromedriver communication. If none of the port in this array is free then a server error is thrown. diff --git a/appium/options/android/common/context/chromedriver_use_system_executable_option.py b/appium/options/android/common/context/chromedriver_use_system_executable_option.py index b164ed13f..673c43fc8 100644 --- a/appium/options/android/common/context/chromedriver_use_system_executable_option.py +++ b/appium/options/android/common/context/chromedriver_use_system_executable_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ChromedriverUseSystemExecutableOption(SupportsCapabilities): @property - def chromedriver_use_system_executable(self) -> Optional[bool]: + def chromedriver_use_system_executable(self) -> bool | None: """ Whether to use the system chromedriver. """ diff --git a/appium/options/android/common/context/ensure_webviews_have_pages_option.py b/appium/options/android/common/context/ensure_webviews_have_pages_option.py index d1f549a9f..da374fa67 100644 --- a/appium/options/android/common/context/ensure_webviews_have_pages_option.py +++ b/appium/options/android/common/context/ensure_webviews_have_pages_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class EnsureWebviewsHavePagesOption(SupportsCapabilities): @property - def ensure_webviews_have_pages(self) -> Optional[bool]: + def ensure_webviews_have_pages(self) -> bool | None: """ Whether to ensure if web views have pages. """ diff --git a/appium/options/android/common/context/extract_chrome_android_package_from_context_name_option.py b/appium/options/android/common/context/extract_chrome_android_package_from_context_name_option.py index 95559072f..79bc4a6c3 100644 --- a/appium/options/android/common/context/extract_chrome_android_package_from_context_name_option.py +++ b/appium/options/android/common/context/extract_chrome_android_package_from_context_name_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ExtractChromeAndroidPackageFromContextNameOption(SupportsCapabilities): @property - def extract_chrome_android_package_from_context_name(self) -> Optional[bool]: + def extract_chrome_android_package_from_context_name(self) -> bool | None: """ Whether to use the android package identifier associated with the context name. """ diff --git a/appium/options/android/common/context/native_web_screenshot_option.py b/appium/options/android/common/context/native_web_screenshot_option.py index 1c59a60b5..06a1db0d1 100644 --- a/appium/options/android/common/context/native_web_screenshot_option.py +++ b/appium/options/android/common/context/native_web_screenshot_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class NativeWebScreenshotOption(SupportsCapabilities): @property - def native_web_screenshot(self) -> Optional[bool]: + def native_web_screenshot(self) -> bool | None: """ Whether to use native screenshots in web view context. """ diff --git a/appium/options/android/common/context/recreate_chrome_driver_sessions_option.py b/appium/options/android/common/context/recreate_chrome_driver_sessions_option.py index 4ef8d1096..4ec8880ff 100644 --- a/appium/options/android/common/context/recreate_chrome_driver_sessions_option.py +++ b/appium/options/android/common/context/recreate_chrome_driver_sessions_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class RecreateChromeDriverSessionsOption(SupportsCapabilities): @property - def recreate_chrome_driver_sessions(self) -> Optional[bool]: + def recreate_chrome_driver_sessions(self) -> bool | None: """ Whether chromedriver sessions should be killed and then recreated instead of just suspending it on context switch. diff --git a/appium/options/android/common/context/show_chromedriver_log_option.py b/appium/options/android/common/context/show_chromedriver_log_option.py index da4f283a4..eff41c558 100644 --- a/appium/options/android/common/context/show_chromedriver_log_option.py +++ b/appium/options/android/common/context/show_chromedriver_log_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ShowChromedriverLogOption(SupportsCapabilities): @property - def show_chromedriver_log(self) -> Optional[bool]: + def show_chromedriver_log(self) -> bool | None: """ Whether to forward chromedriver output to the Appium server log. """ diff --git a/appium/options/android/common/context/webview_devtools_port_option.py b/appium/options/android/common/context/webview_devtools_port_option.py index 2f0e6d7a7..a0c298579 100644 --- a/appium/options/android/common/context/webview_devtools_port_option.py +++ b/appium/options/android/common/context/webview_devtools_port_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class WebviewDevtoolsPortOption(SupportsCapabilities): @property - def webview_devtools_port(self) -> Optional[int]: + def webview_devtools_port(self) -> int | None: """ Local port number to use for devtools communication. """ diff --git a/appium/options/android/common/localization/locale_script_option.py b/appium/options/android/common/localization/locale_script_option.py index abcd08529..d740aecd7 100644 --- a/appium/options/android/common/localization/locale_script_option.py +++ b/appium/options/android/common/localization/locale_script_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class LocaleScriptOption(SupportsCapabilities): @property - def locale_script(self) -> Optional[str]: + def locale_script(self) -> str | None: """ Canonical name of the locale to be set for the app under test. """ diff --git a/appium/options/android/common/locking/skip_unlock_option.py b/appium/options/android/common/locking/skip_unlock_option.py index c80a6efa7..6f4dc5492 100644 --- a/appium/options/android/common/locking/skip_unlock_option.py +++ b/appium/options/android/common/locking/skip_unlock_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SkipUnlockOption(SupportsCapabilities): @property - def skip_unlock(self) -> Optional[bool]: + def skip_unlock(self) -> bool | None: """ Whether to skip the check for lock screen presence. """ diff --git a/appium/options/android/common/locking/unlock_key_option.py b/appium/options/android/common/locking/unlock_key_option.py index ffee5a1a5..297f27e08 100644 --- a/appium/options/android/common/locking/unlock_key_option.py +++ b/appium/options/android/common/locking/unlock_key_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UnlockKeyOption(SupportsCapabilities): @property - def unlock_key(self) -> Optional[str]: + def unlock_key(self) -> str | None: """ Unlock key. """ diff --git a/appium/options/android/common/locking/unlock_strategy_option.py b/appium/options/android/common/locking/unlock_strategy_option.py index fb884518d..fc36cd38c 100644 --- a/appium/options/android/common/locking/unlock_strategy_option.py +++ b/appium/options/android/common/locking/unlock_strategy_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UnlockStrategyOption(SupportsCapabilities): @property - def unlock_strategy(self) -> Optional[str]: + def unlock_strategy(self) -> str | None: """ Unlock strategy name. """ diff --git a/appium/options/android/common/locking/unlock_success_timeout_option.py b/appium/options/android/common/locking/unlock_success_timeout_option.py index 488ae5f9e..268656c0e 100644 --- a/appium/options/android/common/locking/unlock_success_timeout_option.py +++ b/appium/options/android/common/locking/unlock_success_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class UnlockSuccessTimeoutOption(SupportsCapabilities): @property - def unlock_success_timeout(self) -> Optional[timedelta]: + def unlock_success_timeout(self) -> timedelta | None: """ Timeout to wait until the device is unlocked. """ @@ -33,7 +32,7 @@ def unlock_success_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @unlock_success_timeout.setter - def unlock_success_timeout(self, value: Union[timedelta, int]) -> None: + def unlock_success_timeout(self, value: timedelta | int) -> None: """ Maximum timeout to wait until the device is unlocked. 2000 ms by default. diff --git a/appium/options/android/common/locking/unlock_type_option.py b/appium/options/android/common/locking/unlock_type_option.py index 7026cf343..a1677b400 100644 --- a/appium/options/android/common/locking/unlock_type_option.py +++ b/appium/options/android/common/locking/unlock_type_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UnlockTypeOption(SupportsCapabilities): @property - def unlock_type(self) -> Optional[str]: + def unlock_type(self) -> str | None: """ Unlock type. """ diff --git a/appium/options/android/common/mjpeg/mjpeg_screenshot_url_option.py b/appium/options/android/common/mjpeg/mjpeg_screenshot_url_option.py index 70bad0177..c0ddcf6da 100644 --- a/appium/options/android/common/mjpeg/mjpeg_screenshot_url_option.py +++ b/appium/options/android/common/mjpeg/mjpeg_screenshot_url_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class MjpegScreenshotUrlOption(SupportsCapabilities): @property - def mjpeg_screenshot_url(self) -> Optional[str]: + def mjpeg_screenshot_url(self) -> str | None: """ URL of a service that provides realtime device screenshots in MJPEG format. """ diff --git a/appium/options/android/common/other/disable_suppress_accessibility_service_option.py b/appium/options/android/common/other/disable_suppress_accessibility_service_option.py index 980da567c..e0a5b0169 100644 --- a/appium/options/android/common/other/disable_suppress_accessibility_service_option.py +++ b/appium/options/android/common/other/disable_suppress_accessibility_service_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class DisableSuppressAccessibilityServiceOption(SupportsCapabilities): @property - def disable_suppress_accessibility_service(self) -> Optional[bool]: + def disable_suppress_accessibility_service(self) -> bool | None: """ Whether to suppress accessibility services. """ diff --git a/appium/options/android/common/other/user_profile_option.py b/appium/options/android/common/other/user_profile_option.py index 76871396a..a886acef9 100644 --- a/appium/options/android/common/other/user_profile_option.py +++ b/appium/options/android/common/other/user_profile_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UserProfileOption(SupportsCapabilities): @property - def user_profile(self) -> Optional[int]: + def user_profile(self) -> int | None: """ Integer identifier of a user profile. """ diff --git a/appium/options/android/common/signing/key_alias_option.py b/appium/options/android/common/signing/key_alias_option.py index 471b28ee8..ea948faa7 100644 --- a/appium/options/android/common/signing/key_alias_option.py +++ b/appium/options/android/common/signing/key_alias_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class KeyAliasOption(SupportsCapabilities): @property - def key_alias(self) -> Optional[str]: + def key_alias(self) -> str | None: """ Keystore key alias. """ diff --git a/appium/options/android/common/signing/key_password_option.py b/appium/options/android/common/signing/key_password_option.py index 5ed91d1c1..d8879c6cb 100644 --- a/appium/options/android/common/signing/key_password_option.py +++ b/appium/options/android/common/signing/key_password_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class KeyPasswordOption(SupportsCapabilities): @property - def key_password(self) -> Optional[str]: + def key_password(self) -> str | None: """ Keystore key password. """ diff --git a/appium/options/android/common/signing/keystore_password_option.py b/appium/options/android/common/signing/keystore_password_option.py index 8b7667117..c4a9cc3ec 100644 --- a/appium/options/android/common/signing/keystore_password_option.py +++ b/appium/options/android/common/signing/keystore_password_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class KeystorePasswordOption(SupportsCapabilities): @property - def keystore_password(self) -> Optional[str]: + def keystore_password(self) -> str | None: """ Keystore password. """ diff --git a/appium/options/android/common/signing/keystore_path_option.py b/appium/options/android/common/signing/keystore_path_option.py index 3489efe5c..6085ce50e 100644 --- a/appium/options/android/common/signing/keystore_path_option.py +++ b/appium/options/android/common/signing/keystore_path_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class KeystorePathOption(SupportsCapabilities): @property - def keystore_path(self) -> Optional[str]: + def keystore_path(self) -> str | None: """ The path to keystore. """ diff --git a/appium/options/android/common/signing/no_sign_option.py b/appium/options/android/common/signing/no_sign_option.py index a5a52841b..8e0d59a8c 100644 --- a/appium/options/android/common/signing/no_sign_option.py +++ b/appium/options/android/common/signing/no_sign_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class NoSignOption(SupportsCapabilities): @property - def no_sign(self) -> Optional[bool]: + def no_sign(self) -> bool | None: """ Whether to skip application signing. """ diff --git a/appium/options/android/common/signing/use_keystore_option.py b/appium/options/android/common/signing/use_keystore_option.py index f8a947a5c..737d65658 100644 --- a/appium/options/android/common/signing/use_keystore_option.py +++ b/appium/options/android/common/signing/use_keystore_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UseKeystoreOption(SupportsCapabilities): @property - def use_keystore(self) -> Optional[bool]: + def use_keystore(self) -> bool | None: """ Whether to use custom keystore. """ diff --git a/appium/options/android/espresso/activity_options_option.py b/appium/options/android/espresso/activity_options_option.py index a15935feb..45d632dbc 100644 --- a/appium/options/android/espresso/activity_options_option.py +++ b/appium/options/android/espresso/activity_options_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict, Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +23,14 @@ class ActivityOptionsOption(SupportsCapabilities): @property - def activity_options(self) -> Optional[Dict]: + def activity_options(self) -> dict | None: """ Activity options. """ return self.get_capability(ACTIVITY_OPTIONS) @activity_options.setter - def activity_options(self, value: Dict) -> None: + def activity_options(self, value: dict) -> None: """ The mapping of custom options for the main app activity that is going to be started. Check diff --git a/appium/options/android/espresso/app_locale_option.py b/appium/options/android/espresso/app_locale_option.py index 01ae27545..478678067 100644 --- a/appium/options/android/espresso/app_locale_option.py +++ b/appium/options/android/espresso/app_locale_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict, Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +23,14 @@ class AppLocaleOption(SupportsCapabilities): @property - def app_locale(self) -> Optional[Dict[str, str]]: + def app_locale(self) -> dict[str, str] | None: """ Locale for the app under test. """ return self.get_capability(APP_LOCALE) @app_locale.setter - def app_locale(self, value: Dict[str, str]) -> None: + def app_locale(self, value: dict[str, str]) -> None: """ Sets the locale for the app under test. The main difference between this option and the above ones is that this option only changes the locale for the application diff --git a/appium/options/android/espresso/base.py b/appium/options/android/espresso/base.py index c725b63a7..4ceec1b38 100644 --- a/appium/options/android/espresso/base.py +++ b/appium/options/android/espresso/base.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict from appium.options.android.common.adb.adb_exec_timeout_option import AdbExecTimeoutOption from appium.options.android.common.adb.adb_port_option import AdbPortOption @@ -214,7 +213,7 @@ class EspressoOptions( AppLocaleOption, ): @property - def default_capabilities(self) -> Dict: + def default_capabilities(self) -> dict: return { AUTOMATION_NAME: 'Espresso', PLATFORM_NAME: 'Android', diff --git a/appium/options/android/espresso/espresso_build_config_option.py b/appium/options/android/espresso/espresso_build_config_option.py index 7a8694f31..7f46e21ce 100644 --- a/appium/options/android/espresso/espresso_build_config_option.py +++ b/appium/options/android/espresso/espresso_build_config_option.py @@ -16,7 +16,7 @@ # under the License. import json -from typing import Any, Dict, Optional, Union +from typing import Any from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +25,7 @@ class EspressoBuildConfigOption(SupportsCapabilities): @property - def espresso_build_config(self) -> Optional[Union[Dict[str, Any], str]]: + def espresso_build_config(self) -> dict[str, Any] | str | None: """ Espresso build config. """ @@ -36,7 +36,7 @@ def espresso_build_config(self) -> Optional[Union[Dict[str, Any], str]]: return value @espresso_build_config.setter - def espresso_build_config(self, value: Union[Dict[str, Any], str]) -> None: + def espresso_build_config(self, value: dict[str, Any] | str) -> None: """ This config allows to customize several important properties of Espresso server. Refer to diff --git a/appium/options/android/espresso/espresso_server_launch_timeout_option.py b/appium/options/android/espresso/espresso_server_launch_timeout_option.py index 9335358de..91d3cf19c 100644 --- a/appium/options/android/espresso/espresso_server_launch_timeout_option.py +++ b/appium/options/android/espresso/espresso_server_launch_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class EspressoServerLaunchTimeoutOption(SupportsCapabilities): @property - def espresso_server_launch_timeout(self) -> Optional[timedelta]: + def espresso_server_launch_timeout(self) -> timedelta | None: """ Maximum timeout to wait until Espresso server is listening on the device. """ @@ -33,7 +32,7 @@ def espresso_server_launch_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @espresso_server_launch_timeout.setter - def espresso_server_launch_timeout(self, value: Union[timedelta, int]) -> None: + def espresso_server_launch_timeout(self, value: timedelta | int) -> None: """ Set the maximum timeout to wait util Espresso is listening on the device. 45000 ms by default diff --git a/appium/options/android/espresso/force_espresso_rebuild_option.py b/appium/options/android/espresso/force_espresso_rebuild_option.py index 8971db795..cbdf67b06 100644 --- a/appium/options/android/espresso/force_espresso_rebuild_option.py +++ b/appium/options/android/espresso/force_espresso_rebuild_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ForceEspressoRebuildOption(SupportsCapabilities): @property - def force_espresso_rebuild(self) -> Optional[bool]: + def force_espresso_rebuild(self) -> bool | None: """ Whether to force Espresso server rebuild on a new session startup. """ diff --git a/appium/options/android/espresso/intent_options_option.py b/appium/options/android/espresso/intent_options_option.py index 59625bd91..7618cb690 100644 --- a/appium/options/android/espresso/intent_options_option.py +++ b/appium/options/android/espresso/intent_options_option.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from typing import Any, Dict, Optional +from typing import Any from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +24,14 @@ class IntentOptionsOption(SupportsCapabilities): @property - def intent_options(self) -> Optional[Dict[str, Any]]: + def intent_options(self) -> dict[str, Any] | None: """ Intent options. """ return self.get_capability(INTENT_OPTIONS) @intent_options.setter - def intent_options(self, value: Dict[str, Any]) -> None: + def intent_options(self, value: dict[str, Any]) -> None: """ The mapping of custom options for the intent that is going to be passed to the main app activity. Check diff --git a/appium/options/android/espresso/show_gradle_log_option.py b/appium/options/android/espresso/show_gradle_log_option.py index 48d233dbf..9fdfff486 100644 --- a/appium/options/android/espresso/show_gradle_log_option.py +++ b/appium/options/android/espresso/show_gradle_log_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ShowGradleLogOption(SupportsCapabilities): @property - def show_gradle_log(self) -> Optional[bool]: + def show_gradle_log(self) -> bool | None: """ Whether to include Gradle log to the regular server log. """ diff --git a/appium/options/android/uiautomator2/base.py b/appium/options/android/uiautomator2/base.py index 7efcb9036..4b976ea97 100644 --- a/appium/options/android/uiautomator2/base.py +++ b/appium/options/android/uiautomator2/base.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict from appium.options.android.common.adb.adb_exec_timeout_option import AdbExecTimeoutOption from appium.options.android.common.adb.adb_port_option import AdbPortOption @@ -214,7 +213,7 @@ class UiAutomator2Options( UserProfileOption, ): @property - def default_capabilities(self) -> Dict: + def default_capabilities(self) -> dict: return { AUTOMATION_NAME: 'UIAutomator2', PLATFORM_NAME: 'Android', diff --git a/appium/options/android/uiautomator2/disable_window_animation_option.py b/appium/options/android/uiautomator2/disable_window_animation_option.py index 5ff614b49..65274a058 100644 --- a/appium/options/android/uiautomator2/disable_window_animation_option.py +++ b/appium/options/android/uiautomator2/disable_window_animation_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class DisableWindowAnimationOption(SupportsCapabilities): @property - def disable_window_animation(self) -> Optional[bool]: + def disable_window_animation(self) -> bool | None: """ Whether window animations when starting the instrumentation process are disabled. diff --git a/appium/options/android/uiautomator2/mjpeg_server_port_option.py b/appium/options/android/uiautomator2/mjpeg_server_port_option.py index 6c702646f..aebde7ce5 100644 --- a/appium/options/android/uiautomator2/mjpeg_server_port_option.py +++ b/appium/options/android/uiautomator2/mjpeg_server_port_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class MjpegServerPortOption(SupportsCapabilities): @property - def mjpeg_server_port(self) -> Optional[int]: + def mjpeg_server_port(self) -> int | None: """ Number of the port UiAutomator2 server starts the MJPEG server on. """ diff --git a/appium/options/android/uiautomator2/skip_device_initialization_option.py b/appium/options/android/uiautomator2/skip_device_initialization_option.py index eda37be30..6b4e8d1fb 100644 --- a/appium/options/android/uiautomator2/skip_device_initialization_option.py +++ b/appium/options/android/uiautomator2/skip_device_initialization_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SkipDeviceInitializationOption(SupportsCapabilities): @property - def skip_device_initialization(self) -> Optional[bool]: + def skip_device_initialization(self) -> bool | None: """ Whether initial device startup checks by the server are disabled. """ diff --git a/appium/options/android/uiautomator2/skip_server_installation_option.py b/appium/options/android/uiautomator2/skip_server_installation_option.py index c343f78f1..6ff5eba42 100644 --- a/appium/options/android/uiautomator2/skip_server_installation_option.py +++ b/appium/options/android/uiautomator2/skip_server_installation_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SkipServerInstallationOption(SupportsCapabilities): @property - def skip_server_installation(self) -> Optional[bool]: + def skip_server_installation(self) -> bool | None: """ Whether to skip the server components installation on the device under test and all the related checks. diff --git a/appium/options/android/uiautomator2/uiautomator2_server_install_timeout_option.py b/appium/options/android/uiautomator2/uiautomator2_server_install_timeout_option.py index 4b25638f8..2c48608e6 100644 --- a/appium/options/android/uiautomator2/uiautomator2_server_install_timeout_option.py +++ b/appium/options/android/uiautomator2/uiautomator2_server_install_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class Uiautomator2ServerInstallTimeoutOption(SupportsCapabilities): @property - def uiautomator2_server_install_timeout(self) -> Optional[timedelta]: + def uiautomator2_server_install_timeout(self) -> timedelta | None: """ Maximum timeout to wait until UiAutomator2 server is installed on the device. """ @@ -33,7 +32,7 @@ def uiautomator2_server_install_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @uiautomator2_server_install_timeout.setter - def uiautomator2_server_install_timeout(self, value: Union[timedelta, int]) -> None: + def uiautomator2_server_install_timeout(self, value: timedelta | int) -> None: """ Set the maximum timeout to wait util UiAutomator2 server is installed on the device. 20000 ms by default diff --git a/appium/options/android/uiautomator2/uiautomator2_server_launch_timeout_option.py b/appium/options/android/uiautomator2/uiautomator2_server_launch_timeout_option.py index ce74c4473..993087772 100644 --- a/appium/options/android/uiautomator2/uiautomator2_server_launch_timeout_option.py +++ b/appium/options/android/uiautomator2/uiautomator2_server_launch_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class Uiautomator2ServerLaunchTimeoutOption(SupportsCapabilities): @property - def uiautomator2_server_launch_timeout(self) -> Optional[timedelta]: + def uiautomator2_server_launch_timeout(self) -> timedelta | None: """ Maximum timeout to wait until UiAutomator2 server is listening on the device. """ @@ -33,7 +32,7 @@ def uiautomator2_server_launch_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @uiautomator2_server_launch_timeout.setter - def uiautomator2_server_launch_timeout(self, value: Union[timedelta, int]) -> None: + def uiautomator2_server_launch_timeout(self, value: timedelta | int) -> None: """ Set the maximum timeout to wait util UiAutomator2Server is listening on the device. 30000 ms by default diff --git a/appium/options/android/uiautomator2/uiautomator2_server_read_timeout_option.py b/appium/options/android/uiautomator2/uiautomator2_server_read_timeout_option.py index cb8a39c25..bd962fe0c 100644 --- a/appium/options/android/uiautomator2/uiautomator2_server_read_timeout_option.py +++ b/appium/options/android/uiautomator2/uiautomator2_server_read_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class Uiautomator2ServerReadTimeoutOption(SupportsCapabilities): @property - def uiautomator2_server_read_timeout(self) -> Optional[timedelta]: + def uiautomator2_server_read_timeout(self) -> timedelta | None: """ Maximum timeout to wait for an HTTP response from UiAutomator2Server. """ @@ -33,7 +32,7 @@ def uiautomator2_server_read_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @uiautomator2_server_read_timeout.setter - def uiautomator2_server_read_timeout(self, value: Union[timedelta, int]) -> None: + def uiautomator2_server_read_timeout(self, value: timedelta | int) -> None: """ Set the maximum timeout to wait for a HTTP response from UiAutomator2Server. Only values greater than zero are accepted. If the given value is too low diff --git a/appium/options/common/__init__.py b/appium/options/common/__init__.py index a7a37ea6f..7545b4793 100644 --- a/appium/options/common/__init__.py +++ b/appium/options/common/__init__.py @@ -1 +1,3 @@ from .base import AppiumOptions + +__all__ = ['AppiumOptions'] diff --git a/appium/options/common/app_option.py b/appium/options/common/app_option.py index 4a8fff1b1..0ad52788a 100644 --- a/appium/options/common/app_option.py +++ b/appium/options/common/app_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppOption(SupportsCapabilities): @property - def app(self) -> Optional[str]: + def app(self) -> str | None: """ String representing app location. """ diff --git a/appium/options/common/auto_web_view_option.py b/appium/options/common/auto_web_view_option.py index 6983aef47..ced463773 100644 --- a/appium/options/common/auto_web_view_option.py +++ b/appium/options/common/auto_web_view_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AutoWebViewOption(SupportsCapabilities): @property - def auto_web_view(self) -> Optional[bool]: + def auto_web_view(self) -> bool | None: """ Whether the driver should try to automatically switch to a web view context after the session is started. diff --git a/appium/options/common/automation_name_option.py b/appium/options/common/automation_name_option.py index c18e0a15b..49fe5efb0 100644 --- a/appium/options/common/automation_name_option.py +++ b/appium/options/common/automation_name_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AutomationNameOption(SupportsCapabilities): @property - def automation_name(self) -> Optional[str]: + def automation_name(self) -> str | None: """ String representing the name of the automation engine name. """ diff --git a/appium/options/common/base.py b/appium/options/common/base.py index 17bccb61a..5bd4f1a94 100644 --- a/appium/options/common/base.py +++ b/appium/options/common/base.py @@ -16,7 +16,7 @@ # under the License. import copy -from typing import Any, Dict, TypeVar +from typing import Any, TypeVar from selenium.webdriver.common.options import BaseOptions @@ -43,7 +43,7 @@ class AppiumOptions( FullResetOption, NewCommandTimeoutOption, ): - _caps: Dict + _caps: dict W3C_CAPABILITY_NAMES = frozenset( [ 'acceptInsecureCerts', @@ -55,6 +55,9 @@ class AppiumOptions( 'setWindowRect', 'timeouts', 'unhandledPromptBehavior', + 'strictFileInteractability', # WebDriver spec v2 https://www.w3.org/TR/webdriver2/ + 'userAgent', # WebDriver spec v2 https://www.w3.org/TR/webdriver2/ + 'webSocketUrl', # WebDriver BiDi ] ) _OSS_W3C_CONVERSION = { @@ -82,14 +85,14 @@ def get_capability(self, name: str) -> Any: """Fetches capability value or None if the capability is not set""" return self._caps[name] if name in self._caps else self._caps.get(f'{APPIUM_PREFIX}{name}') - def load_capabilities(self: T, caps: Dict[str, Any]) -> T: + def load_capabilities(self: T, caps: dict[str, Any]) -> T: """Sets multiple capabilities""" for name, value in caps.items(): self.set_capability(name, value) return self @staticmethod - def as_w3c(capabilities: Dict) -> Dict: + def as_w3c(capabilities: dict) -> dict: """ Formats given capabilities to a valid W3C session request object @@ -109,7 +112,7 @@ def process_key(k: str) -> str: processed_caps = {process_key(k): v for k, v in copy.deepcopy(capabilities).items()} return {'capabilities': {'firstMatch': [{}], 'alwaysMatch': processed_caps}} - def to_w3c(self) -> Dict: + def to_w3c(self) -> dict: """ Formats the instance to a valid W3C session request object @@ -117,9 +120,9 @@ def to_w3c(self) -> Dict: """ return self.as_w3c(self.to_capabilities()) - def to_capabilities(self) -> Dict: + def to_capabilities(self) -> dict: return copy.copy(self._caps) @property - def default_capabilities(self) -> Dict: + def default_capabilities(self) -> dict: return {} diff --git a/appium/options/common/browser_name_option.py b/appium/options/common/browser_name_option.py index 2b107972a..fc5fec4ea 100644 --- a/appium/options/common/browser_name_option.py +++ b/appium/options/common/browser_name_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class BrowserNameOption(SupportsCapabilities): @property - def browser_name(self) -> Optional[str]: + def browser_name(self) -> str | None: """ The name of the browser to run the test on. """ diff --git a/appium/options/common/bundle_id_option.py b/appium/options/common/bundle_id_option.py index 0546571a5..1a09ed939 100644 --- a/appium/options/common/bundle_id_option.py +++ b/appium/options/common/bundle_id_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class BundleIdOption(SupportsCapabilities): @property - def bundle_id(self) -> Optional[str]: + def bundle_id(self) -> str | None: """ The bundle identifier of the application to automate. """ diff --git a/appium/options/common/clear_system_files_option.py b/appium/options/common/clear_system_files_option.py index 208c4bb96..2614fb36f 100644 --- a/appium/options/common/clear_system_files_option.py +++ b/appium/options/common/clear_system_files_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ClearSystemFilesOption(SupportsCapabilities): @property - def clear_system_files(self) -> Optional[bool]: + def clear_system_files(self) -> bool | None: """ Whether the driver should delete generated files at the end of a session. """ diff --git a/appium/options/common/device_name_option.py b/appium/options/common/device_name_option.py index 8e33cce39..72b952957 100644 --- a/appium/options/common/device_name_option.py +++ b/appium/options/common/device_name_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class DeviceNameOption(SupportsCapabilities): @property - def device_name(self) -> Optional[str]: + def device_name(self) -> str | None: """ The name of the device. """ diff --git a/appium/options/common/enable_performance_logging_option.py b/appium/options/common/enable_performance_logging_option.py index 22a4bdb30..f95b249ec 100644 --- a/appium/options/common/enable_performance_logging_option.py +++ b/appium/options/common/enable_performance_logging_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class EnablePerformanceLoggingOption(SupportsCapabilities): @property - def enable_performance_logging(self) -> Optional[bool]: + def enable_performance_logging(self) -> bool | None: """ Whether to enable additional performance logging. """ diff --git a/appium/options/common/event_timings_option.py b/appium/options/common/event_timings_option.py index b9c0a1245..f2e09b48e 100644 --- a/appium/options/common/event_timings_option.py +++ b/appium/options/common/event_timings_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class EventTimingsOption(SupportsCapabilities): @property - def event_timings(self) -> Optional[bool]: + def event_timings(self) -> bool | None: """ Whether the driver should to report the timings for various Appium-internal events. diff --git a/appium/options/common/full_reset_option.py b/appium/options/common/full_reset_option.py index aee86d7db..2e8b73be6 100644 --- a/appium/options/common/full_reset_option.py +++ b/appium/options/common/full_reset_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class FullResetOption(SupportsCapabilities): @property - def full_reset(self) -> Optional[bool]: + def full_reset(self) -> bool | None: """ Whether the driver should perform a full reset. """ diff --git a/appium/options/common/is_headless_option.py b/appium/options/common/is_headless_option.py index bc0c2b110..19830ceb3 100644 --- a/appium/options/common/is_headless_option.py +++ b/appium/options/common/is_headless_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class IsHeadlessOption(SupportsCapabilities): @property - def is_headless(self) -> Optional[bool]: + def is_headless(self) -> bool | None: """ Whether the driver should start emulator/simulator in headless mode. """ diff --git a/appium/options/common/language_option.py b/appium/options/common/language_option.py index f82de63d0..b176218f6 100644 --- a/appium/options/common/language_option.py +++ b/appium/options/common/language_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class LanguageOption(SupportsCapabilities): @property - def language(self) -> Optional[str]: + def language(self) -> str | None: """ Language abbreviation to use in a test session. """ diff --git a/appium/options/common/locale_option.py b/appium/options/common/locale_option.py index 58503a890..571dad571 100644 --- a/appium/options/common/locale_option.py +++ b/appium/options/common/locale_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class LocaleOption(SupportsCapabilities): @property - def locale(self) -> Optional[str]: + def locale(self) -> str | None: """ Locale abbreviation to use in a test session. """ diff --git a/appium/options/common/new_command_timeout_option.py b/appium/options/common/new_command_timeout_option.py index 377ef7193..79c9d4b34 100644 --- a/appium/options/common/new_command_timeout_option.py +++ b/appium/options/common/new_command_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from .supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class NewCommandTimeoutOption(SupportsCapabilities): @property - def new_command_timeout(self) -> Optional[timedelta]: + def new_command_timeout(self) -> timedelta | None: """ The allowed time before seeing a new server command. """ @@ -33,7 +32,7 @@ def new_command_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(seconds=value) @new_command_timeout.setter - def new_command_timeout(self, value: Union[timedelta, int]) -> None: + def new_command_timeout(self, value: timedelta | int) -> None: """ Set the allowed time before seeing a new server command. The value could either be provided as timedelta instance or an integer number of seconds. diff --git a/appium/options/common/no_reset_option.py b/appium/options/common/no_reset_option.py index ee2dd9988..9b6f3e926 100644 --- a/appium/options/common/no_reset_option.py +++ b/appium/options/common/no_reset_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class NoResetOption(SupportsCapabilities): @property - def no_reset(self) -> Optional[bool]: + def no_reset(self) -> bool | None: """ Whether the driver should not perform a reset. """ diff --git a/appium/options/common/orientation_option.py b/appium/options/common/orientation_option.py index 4141a4d90..54c7e031d 100644 --- a/appium/options/common/orientation_option.py +++ b/appium/options/common/orientation_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class OrientationOption(SupportsCapabilities): @property - def orientation(self) -> Optional[str]: + def orientation(self) -> str | None: """ The orientation of the device's screen. Usually this is either 'PORTRAIT' or 'LANDSCAPE'. diff --git a/appium/options/common/other_apps_option.py b/appium/options/common/other_apps_option.py index 6efbbbc4e..b1569f193 100644 --- a/appium/options/common/other_apps_option.py +++ b/appium/options/common/other_apps_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class OtherAppsOption(SupportsCapabilities): @property - def other_apps(self) -> Optional[str]: + def other_apps(self) -> str | None: """ Locations of apps to install before running a test. """ diff --git a/appium/options/common/platform_version_option.py b/appium/options/common/platform_version_option.py index d237cc280..4baf6b66c 100644 --- a/appium/options/common/platform_version_option.py +++ b/appium/options/common/platform_version_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class PlatformVersionOption(SupportsCapabilities): @property - def platform_version(self) -> Optional[str]: + def platform_version(self) -> str | None: """ The platform version of an emulator or a real device. This capability is used for device autodetection if udid is not provided. diff --git a/appium/options/common/postrun_option.py b/appium/options/common/postrun_option.py index f940cd6b6..5a965d8f8 100644 --- a/appium/options/common/postrun_option.py +++ b/appium/options/common/postrun_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict, Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class PostrunOption(SupportsCapabilities): @property - def postrun(self) -> Optional[Dict[str, str]]: + def postrun(self) -> dict[str, str] | None: """ System script which is supposed to be executed upon driver session quit. @@ -32,7 +31,7 @@ def postrun(self) -> Optional[Dict[str, str]]: return self.get_capability(POSTRUN) @postrun.setter - def postrun(self, value: Dict[str, str]) -> None: + def postrun(self, value: dict[str, str]) -> None: """ Set a system script to execute upon driver session quit. """ diff --git a/appium/options/common/prerun_option.py b/appium/options/common/prerun_option.py index 139874c76..a718d6740 100644 --- a/appium/options/common/prerun_option.py +++ b/appium/options/common/prerun_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict, Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class PrerunOption(SupportsCapabilities): @property - def prerun(self) -> Optional[Dict[str, str]]: + def prerun(self) -> dict[str, str] | None: """ System script which is supposed to be executed before a driver session is initialised. @@ -32,7 +31,7 @@ def prerun(self) -> Optional[Dict[str, str]]: return self.get_capability(PRERUN) @prerun.setter - def prerun(self, value: Dict[str, str]) -> None: + def prerun(self, value: dict[str, str]) -> None: """ Set a system script which is supposed to be executed before a driver session is initialised. diff --git a/appium/options/common/print_page_source_on_find_failure_option.py b/appium/options/common/print_page_source_on_find_failure_option.py index b93f07cf5..b97fbc8a1 100644 --- a/appium/options/common/print_page_source_on_find_failure_option.py +++ b/appium/options/common/print_page_source_on_find_failure_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class PrintPageSourceOnFindFailureOption(SupportsCapabilities): @property - def print_page_source_on_find_failure(self) -> Optional[bool]: + def print_page_source_on_find_failure(self) -> bool | None: """ Whether the driver should print the page source to the log if a find failure occurs. diff --git a/appium/options/common/skip_log_capture_option.py b/appium/options/common/skip_log_capture_option.py index 668704e13..522bc1079 100644 --- a/appium/options/common/skip_log_capture_option.py +++ b/appium/options/common/skip_log_capture_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SkipLogCaptureOption(SupportsCapabilities): @property - def skip_log_capture(self) -> Optional[bool]: + def skip_log_capture(self) -> bool | None: """ Whether the driver should not record device logs. """ diff --git a/appium/options/common/system_host_option.py b/appium/options/common/system_host_option.py index 0544de5ca..57d502b75 100644 --- a/appium/options/common/system_host_option.py +++ b/appium/options/common/system_host_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SystemHostOption(SupportsCapabilities): @property - def system_host(self) -> Optional[str]: + def system_host(self) -> str | None: """ The name of the host for the internal server to listen on. """ diff --git a/appium/options/common/system_port_option.py b/appium/options/common/system_port_option.py index e11f3b59d..fef871e38 100644 --- a/appium/options/common/system_port_option.py +++ b/appium/options/common/system_port_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SystemPortOption(SupportsCapabilities): @property - def system_port(self) -> Optional[int]: + def system_port(self) -> int | None: """ The number of the port for the internal server to listen on. """ diff --git a/appium/options/common/udid_option.py b/appium/options/common/udid_option.py index f760a1d21..97f703c96 100644 --- a/appium/options/common/udid_option.py +++ b/appium/options/common/udid_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from .supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UdidOption(SupportsCapabilities): @property - def udid(self) -> Optional[str]: + def udid(self) -> str | None: """ The unique identifier of the device under test. """ diff --git a/appium/options/flutter_integration/__init__.py b/appium/options/flutter_integration/__init__.py index ba044a8aa..731671682 100644 --- a/appium/options/flutter_integration/__init__.py +++ b/appium/options/flutter_integration/__init__.py @@ -13,3 +13,5 @@ # limitations under the License. from .base import FlutterOptions + +__all__ = ['FlutterOptions'] diff --git a/appium/options/flutter_integration/base.py b/appium/options/flutter_integration/base.py index f67b9a93c..6854197af 100644 --- a/appium/options/flutter_integration/base.py +++ b/appium/options/flutter_integration/base.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict from appium.options.common.automation_name_option import AUTOMATION_NAME from appium.options.common.base import AppiumOptions @@ -33,7 +32,7 @@ class FlutterOptions( FlutterSystemPortOption, ): @property - def default_capabilities(self) -> Dict: + def default_capabilities(self) -> dict: return { AUTOMATION_NAME: 'FlutterIntegration', } diff --git a/appium/options/flutter_integration/flutter_element_wait_timeout_option.py b/appium/options/flutter_integration/flutter_element_wait_timeout_option.py index bd4279774..d367be1cd 100644 --- a/appium/options/flutter_integration/flutter_element_wait_timeout_option.py +++ b/appium/options/flutter_integration/flutter_element_wait_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class FlutterElementWaitTimeOutOption(SupportsCapabilities): @property - def flutter_element_wait_timeout(self) -> Optional[timedelta]: + def flutter_element_wait_timeout(self) -> timedelta | None: """ Maximum timeout to wait for element for Flutter integration test @@ -35,7 +34,7 @@ def flutter_element_wait_timeout(self) -> Optional[timedelta]: return self.get_capability(FLUTTER_ELEMENT_WAIT_TIMEOUT) @flutter_element_wait_timeout.setter - def flutter_element_wait_timeout(self, value: Union[timedelta, int]) -> None: + def flutter_element_wait_timeout(self, value: timedelta | int) -> None: """ Sets the maximum timeout to wait for a Flutter element in an integration test. Default timeout is 5000ms diff --git a/appium/options/flutter_integration/flutter_server_launch_timeout_option.py b/appium/options/flutter_integration/flutter_server_launch_timeout_option.py index 32cea2f94..d387c3c14 100644 --- a/appium/options/flutter_integration/flutter_server_launch_timeout_option.py +++ b/appium/options/flutter_integration/flutter_server_launch_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class FlutterServerLaunchTimeOutOption(SupportsCapabilities): @property - def flutter_server_launch_timeout(self) -> Optional[timedelta]: + def flutter_server_launch_timeout(self) -> timedelta | None: """ Gets the current timeout for launching the Flutter server in a Flutter application. @@ -36,7 +35,7 @@ def flutter_server_launch_timeout(self) -> Optional[timedelta]: return self.get_capability(FLUTTER_SERVER_LAUNCH_TIMEOUT) @flutter_server_launch_timeout.setter - def flutter_server_launch_timeout(self, value: Union[timedelta, int]) -> None: + def flutter_server_launch_timeout(self, value: timedelta | int) -> None: """ Sets the timeout for launching the Flutter server in Flutter application. Default timeout is 5000ms diff --git a/appium/options/flutter_integration/flutter_system_port_option.py b/appium/options/flutter_integration/flutter_system_port_option.py index db7ab7f54..b71a28a7c 100644 --- a/appium/options/flutter_integration/flutter_system_port_option.py +++ b/appium/options/flutter_integration/flutter_system_port_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class FlutterSystemPortOption(SupportsCapabilities): @property - def flutter_system_port(self) -> Optional[int]: + def flutter_system_port(self) -> int | None: """ Get flutter system port for Flutter integration tests. diff --git a/appium/options/gecko/__init__.py b/appium/options/gecko/__init__.py index 1dfd32877..3ad9508a6 100644 --- a/appium/options/gecko/__init__.py +++ b/appium/options/gecko/__init__.py @@ -1 +1,3 @@ from .base import GeckoOptions + +__all__ = ['GeckoOptions'] diff --git a/appium/options/gecko/android_storage_option.py b/appium/options/gecko/android_storage_option.py index 1209ac501..9827ce25a 100644 --- a/appium/options/gecko/android_storage_option.py +++ b/appium/options/gecko/android_storage_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AndroidStorageOption(SupportsCapabilities): @property - def android_storage(self) -> Optional[str]: + def android_storage(self) -> str | None: """ The currently set storage type. """ diff --git a/appium/options/gecko/base.py b/appium/options/gecko/base.py index 873e5646a..dc4723e2e 100644 --- a/appium/options/gecko/base.py +++ b/appium/options/gecko/base.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict from appium.options.common.automation_name_option import AUTOMATION_NAME from appium.options.common.base import AppiumOptions @@ -45,7 +44,7 @@ def system_port(self, value: int) -> None: SystemPortOption.system_port.fset(self, value) # type: ignore @property - def default_capabilities(self) -> Dict: + def default_capabilities(self) -> dict: return { AUTOMATION_NAME: 'Gecko', } diff --git a/appium/options/gecko/firefox_options_option.py b/appium/options/gecko/firefox_options_option.py index 87906b4bb..da3206cff 100644 --- a/appium/options/gecko/firefox_options_option.py +++ b/appium/options/gecko/firefox_options_option.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from typing import Any, Dict, Optional +from typing import Any from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +24,14 @@ class FirefoxOptionsOption(SupportsCapabilities): @property - def firefox_options(self) -> Optional[Dict[str, Any]]: + def firefox_options(self) -> dict[str, Any] | None: """ Firefox options mapping. """ return self.get_capability(FIREFOX_OPTIONS) @firefox_options.setter - def firefox_options(self, value: Dict[str, Any]) -> None: + def firefox_options(self, value: dict[str, Any]) -> None: """ See https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities/firefoxOptions """ diff --git a/appium/options/gecko/marionette_port_option.py b/appium/options/gecko/marionette_port_option.py index 24846fd76..ac9e4071a 100644 --- a/appium/options/gecko/marionette_port_option.py +++ b/appium/options/gecko/marionette_port_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class MarionettePortOption(SupportsCapabilities): @property - def marionette_port(self) -> Optional[int]: + def marionette_port(self) -> int | None: """ The number of the port for the Marionette server to listen on. """ diff --git a/appium/options/gecko/verbosity_option.py b/appium/options/gecko/verbosity_option.py index 9888ddf2d..4b6b6548f 100644 --- a/appium/options/gecko/verbosity_option.py +++ b/appium/options/gecko/verbosity_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class VerbosityOption(SupportsCapabilities): @property - def verbosity(self) -> Optional[str]: + def verbosity(self) -> str | None: """ The verbosity level of driver logging. """ diff --git a/appium/options/ios/__init__.py b/appium/options/ios/__init__.py index 21e82f751..e38c958d0 100644 --- a/appium/options/ios/__init__.py +++ b/appium/options/ios/__init__.py @@ -1,2 +1,4 @@ from .safari.base import SafariOptions from .xcuitest.base import XCUITestOptions + +__all__ = ['SafariOptions', 'XCUITestOptions'] diff --git a/appium/options/ios/safari/automatic_inspection_option.py b/appium/options/ios/safari/automatic_inspection_option.py index 3ab38e82d..a92039fa0 100644 --- a/appium/options/ios/safari/automatic_inspection_option.py +++ b/appium/options/ios/safari/automatic_inspection_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AutomaticInspectionOption(SupportsCapabilities): @property - def automatic_inspection(self) -> Optional[bool]: + def automatic_inspection(self) -> bool | None: """ Whether to use automatic inspection. """ diff --git a/appium/options/ios/safari/automatic_profiling_option.py b/appium/options/ios/safari/automatic_profiling_option.py index 76eae6206..67a81a9b1 100644 --- a/appium/options/ios/safari/automatic_profiling_option.py +++ b/appium/options/ios/safari/automatic_profiling_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AutomaticProfilingOption(SupportsCapabilities): @property - def automatic_profiling(self) -> Optional[bool]: + def automatic_profiling(self) -> bool | None: """ Whether to use automatic profiling. """ diff --git a/appium/options/ios/safari/base.py b/appium/options/ios/safari/base.py index 8c6cfa685..f46bc9f59 100644 --- a/appium/options/ios/safari/base.py +++ b/appium/options/ios/safari/base.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict from appium.options.common.automation_name_option import AUTOMATION_NAME from appium.options.common.base import PLATFORM_NAME, AppiumOptions @@ -44,7 +43,7 @@ class SafariOptions( WebkitWebrtcOption, ): @property - def default_capabilities(self) -> Dict: + def default_capabilities(self) -> dict: return { PLATFORM_NAME: 'iOS', AUTOMATION_NAME: 'Safari', diff --git a/appium/options/ios/safari/device_name_option.py b/appium/options/ios/safari/device_name_option.py index ebc949ad8..28deafef3 100644 --- a/appium/options/ios/safari/device_name_option.py +++ b/appium/options/ios/safari/device_name_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class DeviceNameOption(SupportsCapabilities): @property - def device_name(self) -> Optional[str]: + def device_name(self) -> str | None: """ String representing the name of the device. """ diff --git a/appium/options/ios/safari/device_type_option.py b/appium/options/ios/safari/device_type_option.py index 329974e34..9071c6af4 100644 --- a/appium/options/ios/safari/device_type_option.py +++ b/appium/options/ios/safari/device_type_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class DeviceTypeOption(SupportsCapabilities): @property - def device_type(self) -> Optional[str]: + def device_type(self) -> str | None: """ String representing the type of the device. """ diff --git a/appium/options/ios/safari/device_udid_option.py b/appium/options/ios/safari/device_udid_option.py index 12850acfc..aec15d20a 100644 --- a/appium/options/ios/safari/device_udid_option.py +++ b/appium/options/ios/safari/device_udid_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class DeviceUdidOption(SupportsCapabilities): @property - def device_udid(self) -> Optional[str]: + def device_udid(self) -> str | None: """ String representing the UDID of the device. """ diff --git a/appium/options/ios/safari/platform_build_version_option.py b/appium/options/ios/safari/platform_build_version_option.py index f411ec22e..7454664a6 100644 --- a/appium/options/ios/safari/platform_build_version_option.py +++ b/appium/options/ios/safari/platform_build_version_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class PlatformBuildVersionOption(SupportsCapabilities): @property - def platform_build_version(self) -> Optional[str]: + def platform_build_version(self) -> str | None: """ String representing the platform build version. """ diff --git a/appium/options/ios/safari/platform_version_option.py b/appium/options/ios/safari/platform_version_option.py index fd3d4b60b..e53ef140f 100644 --- a/appium/options/ios/safari/platform_version_option.py +++ b/appium/options/ios/safari/platform_version_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class PlatformVersionOption(SupportsCapabilities): @property - def platform_version(self) -> Optional[str]: + def platform_version(self) -> str | None: """ String representing the platform version. """ diff --git a/appium/options/ios/safari/use_simulator_option.py b/appium/options/ios/safari/use_simulator_option.py index 25a09a6b0..91b9eb391 100644 --- a/appium/options/ios/safari/use_simulator_option.py +++ b/appium/options/ios/safari/use_simulator_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UseSimulatorOption(SupportsCapabilities): @property - def use_simulator(self) -> Optional[bool]: + def use_simulator(self) -> bool | None: """ Whether to use iOS Simulator. """ diff --git a/appium/options/ios/safari/webkit_webrtc_option.py b/appium/options/ios/safari/webkit_webrtc_option.py index 7980df7ab..ac0d4c976 100644 --- a/appium/options/ios/safari/webkit_webrtc_option.py +++ b/appium/options/ios/safari/webkit_webrtc_option.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from typing import Any, Dict, Optional +from typing import Any from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +24,14 @@ class WebkitWebrtcOption(SupportsCapabilities): @property - def webkit_webrtc(self) -> Optional[Dict[str, Any]]: + def webkit_webrtc(self) -> dict[str, Any] | None: """ WebRTC policies. """ return self.get_capability(WEBKIT_WEBRTC) @webkit_webrtc.setter - def webkit_webrtc(self, value: Dict[str, Any]) -> None: + def webkit_webrtc(self, value: dict[str, Any]) -> None: """ This option allows a test to temporarily change Safari's policies for WebRTC and Media Capture. diff --git a/appium/options/ios/xcuitest/app/app_install_strategy_option.py b/appium/options/ios/xcuitest/app/app_install_strategy_option.py index ff812fe86..3ce9f8554 100644 --- a/appium/options/ios/xcuitest/app/app_install_strategy_option.py +++ b/appium/options/ios/xcuitest/app/app_install_strategy_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppInstallStrategyOption(SupportsCapabilities): @property - def app_install_strategy(self) -> Optional[str]: + def app_install_strategy(self) -> str | None: """ App install strategy. """ diff --git a/appium/options/ios/xcuitest/app/app_push_timeout_option.py b/appium/options/ios/xcuitest/app/app_push_timeout_option.py index 3f49bde96..a135b853b 100644 --- a/appium/options/ios/xcuitest/app/app_push_timeout_option.py +++ b/appium/options/ios/xcuitest/app/app_push_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class AppPushTimeoutOption(SupportsCapabilities): @property - def app_push_timeout(self) -> Optional[timedelta]: + def app_push_timeout(self) -> timedelta | None: """ Maximum timeout for application upload. """ @@ -33,7 +32,7 @@ def app_push_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @app_push_timeout.setter - def app_push_timeout(self, value: Union[timedelta, int]) -> None: + def app_push_timeout(self, value: timedelta | int) -> None: """ The timeout for application upload. Works for real devices only. diff --git a/appium/options/ios/xcuitest/app/localizable_strings_dir_option.py b/appium/options/ios/xcuitest/app/localizable_strings_dir_option.py index e78155a6c..21c985e49 100644 --- a/appium/options/ios/xcuitest/app/localizable_strings_dir_option.py +++ b/appium/options/ios/xcuitest/app/localizable_strings_dir_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class LocalizableStringsDirOption(SupportsCapabilities): @property - def localizable_strings_dir(self) -> Optional[str]: + def localizable_strings_dir(self) -> str | None: """ Resource folder name where the main locale strings are stored. """ diff --git a/appium/options/ios/xcuitest/base.py b/appium/options/ios/xcuitest/base.py index 02143a095..75ad7aab4 100644 --- a/appium/options/ios/xcuitest/base.py +++ b/appium/options/ios/xcuitest/base.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict from appium.options.common.app_option import AppOption from appium.options.common.auto_web_view_option import AutoWebViewOption @@ -72,6 +71,7 @@ from .wda.keychain_path_option import KeychainPathOption from .wda.max_typing_frequency_option import MaxTypingFrequencyOption from .wda.mjpeg_server_port_option import MjpegServerPortOption +from .wda.prebuilt_wda_path_option import PrebuiltWdaPathOption from .wda.process_arguments_option import ProcessArgumentsOption from .wda.result_bundle_path_option import ResultBundlePathOption from .wda.screenshot_quality_option import ScreenshotQualityOption @@ -83,6 +83,7 @@ from .wda.use_native_caching_strategy_option import UseNativeCachingStrategyOption from .wda.use_new_wda_option import UseNewWdaOption from .wda.use_prebuilt_wda_option import UsePrebuiltWdaOption +from .wda.use_preinstalled_wda_option import UsePreinstalledWdaOption from .wda.use_simple_build_test_option import UseSimpleBuildTestOption from .wda.use_xctestrun_file_option import UseXctestrunFileOption from .wda.wait_for_idle_timeout_option import WaitForIdleTimeoutOption @@ -171,6 +172,7 @@ class XCUITestOptions( KeychainPathOption, MaxTypingFrequencyOption, MjpegServerPortOption, + PrebuiltWdaPathOption, ProcessArgumentsOption, ResultBundlePathOption, ScreenshotQualityOption, @@ -182,6 +184,7 @@ class XCUITestOptions( UseNativeCachingStrategyOption, UseNewWdaOption, UsePrebuiltWdaOption, + UsePreinstalledWdaOption, UseSimpleBuildTestOption, UseXctestrunFileOption, WaitForIdleTimeoutOption, @@ -216,7 +219,7 @@ class XCUITestOptions( WebviewConnectTimeoutOption, ): @property - def default_capabilities(self) -> Dict: + def default_capabilities(self) -> dict: return { AUTOMATION_NAME: 'XCUITest', PLATFORM_NAME: 'iOS', diff --git a/appium/options/ios/xcuitest/general/include_device_caps_to_session_info_option.py b/appium/options/ios/xcuitest/general/include_device_caps_to_session_info_option.py index b5df6d286..388f90ccd 100644 --- a/appium/options/ios/xcuitest/general/include_device_caps_to_session_info_option.py +++ b/appium/options/ios/xcuitest/general/include_device_caps_to_session_info_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class IncludeDeviceCapsToSessionInfoOption(SupportsCapabilities): @property - def include_device_caps_to_session_info(self) -> Optional[bool]: + def include_device_caps_to_session_info(self) -> bool | None: """ Whether to include screen information as the result of Get Session Capabilities. """ diff --git a/appium/options/ios/xcuitest/general/reset_location_service_option.py b/appium/options/ios/xcuitest/general/reset_location_service_option.py index c9e242cc5..0c70dee46 100644 --- a/appium/options/ios/xcuitest/general/reset_location_service_option.py +++ b/appium/options/ios/xcuitest/general/reset_location_service_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ResetLocationServiceOption(SupportsCapabilities): @property - def reset_location_service(self) -> Optional[bool]: + def reset_location_service(self) -> bool | None: """ Whether to reset the location service in the session deletion on real devices. """ diff --git a/appium/options/ios/xcuitest/other/command_timeouts_option.py b/appium/options/ios/xcuitest/other/command_timeouts_option.py index 420b35039..f48c52de2 100644 --- a/appium/options/ios/xcuitest/other/command_timeouts_option.py +++ b/appium/options/ios/xcuitest/other/command_timeouts_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Dict, Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class CommandTimeoutsOption(SupportsCapabilities): @property - def command_timeouts(self) -> Optional[Union[Dict[str, timedelta], timedelta]]: + def command_timeouts(self) -> dict[str, timedelta] | timedelta | None: """ Custom timeout(s) for WDA backend commands execution. """ @@ -37,7 +36,7 @@ def command_timeouts(self) -> Optional[Union[Dict[str, timedelta], timedelta]]: return timedelta(milliseconds=int(value)) @command_timeouts.setter - def command_timeouts(self, value: Union[Dict[str, timedelta], timedelta, int]) -> None: + def command_timeouts(self, value: dict[str, timedelta] | timedelta | int) -> None: """ Custom timeout for all WDA backend commands execution. This might be useful if WDA backend freezes unexpectedly or requires too diff --git a/appium/options/ios/xcuitest/other/launch_with_idb_option.py b/appium/options/ios/xcuitest/other/launch_with_idb_option.py index c8701c620..9a2a99d8b 100644 --- a/appium/options/ios/xcuitest/other/launch_with_idb_option.py +++ b/appium/options/ios/xcuitest/other/launch_with_idb_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class LaunchWithIdbOption(SupportsCapabilities): @property - def launch_with_idb(self) -> Optional[bool]: + def launch_with_idb(self) -> bool | None: """ Whether to launch WebDriverAgentRunner with idb instead of xcodebuild. """ diff --git a/appium/options/ios/xcuitest/other/show_ios_log_option.py b/appium/options/ios/xcuitest/other/show_ios_log_option.py index b4bf75d3a..fba71a83a 100644 --- a/appium/options/ios/xcuitest/other/show_ios_log_option.py +++ b/appium/options/ios/xcuitest/other/show_ios_log_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ShowIosLogOption(SupportsCapabilities): @property - def show_ios_log(self) -> Optional[bool]: + def show_ios_log(self) -> bool | None: """ Whether to show any logs captured from a device in the appium logs. """ diff --git a/appium/options/ios/xcuitest/other/use_json_source_option.py b/appium/options/ios/xcuitest/other/use_json_source_option.py index 1eac50bb8..48b8d20a5 100644 --- a/appium/options/ios/xcuitest/other/use_json_source_option.py +++ b/appium/options/ios/xcuitest/other/use_json_source_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UseJsonSourceOption(SupportsCapabilities): @property - def use_json_source(self) -> Optional[bool]: + def use_json_source(self) -> bool | None: """ Whether to get JSON source from WDA and transform it to XML on the driver side. """ diff --git a/appium/options/ios/xcuitest/simulator/calendar_access_authorized_option.py b/appium/options/ios/xcuitest/simulator/calendar_access_authorized_option.py index a0e1afe9b..a9a4e08a1 100644 --- a/appium/options/ios/xcuitest/simulator/calendar_access_authorized_option.py +++ b/appium/options/ios/xcuitest/simulator/calendar_access_authorized_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class CalendarAccessAuthorizedOption(SupportsCapabilities): @property - def calendar_access_authorized(self) -> Optional[bool]: + def calendar_access_authorized(self) -> bool | None: """ Whether to enable calendar access on IOS Simulator. """ diff --git a/appium/options/ios/xcuitest/simulator/calendar_format_option.py b/appium/options/ios/xcuitest/simulator/calendar_format_option.py index 4e7565987..2d5c96519 100644 --- a/appium/options/ios/xcuitest/simulator/calendar_format_option.py +++ b/appium/options/ios/xcuitest/simulator/calendar_format_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class CalendarFormatOption(SupportsCapabilities): @property - def calendar_format(self) -> Optional[str]: + def calendar_format(self) -> str | None: """ Calendar format for the iOS Simulator. """ diff --git a/appium/options/ios/xcuitest/simulator/connect_hardware_keyboard_option.py b/appium/options/ios/xcuitest/simulator/connect_hardware_keyboard_option.py index f7118d6de..944a22627 100644 --- a/appium/options/ios/xcuitest/simulator/connect_hardware_keyboard_option.py +++ b/appium/options/ios/xcuitest/simulator/connect_hardware_keyboard_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ConnectHardwareKeyboardOption(SupportsCapabilities): @property - def connect_hardware_keyboard(self) -> Optional[bool]: + def connect_hardware_keyboard(self) -> bool | None: """ Whether to connect hardware keyboard to Simulator. """ diff --git a/appium/options/ios/xcuitest/simulator/custom_ssl_cert_option.py b/appium/options/ios/xcuitest/simulator/custom_ssl_cert_option.py index a3914b939..131e04283 100644 --- a/appium/options/ios/xcuitest/simulator/custom_ssl_cert_option.py +++ b/appium/options/ios/xcuitest/simulator/custom_ssl_cert_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class CustomSslCertOption(SupportsCapabilities): @property - def custom_ssl_cert(self) -> Optional[str]: + def custom_ssl_cert(self) -> str | None: """ SSL certificate content. """ diff --git a/appium/options/ios/xcuitest/simulator/enforce_fresh_simulator_creation_option.py b/appium/options/ios/xcuitest/simulator/enforce_fresh_simulator_creation_option.py index cea87eb05..ceb44d376 100644 --- a/appium/options/ios/xcuitest/simulator/enforce_fresh_simulator_creation_option.py +++ b/appium/options/ios/xcuitest/simulator/enforce_fresh_simulator_creation_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class EnforceFreshSimulatorCreationOption(SupportsCapabilities): @property - def enforce_fresh_simulator_creation(self) -> Optional[bool]: + def enforce_fresh_simulator_creation(self) -> bool | None: """ Whether to create a new simulator for each new test session. """ diff --git a/appium/options/ios/xcuitest/simulator/force_simulator_software_keyboard_presence_option.py b/appium/options/ios/xcuitest/simulator/force_simulator_software_keyboard_presence_option.py index 1e1a697aa..62915e91b 100644 --- a/appium/options/ios/xcuitest/simulator/force_simulator_software_keyboard_presence_option.py +++ b/appium/options/ios/xcuitest/simulator/force_simulator_software_keyboard_presence_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ForceSimulatorSoftwareKeyboardPresenceOption(SupportsCapabilities): @property - def force_simulator_software_keyboard_presence(self) -> Optional[bool]: + def force_simulator_software_keyboard_presence(self) -> bool | None: """ Whether to enforce software keyboard presence. """ diff --git a/appium/options/ios/xcuitest/simulator/ios_simulator_logs_predicate_option.py b/appium/options/ios/xcuitest/simulator/ios_simulator_logs_predicate_option.py index c7d486477..6e67354aa 100644 --- a/appium/options/ios/xcuitest/simulator/ios_simulator_logs_predicate_option.py +++ b/appium/options/ios/xcuitest/simulator/ios_simulator_logs_predicate_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class IosSimulatorLogsPredicateOption(SupportsCapabilities): @property - def ios_simulator_logs_predicate(self) -> Optional[bool]: + def ios_simulator_logs_predicate(self) -> bool | None: """ Get Simulator log filtering predicate. """ diff --git a/appium/options/ios/xcuitest/simulator/keep_key_chains_option.py b/appium/options/ios/xcuitest/simulator/keep_key_chains_option.py index a304c935e..9395b30b1 100644 --- a/appium/options/ios/xcuitest/simulator/keep_key_chains_option.py +++ b/appium/options/ios/xcuitest/simulator/keep_key_chains_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class KeepKeyChainsOption(SupportsCapabilities): @property - def keep_key_chains(self) -> Optional[bool]: + def keep_key_chains(self) -> bool | None: """ Whether to preserve Simulator keychains after full reset. """ diff --git a/appium/options/ios/xcuitest/simulator/keychains_exclude_patterns_option.py b/appium/options/ios/xcuitest/simulator/keychains_exclude_patterns_option.py index d971f5c5c..ddfba4223 100644 --- a/appium/options/ios/xcuitest/simulator/keychains_exclude_patterns_option.py +++ b/appium/options/ios/xcuitest/simulator/keychains_exclude_patterns_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class KeychainsExcludePatternsOption(SupportsCapabilities): @property - def keychains_exclude_patterns(self) -> Optional[str]: + def keychains_exclude_patterns(self) -> str | None: """ Keychains exclude patterns. """ diff --git a/appium/options/ios/xcuitest/simulator/permissions_option.py b/appium/options/ios/xcuitest/simulator/permissions_option.py index 6146e382b..1957273d6 100644 --- a/appium/options/ios/xcuitest/simulator/permissions_option.py +++ b/appium/options/ios/xcuitest/simulator/permissions_option.py @@ -16,7 +16,6 @@ # under the License. import json -from typing import Dict, Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class PermissionsOption(SupportsCapabilities): @property - def permissions(self) -> Optional[Dict[str, Dict[str, str]]]: + def permissions(self) -> dict[str, dict[str, str]] | None: """ Get Simulator permissions. """ @@ -33,7 +32,7 @@ def permissions(self) -> Optional[Dict[str, Dict[str, str]]]: return None if value is None else json.loads(value) @permissions.setter - def permissions(self, value: Dict[str, Dict[str, str]]) -> None: + def permissions(self, value: dict[str, dict[str, str]]) -> None: """ Allows setting of permissions for the specified application bundle on Simulator only. diff --git a/appium/options/ios/xcuitest/simulator/reduce_motion_option.py b/appium/options/ios/xcuitest/simulator/reduce_motion_option.py index 89dbe8779..29d0defb0 100644 --- a/appium/options/ios/xcuitest/simulator/reduce_motion_option.py +++ b/appium/options/ios/xcuitest/simulator/reduce_motion_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ReduceMotionOption(SupportsCapabilities): @property - def reduce_motion(self) -> Optional[bool]: + def reduce_motion(self) -> bool | None: """ Whether to reduce motion accessibility preference. """ diff --git a/appium/options/ios/xcuitest/simulator/reset_on_session_start_only_option.py b/appium/options/ios/xcuitest/simulator/reset_on_session_start_only_option.py index 294a72117..ce6b4d82f 100644 --- a/appium/options/ios/xcuitest/simulator/reset_on_session_start_only_option.py +++ b/appium/options/ios/xcuitest/simulator/reset_on_session_start_only_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ResetOnSessionStartOnlyOption(SupportsCapabilities): @property - def reset_on_session_start_only(self) -> Optional[bool]: + def reset_on_session_start_only(self) -> bool | None: """ Whether to perform Simulator reset on test session finish (false) or not (true). """ diff --git a/appium/options/ios/xcuitest/simulator/scale_factor_option.py b/appium/options/ios/xcuitest/simulator/scale_factor_option.py index 8b7e6e037..2d6b528b7 100644 --- a/appium/options/ios/xcuitest/simulator/scale_factor_option.py +++ b/appium/options/ios/xcuitest/simulator/scale_factor_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ScaleFactorOption(SupportsCapabilities): @property - def scale_factor(self) -> Optional[str]: + def scale_factor(self) -> str | None: """ Simulator scale factor. """ diff --git a/appium/options/ios/xcuitest/simulator/shutdown_other_simulators_option.py b/appium/options/ios/xcuitest/simulator/shutdown_other_simulators_option.py index a7c5edc51..60497919d 100644 --- a/appium/options/ios/xcuitest/simulator/shutdown_other_simulators_option.py +++ b/appium/options/ios/xcuitest/simulator/shutdown_other_simulators_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ShutdownOtherSimulatorsOption(SupportsCapabilities): @property - def shutdown_other_simulators(self) -> Optional[bool]: + def shutdown_other_simulators(self) -> bool | None: """ Whether to shut down of other booted simulators except of the current one. """ diff --git a/appium/options/ios/xcuitest/simulator/simulator_devices_set_path_option.py b/appium/options/ios/xcuitest/simulator/simulator_devices_set_path_option.py index 845575355..2ac9253e7 100644 --- a/appium/options/ios/xcuitest/simulator/simulator_devices_set_path_option.py +++ b/appium/options/ios/xcuitest/simulator/simulator_devices_set_path_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SimulatorDevicesSetPathOption(SupportsCapabilities): @property - def simulator_devices_set_path(self) -> Optional[str]: + def simulator_devices_set_path(self) -> str | None: """ Alternative path to the simulator devices set. """ diff --git a/appium/options/ios/xcuitest/simulator/simulator_pasteboard_automatic_sync_option.py b/appium/options/ios/xcuitest/simulator/simulator_pasteboard_automatic_sync_option.py index a1258df4e..435ea5aa8 100644 --- a/appium/options/ios/xcuitest/simulator/simulator_pasteboard_automatic_sync_option.py +++ b/appium/options/ios/xcuitest/simulator/simulator_pasteboard_automatic_sync_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SimulatorPasteboardAutomaticSyncOption(SupportsCapabilities): @property - def simulator_pasteboard_automatic_sync(self) -> Optional[bool]: + def simulator_pasteboard_automatic_sync(self) -> bool | None: """ Pasteboard automation sync state. """ diff --git a/appium/options/ios/xcuitest/simulator/simulator_startup_timeout_option.py b/appium/options/ios/xcuitest/simulator/simulator_startup_timeout_option.py index 29353498d..e282e229f 100644 --- a/appium/options/ios/xcuitest/simulator/simulator_startup_timeout_option.py +++ b/appium/options/ios/xcuitest/simulator/simulator_startup_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class SimulatorStartupTimeoutOption(SupportsCapabilities): @property - def simulator_startup_timeout(self) -> Optional[timedelta]: + def simulator_startup_timeout(self) -> timedelta | None: """ Simulator startup timeout. """ @@ -33,7 +32,7 @@ def simulator_startup_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @simulator_startup_timeout.setter - def simulator_startup_timeout(self, value: Union[timedelta, int]) -> None: + def simulator_startup_timeout(self, value: timedelta | int) -> None: """ Allows to change the default timeout for Simulator startup. By default, this value is set to 120000ms (2 minutes), diff --git a/appium/options/ios/xcuitest/simulator/simulator_trace_pointer_option.py b/appium/options/ios/xcuitest/simulator/simulator_trace_pointer_option.py index d5f5d1fd8..508cad64f 100644 --- a/appium/options/ios/xcuitest/simulator/simulator_trace_pointer_option.py +++ b/appium/options/ios/xcuitest/simulator/simulator_trace_pointer_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SimulatorTracePointerOption(SupportsCapabilities): @property - def simulator_trace_pointer(self) -> Optional[bool]: + def simulator_trace_pointer(self) -> bool | None: """ Whether to highlight pointer moves in the Simulator window. """ diff --git a/appium/options/ios/xcuitest/simulator/simulator_window_center_option.py b/appium/options/ios/xcuitest/simulator/simulator_window_center_option.py index 1f8b2d8b8..85c06c9a1 100644 --- a/appium/options/ios/xcuitest/simulator/simulator_window_center_option.py +++ b/appium/options/ios/xcuitest/simulator/simulator_window_center_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SimulatorWindowCenterOption(SupportsCapabilities): @property - def simulator_window_center(self) -> Optional[str]: + def simulator_window_center(self) -> str | None: """ Simulator window center coordinates. """ diff --git a/appium/options/ios/xcuitest/wda/allow_provisioning_device_regitration_option.py b/appium/options/ios/xcuitest/wda/allow_provisioning_device_regitration_option.py index c88124b4c..504cebf30 100644 --- a/appium/options/ios/xcuitest/wda/allow_provisioning_device_regitration_option.py +++ b/appium/options/ios/xcuitest/wda/allow_provisioning_device_regitration_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AllowProvisioningDeviceRegistrationOption(SupportsCapabilities): @property - def allow_provisioning_device_registration(self) -> Optional[bool]: + def allow_provisioning_device_registration(self) -> bool | None: """ Whether to allow xcodebuild to register your destination device on the developer portal. """ diff --git a/appium/options/ios/xcuitest/wda/auto_accept_alerts_option.py b/appium/options/ios/xcuitest/wda/auto_accept_alerts_option.py index 05c55943e..59378a857 100644 --- a/appium/options/ios/xcuitest/wda/auto_accept_alerts_option.py +++ b/appium/options/ios/xcuitest/wda/auto_accept_alerts_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AutoAcceptAlertsOption(SupportsCapabilities): @property - def auto_accept_alerts(self) -> Optional[bool]: + def auto_accept_alerts(self) -> bool | None: """ Whether to accept all alerts automatically. """ diff --git a/appium/options/ios/xcuitest/wda/auto_disimiss_alerts_option.py b/appium/options/ios/xcuitest/wda/auto_disimiss_alerts_option.py index 61a28414c..1900274c7 100644 --- a/appium/options/ios/xcuitest/wda/auto_disimiss_alerts_option.py +++ b/appium/options/ios/xcuitest/wda/auto_disimiss_alerts_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AutoDismissAlertsOption(SupportsCapabilities): @property - def auto_dismiss_alerts(self) -> Optional[bool]: + def auto_dismiss_alerts(self) -> bool | None: """ Whether to dismiss all alerts automatically. """ diff --git a/appium/options/ios/xcuitest/wda/derived_data_path_option.py b/appium/options/ios/xcuitest/wda/derived_data_path_option.py index ffa40a682..063df5489 100644 --- a/appium/options/ios/xcuitest/wda/derived_data_path_option.py +++ b/appium/options/ios/xcuitest/wda/derived_data_path_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class DerivedDataPathOption(SupportsCapabilities): @property - def derived_data_path(self) -> Optional[str]: + def derived_data_path(self) -> str | None: """ Path to the derived data WDA folder. """ diff --git a/appium/options/ios/xcuitest/wda/disable_automatic_screenshots_option.py b/appium/options/ios/xcuitest/wda/disable_automatic_screenshots_option.py index ac76af330..ef17b5d63 100644 --- a/appium/options/ios/xcuitest/wda/disable_automatic_screenshots_option.py +++ b/appium/options/ios/xcuitest/wda/disable_automatic_screenshots_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class DisableAutomaticScreenshotsOption(SupportsCapabilities): @property - def disable_automatic_screenshots(self) -> Optional[bool]: + def disable_automatic_screenshots(self) -> bool | None: """ Whether to disable automatic XCTest screenshots. """ diff --git a/appium/options/ios/xcuitest/wda/force_app_launch_option.py b/appium/options/ios/xcuitest/wda/force_app_launch_option.py index 364133d03..ba2f5d04c 100644 --- a/appium/options/ios/xcuitest/wda/force_app_launch_option.py +++ b/appium/options/ios/xcuitest/wda/force_app_launch_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ForceAppLaunchOption(SupportsCapabilities): @property - def force_app_launch(self) -> Optional[bool]: + def force_app_launch(self) -> bool | None: """ Whether to enforce app restart on session startup. """ diff --git a/appium/options/ios/xcuitest/wda/keychain_password_option.py b/appium/options/ios/xcuitest/wda/keychain_password_option.py index 5514519f0..e0a2a0914 100644 --- a/appium/options/ios/xcuitest/wda/keychain_password_option.py +++ b/appium/options/ios/xcuitest/wda/keychain_password_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class KeychainPasswordOption(SupportsCapabilities): @property - def keychain_password(self) -> Optional[str]: + def keychain_password(self) -> str | None: """ Custom keychain password. """ diff --git a/appium/options/ios/xcuitest/wda/keychain_path_option.py b/appium/options/ios/xcuitest/wda/keychain_path_option.py index 5cf397426..a3b111d8d 100644 --- a/appium/options/ios/xcuitest/wda/keychain_path_option.py +++ b/appium/options/ios/xcuitest/wda/keychain_path_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class KeychainPathOption(SupportsCapabilities): @property - def keychain_path(self) -> Optional[str]: + def keychain_path(self) -> str | None: """ Path to a custom keychain. """ diff --git a/appium/options/ios/xcuitest/wda/max_typing_frequency_option.py b/appium/options/ios/xcuitest/wda/max_typing_frequency_option.py index d5ea8dea1..0a778c603 100644 --- a/appium/options/ios/xcuitest/wda/max_typing_frequency_option.py +++ b/appium/options/ios/xcuitest/wda/max_typing_frequency_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class MaxTypingFrequencyOption(SupportsCapabilities): @property - def max_typing_frequency(self) -> Optional[int]: + def max_typing_frequency(self) -> int | None: """ The number of keystrokes per minute. """ diff --git a/appium/options/ios/xcuitest/wda/mjpeg_server_port_option.py b/appium/options/ios/xcuitest/wda/mjpeg_server_port_option.py index 679c1af4a..dedd43ee0 100644 --- a/appium/options/ios/xcuitest/wda/mjpeg_server_port_option.py +++ b/appium/options/ios/xcuitest/wda/mjpeg_server_port_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class MjpegServerPortOption(SupportsCapabilities): @property - def mjpeg_server_port(self) -> Optional[int]: + def mjpeg_server_port(self) -> int | None: """ Port number on which WDA broadcasts screenshots stream encoded into MJPEG format from the device under test. diff --git a/appium/options/ios/xcuitest/wda/prebuilt_wda_path_option.py b/appium/options/ios/xcuitest/wda/prebuilt_wda_path_option.py new file mode 100644 index 000000000..649b5cf69 --- /dev/null +++ b/appium/options/ios/xcuitest/wda/prebuilt_wda_path_option.py @@ -0,0 +1,38 @@ +# Licensed to the Software Freedom Conservancy (SFC) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The SFC 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 appium.options.common.supports_capabilities import SupportsCapabilities + +PREBUILT_WDA_PATH = 'prebuiltWDAPath' + + +class PrebuiltWdaPathOption(SupportsCapabilities): + @property + def prebuilt_wda_path(self) -> str | None: + """ + The path to the prebuilt WebDriverAgent. + """ + return self.get_capability(PREBUILT_WDA_PATH) + + @prebuilt_wda_path.setter + def prebuilt_wda_path(self, value: str) -> None: + """ + The path to the prebuilt WebDriverAgent. This should be the path to the + WebDriverAgent.xcarchive file or the WebDriverAgent.app bundle. + """ + self.set_capability(PREBUILT_WDA_PATH, value) diff --git a/appium/options/ios/xcuitest/wda/process_arguments_option.py b/appium/options/ios/xcuitest/wda/process_arguments_option.py index 5b169a945..07f7ef126 100644 --- a/appium/options/ios/xcuitest/wda/process_arguments_option.py +++ b/appium/options/ios/xcuitest/wda/process_arguments_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict, List, Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +23,14 @@ class ProcessArgumentsOption(SupportsCapabilities): @property - def process_arguments(self) -> Optional[Dict[str, Union[List[str], Dict[str, str]]]]: + def process_arguments(self) -> dict[str, list[str] | dict[str, str]] | None: """ Command line arguments and/or environment variables of the application under test. """ return self.get_capability(PROCESS_ARGUMENTS) @process_arguments.setter - def process_arguments(self, value: Dict[str, Union[List[str], Dict[str, str]]]) -> None: + def process_arguments(self, value: dict[str, list[str] | dict[str, str]]) -> None: """ Provides process arguments and environment which will be sent to the WebDriverAgent server. Acceptable dictionary keys are 'env' diff --git a/appium/options/ios/xcuitest/wda/result_bundle_path_option.py b/appium/options/ios/xcuitest/wda/result_bundle_path_option.py index 5cf7ec098..f3e470acc 100644 --- a/appium/options/ios/xcuitest/wda/result_bundle_path_option.py +++ b/appium/options/ios/xcuitest/wda/result_bundle_path_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ResultBundlePathOption(SupportsCapabilities): @property - def result_bundle_path(self) -> Optional[str]: + def result_bundle_path(self) -> str | None: """ Path where the resulting XCTest bundle should be stored. """ diff --git a/appium/options/ios/xcuitest/wda/screenshot_quality_option.py b/appium/options/ios/xcuitest/wda/screenshot_quality_option.py index d808db9d6..bbe052fa2 100644 --- a/appium/options/ios/xcuitest/wda/screenshot_quality_option.py +++ b/appium/options/ios/xcuitest/wda/screenshot_quality_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ScreenshotQualityOption(SupportsCapabilities): @property - def screenshot_quality(self) -> Optional[int]: + def screenshot_quality(self) -> int | None: """ Screenshot quality value. """ diff --git a/appium/options/ios/xcuitest/wda/should_terminate_app_option.py b/appium/options/ios/xcuitest/wda/should_terminate_app_option.py index 8550627cf..3d9fc07ad 100644 --- a/appium/options/ios/xcuitest/wda/should_terminate_app_option.py +++ b/appium/options/ios/xcuitest/wda/should_terminate_app_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ShouldTerminateAppOption(SupportsCapabilities): @property - def should_terminate_app(self) -> Optional[bool]: + def should_terminate_app(self) -> bool | None: """ Whether to enforce app termination on session quit. """ diff --git a/appium/options/ios/xcuitest/wda/should_use_singleton_test_manager_option.py b/appium/options/ios/xcuitest/wda/should_use_singleton_test_manager_option.py index 569236810..6fbf4e893 100644 --- a/appium/options/ios/xcuitest/wda/should_use_singleton_test_manager_option.py +++ b/appium/options/ios/xcuitest/wda/should_use_singleton_test_manager_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ShouldUseSingletonTestManagerOption(SupportsCapabilities): @property - def should_use_singleton_test_manager(self) -> Optional[bool]: + def should_use_singleton_test_manager(self) -> bool | None: """ Whether to use the default proxy for test management within WebDriverAgent. """ diff --git a/appium/options/ios/xcuitest/wda/show_xcode_log_option.py b/appium/options/ios/xcuitest/wda/show_xcode_log_option.py index 0e435b71d..26cd52f9e 100644 --- a/appium/options/ios/xcuitest/wda/show_xcode_log_option.py +++ b/appium/options/ios/xcuitest/wda/show_xcode_log_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ShowXcodeLogOption(SupportsCapabilities): @property - def show_xcode_log(self) -> Optional[bool]: + def show_xcode_log(self) -> bool | None: """ Whether to display the output of the Xcode command used to run the tests. """ diff --git a/appium/options/ios/xcuitest/wda/simple_is_visible_check_option.py b/appium/options/ios/xcuitest/wda/simple_is_visible_check_option.py index 694ed5743..1f596b0af 100644 --- a/appium/options/ios/xcuitest/wda/simple_is_visible_check_option.py +++ b/appium/options/ios/xcuitest/wda/simple_is_visible_check_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SimpleIsVisibleCheckOption(SupportsCapabilities): @property - def simple_is_visible_check(self) -> Optional[bool]: + def simple_is_visible_check(self) -> bool | None: """ Whether to use native methods for determining visibility of elements. """ diff --git a/appium/options/ios/xcuitest/wda/updated_wda_bundle_id_option.py b/appium/options/ios/xcuitest/wda/updated_wda_bundle_id_option.py index b799c949b..a6f2a8eef 100644 --- a/appium/options/ios/xcuitest/wda/updated_wda_bundle_id_option.py +++ b/appium/options/ios/xcuitest/wda/updated_wda_bundle_id_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UpdatedWdaBundleIdOption(SupportsCapabilities): @property - def updated_wda_bundle_id(self) -> Optional[str]: + def updated_wda_bundle_id(self) -> str | None: """ WDA bundle identifier. """ diff --git a/appium/options/ios/xcuitest/wda/use_native_caching_strategy_option.py b/appium/options/ios/xcuitest/wda/use_native_caching_strategy_option.py index a3e30de17..f59bf6067 100644 --- a/appium/options/ios/xcuitest/wda/use_native_caching_strategy_option.py +++ b/appium/options/ios/xcuitest/wda/use_native_caching_strategy_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UseNativeCachingStrategyOption(SupportsCapabilities): @property - def use_native_caching_strategy(self) -> Optional[bool]: + def use_native_caching_strategy(self) -> bool | None: """ Whether to use the native caching strategy. """ diff --git a/appium/options/ios/xcuitest/wda/use_new_wda_option.py b/appium/options/ios/xcuitest/wda/use_new_wda_option.py index f52684a65..fddfec6b1 100644 --- a/appium/options/ios/xcuitest/wda/use_new_wda_option.py +++ b/appium/options/ios/xcuitest/wda/use_new_wda_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UseNewWdaOption(SupportsCapabilities): @property - def use_new_wda(self) -> Optional[bool]: + def use_new_wda(self) -> bool | None: """ Whether whether to uninstall of any existing WebDriverAgent app on the device under test. diff --git a/appium/options/ios/xcuitest/wda/use_prebuilt_wda_option.py b/appium/options/ios/xcuitest/wda/use_prebuilt_wda_option.py index 76fd5163e..4d1c8d1bf 100644 --- a/appium/options/ios/xcuitest/wda/use_prebuilt_wda_option.py +++ b/appium/options/ios/xcuitest/wda/use_prebuilt_wda_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UsePrebuiltWdaOption(SupportsCapabilities): @property - def use_prebuilt_wda(self) -> Optional[bool]: + def use_prebuilt_wda(self) -> bool | None: """ Whether to skip the build phase of running the WDA app. """ diff --git a/appium/options/ios/xcuitest/wda/use_preinstalled_wda_option.py b/appium/options/ios/xcuitest/wda/use_preinstalled_wda_option.py new file mode 100644 index 000000000..0ea313a91 --- /dev/null +++ b/appium/options/ios/xcuitest/wda/use_preinstalled_wda_option.py @@ -0,0 +1,39 @@ +# Licensed to the Software Freedom Conservancy (SFC) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The SFC 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 appium.options.common.supports_capabilities import SupportsCapabilities + +USE_PREINSTALLED_WDA = 'usePreinstalledWDA' + + +class UsePreinstalledWdaOption(SupportsCapabilities): + @property + def use_preinstalled_wda(self) -> bool | None: + """ + Whether to use a preinstalled WebDriverAgent. + """ + return self.get_capability(USE_PREINSTALLED_WDA) + + @use_preinstalled_wda.setter + def use_preinstalled_wda(self, value: bool) -> None: + """ + Whether to use a preinstalled WebDriverAgent. If true, Appium will not + build and install the WebDriverAgent, but will use an existing one. + Defaults to false. + """ + self.set_capability(USE_PREINSTALLED_WDA, value) diff --git a/appium/options/ios/xcuitest/wda/use_simple_build_test_option.py b/appium/options/ios/xcuitest/wda/use_simple_build_test_option.py index 516e08cbe..86cba52a5 100644 --- a/appium/options/ios/xcuitest/wda/use_simple_build_test_option.py +++ b/appium/options/ios/xcuitest/wda/use_simple_build_test_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UseSimpleBuildTestOption(SupportsCapabilities): @property - def use_simple_build_test(self) -> Optional[bool]: + def use_simple_build_test(self) -> bool | None: """ Whether to enforce app termination on session quit. """ diff --git a/appium/options/ios/xcuitest/wda/use_xctestrun_file_option.py b/appium/options/ios/xcuitest/wda/use_xctestrun_file_option.py index 0d1a3c64b..cb74886fc 100644 --- a/appium/options/ios/xcuitest/wda/use_xctestrun_file_option.py +++ b/appium/options/ios/xcuitest/wda/use_xctestrun_file_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class UseXctestrunFileOption(SupportsCapabilities): @property - def use_xctestrun_file(self) -> Optional[bool]: + def use_xctestrun_file(self) -> bool | None: """ Whether to use of .xctestrun file to launch WDA. """ diff --git a/appium/options/ios/xcuitest/wda/wait_for_idle_timeout_option.py b/appium/options/ios/xcuitest/wda/wait_for_idle_timeout_option.py index ff994d43e..06a0420a4 100644 --- a/appium/options/ios/xcuitest/wda/wait_for_idle_timeout_option.py +++ b/appium/options/ios/xcuitest/wda/wait_for_idle_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class WaitForIdleTimeoutOption(SupportsCapabilities): @property - def wait_for_idle_timeout(self) -> Optional[timedelta]: + def wait_for_idle_timeout(self) -> timedelta | None: """ Maximum timeout to wait until WDA responds to HTTP requests. """ @@ -33,7 +32,7 @@ def wait_for_idle_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(seconds=value) @wait_for_idle_timeout.setter - def wait_for_idle_timeout(self, value: Union[timedelta, float]) -> None: + def wait_for_idle_timeout(self, value: timedelta | float) -> None: """ The time to wait until the application under test is idling. XCTest requires the app's main thread to be idling in order to execute any action on it, diff --git a/appium/options/ios/xcuitest/wda/wait_for_quiescence_option.py b/appium/options/ios/xcuitest/wda/wait_for_quiescence_option.py index b8be7f322..d4e108940 100644 --- a/appium/options/ios/xcuitest/wda/wait_for_quiescence_option.py +++ b/appium/options/ios/xcuitest/wda/wait_for_quiescence_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,14 +24,14 @@ class WaitForQuiescenceOption(SupportsCapabilities): @property - def wait_for_quiescence(self) -> Optional[bool]: + def wait_for_quiescence(self) -> bool | None: """ Whether to wait for application quiescence. """ return self.get_capability(WAIT_FOR_QUIESCENCE) @wait_for_quiescence.setter - def wait_for_quiescence(self, value: Union[timedelta, float]) -> None: + def wait_for_quiescence(self, value: timedelta | float) -> None: """ It allows to turn on/off waiting for application quiescence in WebDriverAgent, while performing queries. The default value is true. You can avoid this kind diff --git a/appium/options/ios/xcuitest/wda/wda_base_url_option.py b/appium/options/ios/xcuitest/wda/wda_base_url_option.py index c2ca5cd81..f777aa510 100644 --- a/appium/options/ios/xcuitest/wda/wda_base_url_option.py +++ b/appium/options/ios/xcuitest/wda/wda_base_url_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class WdaBaseUrlOption(SupportsCapabilities): @property - def wda_base_url(self) -> Optional[str]: + def wda_base_url(self) -> str | None: """ Prefix to build a custom WebDriverAgent URL. """ diff --git a/appium/options/ios/xcuitest/wda/wda_connection_timeout_option.py b/appium/options/ios/xcuitest/wda/wda_connection_timeout_option.py index e21bb1834..10711810f 100644 --- a/appium/options/ios/xcuitest/wda/wda_connection_timeout_option.py +++ b/appium/options/ios/xcuitest/wda/wda_connection_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class WdaConnectionTimeoutOption(SupportsCapabilities): @property - def wda_connection_timeout(self) -> Optional[timedelta]: + def wda_connection_timeout(self) -> timedelta | None: """ Maximum timeout to wait until WDA responds to HTTP requests. """ @@ -33,7 +32,7 @@ def wda_connection_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @wda_connection_timeout.setter - def wda_connection_timeout(self, value: Union[timedelta, int]) -> None: + def wda_connection_timeout(self, value: timedelta | int) -> None: """ Connection timeout to wait for a response from WebDriverAgent. Defaults to 240000ms. diff --git a/appium/options/ios/xcuitest/wda/wda_eventloop_idle_delay_option.py b/appium/options/ios/xcuitest/wda/wda_eventloop_idle_delay_option.py index e957f2690..f6661da88 100644 --- a/appium/options/ios/xcuitest/wda/wda_eventloop_idle_delay_option.py +++ b/appium/options/ios/xcuitest/wda/wda_eventloop_idle_delay_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class WdaEventloopIdleDelayOption(SupportsCapabilities): @property - def wda_eventloop_idle_delay(self) -> Optional[timedelta]: + def wda_eventloop_idle_delay(self) -> timedelta | None: """ Event loop idle delay. """ @@ -33,7 +32,7 @@ def wda_eventloop_idle_delay(self) -> Optional[timedelta]: return None if value is None else timedelta(seconds=value) @wda_eventloop_idle_delay.setter - def wda_eventloop_idle_delay(self, value: Union[timedelta, float]) -> None: + def wda_eventloop_idle_delay(self, value: timedelta | float) -> None: """ Delays the invocation of -[XCUIApplicationProcess setEventLoopHasIdled:] by the duration specified with this capability. This can help quiescence apps diff --git a/appium/options/ios/xcuitest/wda/wda_launch_timeout_option.py b/appium/options/ios/xcuitest/wda/wda_launch_timeout_option.py index 325b7e40e..cbc911c4b 100644 --- a/appium/options/ios/xcuitest/wda/wda_launch_timeout_option.py +++ b/appium/options/ios/xcuitest/wda/wda_launch_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class WdaLaunchTimeoutOption(SupportsCapabilities): @property - def wda_launch_timeout(self) -> Optional[timedelta]: + def wda_launch_timeout(self) -> timedelta | None: """ Maximum timeout to wait until WDA is listening. """ @@ -33,7 +32,7 @@ def wda_launch_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @wda_launch_timeout.setter - def wda_launch_timeout(self, value: Union[timedelta, int]) -> None: + def wda_launch_timeout(self, value: timedelta | int) -> None: """ Timeout to wait for WebDriverAgent to be pingable, after its building is finished. Defaults to 60000ms. diff --git a/appium/options/ios/xcuitest/wda/wda_local_port_option.py b/appium/options/ios/xcuitest/wda/wda_local_port_option.py index 1af241a35..b0ca7031e 100644 --- a/appium/options/ios/xcuitest/wda/wda_local_port_option.py +++ b/appium/options/ios/xcuitest/wda/wda_local_port_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class WdaLocalPortOption(SupportsCapabilities): @property - def wda_local_port(self) -> Optional[int]: + def wda_local_port(self) -> int | None: """ Local port number where the WDA traffic is being forwarded. """ diff --git a/appium/options/ios/xcuitest/wda/wda_startup_retries_option.py b/appium/options/ios/xcuitest/wda/wda_startup_retries_option.py index a70999621..00de25d4c 100644 --- a/appium/options/ios/xcuitest/wda/wda_startup_retries_option.py +++ b/appium/options/ios/xcuitest/wda/wda_startup_retries_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class WdaStartupRetriesOption(SupportsCapabilities): @property - def wda_startup_retries(self) -> Optional[int]: + def wda_startup_retries(self) -> int | None: """ Number of retries before to fail WDA deployment. """ diff --git a/appium/options/ios/xcuitest/wda/wda_startup_retry_interval_option.py b/appium/options/ios/xcuitest/wda/wda_startup_retry_interval_option.py index 99d89daa6..53313e895 100644 --- a/appium/options/ios/xcuitest/wda/wda_startup_retry_interval_option.py +++ b/appium/options/ios/xcuitest/wda/wda_startup_retry_interval_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class WdaStartupRetryIntervalOption(SupportsCapabilities): @property - def wda_startup_retry_interval(self) -> Optional[timedelta]: + def wda_startup_retry_interval(self) -> timedelta | None: """ Interval to wait between tries to build and launch WebDriverAgent. """ @@ -33,7 +32,7 @@ def wda_startup_retry_interval(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @wda_startup_retry_interval.setter - def wda_startup_retry_interval(self, value: Union[timedelta, int]) -> None: + def wda_startup_retry_interval(self, value: timedelta | int) -> None: """ Time interval to wait between tries to build and launch WebDriverAgent. Defaults to 10000ms. diff --git a/appium/options/ios/xcuitest/wda/web_driver_agent_url_option.py b/appium/options/ios/xcuitest/wda/web_driver_agent_url_option.py index 5dd89f2c6..b453bee38 100644 --- a/appium/options/ios/xcuitest/wda/web_driver_agent_url_option.py +++ b/appium/options/ios/xcuitest/wda/web_driver_agent_url_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class WebDriverAgentUrlOption(SupportsCapabilities): @property - def web_driver_agent_url(self) -> Optional[str]: + def web_driver_agent_url(self) -> str | None: """ WedDriverAgent URL. """ diff --git a/appium/options/ios/xcuitest/wda/xcode_org_id_option.py b/appium/options/ios/xcuitest/wda/xcode_org_id_option.py index d5c517935..1ddb3f1c7 100644 --- a/appium/options/ios/xcuitest/wda/xcode_org_id_option.py +++ b/appium/options/ios/xcuitest/wda/xcode_org_id_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class XcodeOrgIdOption(SupportsCapabilities): @property - def xcode_org_id(self) -> Optional[str]: + def xcode_org_id(self) -> str | None: """ Signing certificate organization id for WebDriverAgent compilation. """ diff --git a/appium/options/ios/xcuitest/wda/xcode_signing_id_option.py b/appium/options/ios/xcuitest/wda/xcode_signing_id_option.py index 08ba1855e..ce1877cb6 100644 --- a/appium/options/ios/xcuitest/wda/xcode_signing_id_option.py +++ b/appium/options/ios/xcuitest/wda/xcode_signing_id_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class XcodeSigningIdOption(SupportsCapabilities): @property - def xcode_signing_id(self) -> Optional[str]: + def xcode_signing_id(self) -> str | None: """ Signing certificate for WebDriverAgent compilation. """ diff --git a/appium/options/ios/xcuitest/webview/absolute_web_locations_option.py b/appium/options/ios/xcuitest/webview/absolute_web_locations_option.py index 114c737dc..50ffdc67d 100644 --- a/appium/options/ios/xcuitest/webview/absolute_web_locations_option.py +++ b/appium/options/ios/xcuitest/webview/absolute_web_locations_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AbsoluteWebLocationsOption(SupportsCapabilities): @property - def absolute_web_locations(self) -> Optional[bool]: + def absolute_web_locations(self) -> bool | None: """ Whether Get Element Location returns coordinates relative to the page origin for web view elements. diff --git a/appium/options/ios/xcuitest/webview/additional_webview_bundle_ids_option.py b/appium/options/ios/xcuitest/webview/additional_webview_bundle_ids_option.py index 6546c548f..1e75499da 100644 --- a/appium/options/ios/xcuitest/webview/additional_webview_bundle_ids_option.py +++ b/appium/options/ios/xcuitest/webview/additional_webview_bundle_ids_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import List, Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +23,14 @@ class AdditionalWebviewBundleIdsOption(SupportsCapabilities): @property - def additional_webview_bundle_ids(self) -> Optional[List[str]]: + def additional_webview_bundle_ids(self) -> list[str] | None: """ Array of possible bundle identifiers for webviews. """ return self.get_capability(ADDITIONAL_WEBVIEW_BUNDLE_IDS) @additional_webview_bundle_ids.setter - def additional_webview_bundle_ids(self, value: List[str]) -> None: + def additional_webview_bundle_ids(self, value: list[str]) -> None: """ Array of possible bundle identifiers for webviews. This is sometimes necessary if the Web Inspector is found to be returning a modified diff --git a/appium/options/ios/xcuitest/webview/enable_async_execute_from_https_option.py b/appium/options/ios/xcuitest/webview/enable_async_execute_from_https_option.py index ae2a3dcc1..d76d24544 100644 --- a/appium/options/ios/xcuitest/webview/enable_async_execute_from_https_option.py +++ b/appium/options/ios/xcuitest/webview/enable_async_execute_from_https_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class EnableAsyncExecuteFromHttpsOption(SupportsCapabilities): @property - def enable_async_execute_from_https(self) -> Optional[bool]: + def enable_async_execute_from_https(self) -> bool | None: """ Whether to allow simulators to execute async JavaScript on pages using HTTPS. """ diff --git a/appium/options/ios/xcuitest/webview/full_context_list_option.py b/appium/options/ios/xcuitest/webview/full_context_list_option.py index 7bdd3102d..c58e73e1f 100644 --- a/appium/options/ios/xcuitest/webview/full_context_list_option.py +++ b/appium/options/ios/xcuitest/webview/full_context_list_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class FullContextListOption(SupportsCapabilities): @property - def full_context_list(self) -> Optional[bool]: + def full_context_list(self) -> bool | None: """ Whether to return the detailed information on contexts for the get available context command. diff --git a/appium/options/ios/xcuitest/webview/include_safari_in_webviews_option.py b/appium/options/ios/xcuitest/webview/include_safari_in_webviews_option.py index c21cb141c..ff13eb423 100644 --- a/appium/options/ios/xcuitest/webview/include_safari_in_webviews_option.py +++ b/appium/options/ios/xcuitest/webview/include_safari_in_webviews_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class IncludeSafariInWebviewsOption(SupportsCapabilities): @property - def include_safari_in_webviews(self) -> Optional[bool]: + def include_safari_in_webviews(self) -> bool | None: """ Whether to add Safari web views to the list of contexts available during a native/webview app test. diff --git a/appium/options/ios/xcuitest/webview/native_web_tap_option.py b/appium/options/ios/xcuitest/webview/native_web_tap_option.py index 02a40b98e..3ca218eb9 100644 --- a/appium/options/ios/xcuitest/webview/native_web_tap_option.py +++ b/appium/options/ios/xcuitest/webview/native_web_tap_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class NativeWebTapOption(SupportsCapabilities): @property - def native_web_tap(self) -> Optional[bool]: + def native_web_tap(self) -> bool | None: """ Whether to enable native taps in web view mode. """ diff --git a/appium/options/ios/xcuitest/webview/safari_garbage_collect_option.py b/appium/options/ios/xcuitest/webview/safari_garbage_collect_option.py index 63aefc4c4..696a19137 100644 --- a/appium/options/ios/xcuitest/webview/safari_garbage_collect_option.py +++ b/appium/options/ios/xcuitest/webview/safari_garbage_collect_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SafariGarbageCollectOption(SupportsCapabilities): @property - def safari_garbage_collect(self) -> Optional[bool]: + def safari_garbage_collect(self) -> bool | None: """ Whether to turn on garbage collection when executing scripts on Safari. """ diff --git a/appium/options/ios/xcuitest/webview/safari_ignore_fraud_warning_option.py b/appium/options/ios/xcuitest/webview/safari_ignore_fraud_warning_option.py index c600285d0..38f6cc2bb 100644 --- a/appium/options/ios/xcuitest/webview/safari_ignore_fraud_warning_option.py +++ b/appium/options/ios/xcuitest/webview/safari_ignore_fraud_warning_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SafariIgnoreFraudWarningOption(SupportsCapabilities): @property - def safari_ignore_fraud_warning(self) -> Optional[bool]: + def safari_ignore_fraud_warning(self) -> bool | None: """ Whether to prevent Safari from showing a fraudulent website warning. """ diff --git a/appium/options/ios/xcuitest/webview/safari_ignore_web_hostnames_option.py b/appium/options/ios/xcuitest/webview/safari_ignore_web_hostnames_option.py index 9f48f8cf3..e8f9052f3 100644 --- a/appium/options/ios/xcuitest/webview/safari_ignore_web_hostnames_option.py +++ b/appium/options/ios/xcuitest/webview/safari_ignore_web_hostnames_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SafariIgnoreWebHostnamesOption(SupportsCapabilities): @property - def safari_ignore_web_hostnames(self) -> Optional[str]: + def safari_ignore_web_hostnames(self) -> str | None: """ Comma-separated list of host names to be ignored. """ diff --git a/appium/options/ios/xcuitest/webview/safari_initial_url_option.py b/appium/options/ios/xcuitest/webview/safari_initial_url_option.py index 79dc14fe3..5787cd2da 100644 --- a/appium/options/ios/xcuitest/webview/safari_initial_url_option.py +++ b/appium/options/ios/xcuitest/webview/safari_initial_url_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SafariInitialUrlOption(SupportsCapabilities): @property - def safari_initial_url(self) -> Optional[str]: + def safari_initial_url(self) -> str | None: """ The initial safari url. """ diff --git a/appium/options/ios/xcuitest/webview/safari_log_all_communication_hex_dump_option.py b/appium/options/ios/xcuitest/webview/safari_log_all_communication_hex_dump_option.py index 03b2e28cc..ef7d15af7 100644 --- a/appium/options/ios/xcuitest/webview/safari_log_all_communication_hex_dump_option.py +++ b/appium/options/ios/xcuitest/webview/safari_log_all_communication_hex_dump_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SafariLogAllCommunicationHexDumpOption(SupportsCapabilities): @property - def safari_log_all_communication_hex_dump(self) -> Optional[bool]: + def safari_log_all_communication_hex_dump(self) -> bool | None: """ Whether to log of plists sent to and received from the Web Inspector in hex dump format. diff --git a/appium/options/ios/xcuitest/webview/safari_log_all_communication_option.py b/appium/options/ios/xcuitest/webview/safari_log_all_communication_option.py index b022dba3d..36ff3f1f7 100644 --- a/appium/options/ios/xcuitest/webview/safari_log_all_communication_option.py +++ b/appium/options/ios/xcuitest/webview/safari_log_all_communication_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SafariLogAllCommunicationOption(SupportsCapabilities): @property - def safari_log_all_communication(self) -> Optional[bool]: + def safari_log_all_communication(self) -> bool | None: """ Whether to log of plists sent to and received from the Web Inspector. """ diff --git a/appium/options/ios/xcuitest/webview/safari_open_links_in_background_option.py b/appium/options/ios/xcuitest/webview/safari_open_links_in_background_option.py index 2ebb48011..4fe804d77 100644 --- a/appium/options/ios/xcuitest/webview/safari_open_links_in_background_option.py +++ b/appium/options/ios/xcuitest/webview/safari_open_links_in_background_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SafariOpenLinksInBackgroundOption(SupportsCapabilities): @property - def safari_open_links_in_background(self) -> Optional[bool]: + def safari_open_links_in_background(self) -> bool | None: """ Whether Safari should allow links to open in new windows. """ diff --git a/appium/options/ios/xcuitest/webview/safari_socket_chunk_size_option.py b/appium/options/ios/xcuitest/webview/safari_socket_chunk_size_option.py index c33ea61d2..c5fb4bff6 100644 --- a/appium/options/ios/xcuitest/webview/safari_socket_chunk_size_option.py +++ b/appium/options/ios/xcuitest/webview/safari_socket_chunk_size_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SafariSocketChunkSizeOption(SupportsCapabilities): @property - def safari_socket_chunk_size(self) -> Optional[int]: + def safari_socket_chunk_size(self) -> int | None: """ Get the size of a single remote debugger socket chunk. """ diff --git a/appium/options/ios/xcuitest/webview/safari_web_inspector_max_frame_length_option.py b/appium/options/ios/xcuitest/webview/safari_web_inspector_max_frame_length_option.py index d92fb2d4a..6732dfef2 100644 --- a/appium/options/ios/xcuitest/webview/safari_web_inspector_max_frame_length_option.py +++ b/appium/options/ios/xcuitest/webview/safari_web_inspector_max_frame_length_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SafariWebInspectorMaxFrameLengthOption(SupportsCapabilities): @property - def safari_web_inspector_max_frame_length(self) -> Optional[int]: + def safari_web_inspector_max_frame_length(self) -> int | None: """ Maximum size in bytes of a single data frame for the Web Inspector. """ diff --git a/appium/options/ios/xcuitest/webview/webkit_response_timeout_option.py b/appium/options/ios/xcuitest/webview/webkit_response_timeout_option.py index 1e274bf01..25d0f8d76 100644 --- a/appium/options/ios/xcuitest/webview/webkit_response_timeout_option.py +++ b/appium/options/ios/xcuitest/webview/webkit_response_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class WebkitResponseTimeoutOption(SupportsCapabilities): @property - def webkit_response_timeout(self) -> Optional[timedelta]: + def webkit_response_timeout(self) -> timedelta | None: """ Time to wait for a response from WebKit in a Safari session. """ @@ -33,7 +32,7 @@ def webkit_response_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @webkit_response_timeout.setter - def webkit_response_timeout(self, value: Union[timedelta, int]) -> None: + def webkit_response_timeout(self, value: timedelta | int) -> None: """ (Real device only) Set the time to wait for a response from WebKit in a Safari session. Defaults to 5000ms. diff --git a/appium/options/ios/xcuitest/webview/webview_connect_retries_option.py b/appium/options/ios/xcuitest/webview/webview_connect_retries_option.py index 7792f15b0..e8dd86b36 100644 --- a/appium/options/ios/xcuitest/webview/webview_connect_retries_option.py +++ b/appium/options/ios/xcuitest/webview/webview_connect_retries_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class WebviewConnectRetriesOption(SupportsCapabilities): @property - def webview_connect_retries(self) -> Optional[int]: + def webview_connect_retries(self) -> int | None: """ Number of retries to send connection message to remote debugger, to get a webview. diff --git a/appium/options/ios/xcuitest/webview/webview_connect_timeout_option.py b/appium/options/ios/xcuitest/webview/webview_connect_timeout_option.py index 9fa742020..b011e6a47 100644 --- a/appium/options/ios/xcuitest/webview/webview_connect_timeout_option.py +++ b/appium/options/ios/xcuitest/webview/webview_connect_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class WebviewConnectTimeoutOption(SupportsCapabilities): @property - def webview_connect_timeout(self) -> Optional[timedelta]: + def webview_connect_timeout(self) -> timedelta | None: """ Timeout to wait for the initial presence of webviews. """ @@ -33,7 +32,7 @@ def webview_connect_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @webview_connect_timeout.setter - def webview_connect_timeout(self, value: Union[timedelta, int]) -> None: + def webview_connect_timeout(self, value: timedelta | int) -> None: """ The time to wait for the initial presence of webviews in MobileSafari or hybrid apps. Defaults to 0ms. diff --git a/appium/options/mac/__init__.py b/appium/options/mac/__init__.py index 41a091df5..4c9945356 100644 --- a/appium/options/mac/__init__.py +++ b/appium/options/mac/__init__.py @@ -1 +1,3 @@ from .mac2.base import Mac2Options + +__all__ = ['Mac2Options'] diff --git a/appium/options/mac/mac2/app_path_option.py b/appium/options/mac/mac2/app_path_option.py index 71506fd45..bf12ea633 100644 --- a/appium/options/mac/mac2/app_path_option.py +++ b/appium/options/mac/mac2/app_path_option.py @@ -16,7 +16,6 @@ # under the License. from os import PathLike, fspath -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,14 +24,14 @@ class AppPathOption(SupportsCapabilities): @property - def app_path(self) -> Optional[str]: + def app_path(self) -> str | None: """ The path of the application to automate. """ return self.get_capability(APP_PATH) @app_path.setter - def app_path(self, value: Union[str, PathLike]) -> None: + def app_path(self, value: str | PathLike) -> None: """ Set the path of the application to automate. """ diff --git a/appium/options/mac/mac2/arguments_option.py b/appium/options/mac/mac2/arguments_option.py index 3c9a5a70e..063ebe94f 100644 --- a/appium/options/mac/mac2/arguments_option.py +++ b/appium/options/mac/mac2/arguments_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import List, Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +23,14 @@ class ArgumentsOption(SupportsCapabilities): @property - def arguments(self) -> Optional[List[str]]: + def arguments(self) -> list[str] | None: """ Array of application command line arguments. """ return self.get_capability(ARGUMENTS) @arguments.setter - def arguments(self, value: List[str]) -> None: + def arguments(self, value: list[str]) -> None: """ Set the array of application command line arguments. This capability is only going to be applied if the application is not running on session startup. diff --git a/appium/options/mac/mac2/base.py b/appium/options/mac/mac2/base.py index d635f2b38..511a096f4 100644 --- a/appium/options/mac/mac2/base.py +++ b/appium/options/mac/mac2/base.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict from appium.options.common.automation_name_option import AUTOMATION_NAME from appium.options.common.base import PLATFORM_NAME, AppiumOptions @@ -52,7 +51,7 @@ class Mac2Options( WebDriverAgentMacUrlOption, ): @PrerunOption.prerun.setter # type: ignore - def prerun(self, value: Dict[str, str]) -> None: + def prerun(self, value: dict[str, str]) -> None: """ A mapping containing either 'script' or 'command' key. The value of each key must be a valid AppleScript script or command to be @@ -63,7 +62,7 @@ def prerun(self, value: Dict[str, str]) -> None: PrerunOption.prerun.fset(self, value) # type: ignore @PostrunOption.postrun.setter # type: ignore - def postrun(self, value: Dict[str, str]) -> None: + def postrun(self, value: dict[str, str]) -> None: """ A mapping containing either 'script' or 'command' key. The value of each key must be a valid AppleScript script or command to be @@ -106,7 +105,7 @@ def bundle_id(self, value: str) -> None: BundleIdOption.bundle_id.fset(self, value) # type: ignore @property - def default_capabilities(self) -> Dict: + def default_capabilities(self) -> dict: return { AUTOMATION_NAME: 'Mac2', PLATFORM_NAME: 'Mac', diff --git a/appium/options/mac/mac2/bootstrap_root_option.py b/appium/options/mac/mac2/bootstrap_root_option.py index 25c53d1ba..dc68a6bbe 100644 --- a/appium/options/mac/mac2/bootstrap_root_option.py +++ b/appium/options/mac/mac2/bootstrap_root_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class BootstrapRootOption(SupportsCapabilities): @property - def bootstrap_root(self) -> Optional[str]: + def bootstrap_root(self) -> str | None: """ The full path to WebDriverAgentMac root folder where Xcode project of the server sources lives. diff --git a/appium/options/mac/mac2/environment_option.py b/appium/options/mac/mac2/environment_option.py index b5d72a9fc..40818ebea 100644 --- a/appium/options/mac/mac2/environment_option.py +++ b/appium/options/mac/mac2/environment_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict, Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,14 +23,14 @@ class EnvironmentOption(SupportsCapabilities): @property - def environment(self) -> Optional[Dict[str, str]]: + def environment(self) -> dict[str, str] | None: """ Application environment variables mapping. """ return self.get_capability(ENVIRONMENT) @environment.setter - def environment(self, value: Dict[str, str]) -> None: + def environment(self, value: dict[str, str]) -> None: """ Set the dictionary of environment variables (name->value) that are going to be passed to the application under test on top of environment variables inherited from diff --git a/appium/options/mac/mac2/server_startup_timeout_option.py b/appium/options/mac/mac2/server_startup_timeout_option.py index 32e13f79a..7bfb4af28 100644 --- a/appium/options/mac/mac2/server_startup_timeout_option.py +++ b/appium/options/mac/mac2/server_startup_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class ServerStartupTimeoutOption(SupportsCapabilities): @property - def server_startup_timeout(self) -> Optional[timedelta]: + def server_startup_timeout(self) -> timedelta | None: """ Get the timeout to wait util the WebDriverAgentMac project is built and started. @@ -34,7 +33,7 @@ def server_startup_timeout(self) -> Optional[timedelta]: return None if value_ms is None else timedelta(milliseconds=value_ms) @server_startup_timeout.setter - def server_startup_timeout(self, value: Union[int, timedelta]) -> None: + def server_startup_timeout(self, value: int | timedelta) -> None: """ Set the timeout to wait util the WebDriverAgentMac project is built and started. diff --git a/appium/options/mac/mac2/show_server_logs_option.py b/appium/options/mac/mac2/show_server_logs_option.py index 635304925..ad380f50b 100644 --- a/appium/options/mac/mac2/show_server_logs_option.py +++ b/appium/options/mac/mac2/show_server_logs_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ShowServerLogsOption(SupportsCapabilities): @property - def show_server_logs(self) -> Optional[bool]: + def show_server_logs(self) -> bool | None: """ Whether to show WDA server logs in the Appium log. """ diff --git a/appium/options/mac/mac2/skip_app_kill_option.py b/appium/options/mac/mac2/skip_app_kill_option.py index adfcd19a3..41fdc3942 100644 --- a/appium/options/mac/mac2/skip_app_kill_option.py +++ b/appium/options/mac/mac2/skip_app_kill_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class SkipAppKillOption(SupportsCapabilities): @property - def skip_app_kill(self) -> Optional[bool]: + def skip_app_kill(self) -> bool | None: """ Whether to skip the termination of the application under test. """ diff --git a/appium/options/mac/mac2/web_driver_agent_mac_url_option.py b/appium/options/mac/mac2/web_driver_agent_mac_url_option.py index 8ffab4391..b8bb4d90e 100644 --- a/appium/options/mac/mac2/web_driver_agent_mac_url_option.py +++ b/appium/options/mac/mac2/web_driver_agent_mac_url_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class WebDriverAgentMacUrlOption(SupportsCapabilities): @property - def web_driver_agent_mac_url(self) -> Optional[str]: + def web_driver_agent_mac_url(self) -> str | None: """ The URL Appium will connect to an existing WebDriverAgentMac instance. """ diff --git a/appium/options/windows/__init__.py b/appium/options/windows/__init__.py index 12d31fe34..2a4617c6e 100644 --- a/appium/options/windows/__init__.py +++ b/appium/options/windows/__init__.py @@ -1 +1,3 @@ from .windows.base import WindowsOptions + +__all__ = ['WindowsOptions'] diff --git a/appium/options/windows/windows/app_arguments_option.py b/appium/options/windows/windows/app_arguments_option.py index 665977d37..9ea8bd47c 100644 --- a/appium/options/windows/windows/app_arguments_option.py +++ b/appium/options/windows/windows/app_arguments_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppArgumentsOption(SupportsCapabilities): @property - def app_arguments(self) -> Optional[str]: + def app_arguments(self) -> str | None: """ Application arguments string, for example `/?`. """ diff --git a/appium/options/windows/windows/app_top_level_window_option.py b/appium/options/windows/windows/app_top_level_window_option.py index f573fb48e..d568816c2 100644 --- a/appium/options/windows/windows/app_top_level_window_option.py +++ b/appium/options/windows/windows/app_top_level_window_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppTopLevelWindowOption(SupportsCapabilities): @property - def app_top_level_window(self) -> Optional[str]: + def app_top_level_window(self) -> str | None: """ Hexadecimal handle of an existing application top level window to attach to. """ diff --git a/appium/options/windows/windows/app_working_dir_option.py b/appium/options/windows/windows/app_working_dir_option.py index 0160f89aa..8539542ec 100644 --- a/appium/options/windows/windows/app_working_dir_option.py +++ b/appium/options/windows/windows/app_working_dir_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class AppWorkingDirOption(SupportsCapabilities): @property - def app_working_dir(self) -> Optional[str]: + def app_working_dir(self) -> str | None: """ Full path to the folder, which is going to be set as the working dir for the application under test. diff --git a/appium/options/windows/windows/base.py b/appium/options/windows/windows/base.py index 52de731e6..070e8f353 100644 --- a/appium/options/windows/windows/base.py +++ b/appium/options/windows/windows/base.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Dict from appium.options.common.app_option import AppOption from appium.options.common.automation_name_option import AUTOMATION_NAME @@ -58,7 +57,7 @@ def app(self, value: str) -> None: AppOption.app.fset(self, value) # type: ignore @PrerunOption.prerun.setter # type: ignore - def prerun(self, value: Dict[str, str]) -> None: + def prerun(self, value: dict[str, str]) -> None: """ A mapping containing either 'script' or 'command' key. The value of each key must be a valid PowerShell script or command to be @@ -69,7 +68,7 @@ def prerun(self, value: Dict[str, str]) -> None: PrerunOption.prerun.fset(self, value) # type: ignore @PostrunOption.postrun.setter # type: ignore - def postrun(self, value: Dict[str, str]) -> None: + def postrun(self, value: dict[str, str]) -> None: """ A mapping containing either 'script' or 'command' key. The value of each key must be a valid PowerShell script or command to be @@ -90,7 +89,7 @@ def system_port(self, value: int) -> None: SystemPortOption.system_port.fset(self, value) # type: ignore @property - def default_capabilities(self) -> Dict: + def default_capabilities(self) -> dict: return { AUTOMATION_NAME: 'Windows', PLATFORM_NAME: 'Windows', diff --git a/appium/options/windows/windows/create_session_timeout_option.py b/appium/options/windows/windows/create_session_timeout_option.py index acf1289a8..17654f2bb 100644 --- a/appium/options/windows/windows/create_session_timeout_option.py +++ b/appium/options/windows/windows/create_session_timeout_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class CreateSessionTimeoutOption(SupportsCapabilities): @property - def create_session_timeout(self) -> Optional[timedelta]: + def create_session_timeout(self) -> timedelta | None: """ Timeout used to retry Appium Windows Driver session startup. """ @@ -33,7 +32,7 @@ def create_session_timeout(self) -> Optional[timedelta]: return None if value is None else timedelta(milliseconds=value) @create_session_timeout.setter - def create_session_timeout(self, value: Union[timedelta, int]) -> None: + def create_session_timeout(self, value: timedelta | int) -> None: """ Set the timeout used to retry Appium Windows Driver session startup. This capability could be used as a workaround for the long startup times diff --git a/appium/options/windows/windows/expreimental_web_driver_option.py b/appium/options/windows/windows/expreimental_web_driver_option.py index ae065d717..af45aa4c2 100644 --- a/appium/options/windows/windows/expreimental_web_driver_option.py +++ b/appium/options/windows/windows/expreimental_web_driver_option.py @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. -from typing import Optional from appium.options.common.supports_capabilities import SupportsCapabilities @@ -24,7 +23,7 @@ class ExperimentalWebDriverOption(SupportsCapabilities): @property - def experimental_webdriver(self) -> Optional[bool]: + def experimental_webdriver(self) -> bool | None: """ Whether to enable experimental features and optimizations. """ diff --git a/appium/options/windows/windows/wait_for_app_launch_option.py b/appium/options/windows/windows/wait_for_app_launch_option.py index 9631b9231..68c0f1f2d 100644 --- a/appium/options/windows/windows/wait_for_app_launch_option.py +++ b/appium/options/windows/windows/wait_for_app_launch_option.py @@ -16,7 +16,6 @@ # under the License. from datetime import timedelta -from typing import Optional, Union from appium.options.common.supports_capabilities import SupportsCapabilities @@ -25,7 +24,7 @@ class WaitForAppLaunchOption(SupportsCapabilities): @property - def wait_for_app_launch(self) -> Optional[timedelta]: + def wait_for_app_launch(self) -> timedelta | None: """ Timeout used to retry Appium Windows Driver session startup. """ @@ -33,7 +32,7 @@ def wait_for_app_launch(self) -> Optional[timedelta]: return None if value is None else timedelta(seconds=value) @wait_for_app_launch.setter - def wait_for_app_launch(self, value: Union[timedelta, int]) -> None: + def wait_for_app_launch(self, value: timedelta | int) -> None: """ Similar to createSessionTimeout, but is applied on the server side. Enables Appium Windows Driver to wait for diff --git a/appium/protocols/webdriver/can_execute_commands.py b/appium/protocols/webdriver/can_execute_commands.py index de4f1b4ad..0ec39cf78 100644 --- a/appium/protocols/webdriver/can_execute_commands.py +++ b/appium/protocols/webdriver/can_execute_commands.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, Protocol, Union +from typing import Protocol from selenium.webdriver.remote.remote_connection import RemoteConnection @@ -20,4 +20,4 @@ class CanExecuteCommands(Protocol): command_executor: RemoteConnection - def execute(self, driver_command: str, params: Union[Dict, None] = None) -> Dict: ... + def execute(self, driver_command: str, params: dict | None = None) -> dict: ... diff --git a/appium/protocols/webdriver/can_execute_scripts.py b/appium/protocols/webdriver/can_execute_scripts.py index 1d04f6cae..3b6e9facf 100644 --- a/appium/protocols/webdriver/can_execute_scripts.py +++ b/appium/protocols/webdriver/can_execute_scripts.py @@ -12,15 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, List, Optional, Protocol +from typing import Any, Protocol class CanExecuteScripts(Protocol): - def pin_script(self, script: str, script_key: Optional[Any] = None) -> Any: ... + def pin_script(self, script: str, script_key: Any | None = None) -> Any: ... def unpin(self, script_key: Any) -> None: ... - def get_pinned_scripts(self) -> List[str]: ... + def get_pinned_scripts(self) -> list[str]: ... def execute_script(self, script: str, *args: Any) -> Any: ... diff --git a/appium/protocols/webdriver/can_find_elements.py b/appium/protocols/webdriver/can_find_elements.py index 07b0b8279..01cbe5b4d 100644 --- a/appium/protocols/webdriver/can_find_elements.py +++ b/appium/protocols/webdriver/can_find_elements.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TYPE_CHECKING, Dict, List, Protocol, Union, runtime_checkable +from typing import TYPE_CHECKING, Protocol, runtime_checkable if TYPE_CHECKING: from appium.webdriver.webelement import WebElement @@ -27,6 +27,6 @@ class CanFindElements(Protocol): - find_elements(by, value): Find multiple elements """ - def find_element(self, by: str, value: Union[str, Dict, None] = None) -> 'WebElement': ... + def find_element(self, by: str, value: str | dict | None = None) -> 'WebElement': ... - def find_elements(self, by: str, value: Union[str, Dict, None] = None) -> List['WebElement']: ... + def find_elements(self, by: str, value: str | dict | None = None) -> list['WebElement']: ... diff --git a/appium/protocols/webdriver/can_remember_extension_presence.py b/appium/protocols/webdriver/can_remember_extension_presence.py deleted file mode 100644 index 1684788b0..000000000 --- a/appium/protocols/webdriver/can_remember_extension_presence.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import Protocol, TypeVar - -T = TypeVar('T') - - -class CanRememberExtensionPresence(Protocol): - def assert_extension_exists(self: T, ext_name: str) -> T: ... - - def mark_extension_absence(self: T, ext_name: str) -> T: ... diff --git a/appium/version.py b/appium/version.py index 0616a7c5e..6398ce531 100644 --- a/appium/version.py +++ b/appium/version.py @@ -12,11 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from importlib import metadata +from importlib.metadata import version as _metadata_version - -def _get_version(): - return metadata.version('Appium-Python-Client') - - -version = _get_version() +version = _metadata_version('Appium-Python-Client') diff --git a/appium/webdriver/__init__.py b/appium/webdriver/__init__.py index 062d726b1..6a0abb2ce 100644 --- a/appium/webdriver/__init__.py +++ b/appium/webdriver/__init__.py @@ -18,3 +18,5 @@ from .webdriver import WebDriver as Remote from .webelement import WebElement + +__all__ = ['Remote', 'WebElement'] diff --git a/appium/webdriver/appium_connection.py b/appium/webdriver/appium_connection.py index 9ca311824..559a695c0 100644 --- a/appium/webdriver/appium_connection.py +++ b/appium/webdriver/appium_connection.py @@ -13,7 +13,7 @@ # limitations under the License. import uuid -from typing import TYPE_CHECKING, Any, Dict +from typing import TYPE_CHECKING, Any from selenium.webdriver.remote.remote_connection import RemoteConnection @@ -28,7 +28,7 @@ HEADER_IDEMOTENCY_KEY = 'X-Idempotency-Key' -def _get_new_headers(key: str, headers: Dict[str, str]) -> Dict[str, str]: +def _get_new_headers(key: str, headers: dict[str, str]) -> dict[str, str]: """Return a new dictionary of heafers without the given key. The key match is case-insensitive.""" lower_key = key.lower() @@ -51,7 +51,7 @@ class AppiumConnection(RemoteConnection): extra_headers = {} @classmethod - def get_remote_connection_headers(cls, parsed_url: 'ParseResult', keep_alive: bool = True) -> Dict[str, Any]: + def get_remote_connection_headers(cls, parsed_url: 'ParseResult', keep_alive: bool = True) -> dict[str, Any]: """Override get_remote_connection_headers in RemoteConnection to control the extra headers. This method will be used in sending a request method in this class. """ diff --git a/appium/webdriver/appium_service.py b/appium/webdriver/appium_service.py index 93c926c65..15ed1f771 100644 --- a/appium/webdriver/appium_service.py +++ b/appium/webdriver/appium_service.py @@ -17,7 +17,8 @@ import subprocess as sp import sys import time -from typing import Any, Callable, List, Optional, Set +from collections.abc import Callable +from typing import Any from selenium.webdriver.remote.remote_connection import urllib3 @@ -41,8 +42,8 @@ class AppiumStartupError(RuntimeError): class AppiumService: def __init__(self) -> None: - self._process: Optional[sp.Popen] = None - self._cmd: Optional[List[str]] = None + self._process: sp.Popen | None = None + self._cmd: list[str] | None = None def start(self, **kwargs: Any) -> sp.Popen: """Starts Appium service with given arguments. @@ -82,21 +83,21 @@ def start(self, **kwargs: Any) -> sp.Popen: """ self.stop() - env = kwargs['env'] if 'env' in kwargs else None + env = kwargs.get('env') node: str = kwargs.get('node') or get_node() npm: str = kwargs.get('npm') or get_npm() main_script: str = kwargs.get('main_script') or get_main_script(node, npm) # A workaround for https://github.com/appium/python-client/issues/534 default_std = sp.DEVNULL if sys.platform == 'win32' else sp.PIPE - stdout = kwargs['stdout'] if 'stdout' in kwargs else default_std - stderr = kwargs['stderr'] if 'stderr' in kwargs else default_std + stdout = kwargs.get('stdout', default_std) + stderr = kwargs.get('stderr', default_std) timeout_ms = int(kwargs['timeout_ms']) if 'timeout_ms' in kwargs else STARTUP_TIMEOUT_MS - args: List[str] = [node, main_script] + args: list[str] = [node, main_script] if 'args' in kwargs: args.extend(kwargs['args']) self._cmd = args self._process = sp.Popen(args=args, stdout=stdout, stderr=stderr, env=env) - error_msg: Optional[str] = None + error_msg: str | None = None startup_failure_msg = ( 'Appium server process is unable to start. Make sure proper values have been ' f"provided to 'node' ({node}), 'npm' ({npm}) and 'main_script' ({main_script}) " @@ -194,7 +195,7 @@ def _assert_is_running(self) -> None: raise AppiumStartupError() -def is_service_listening(url: str, timeout: float = 5, custom_validator: Optional[Callable[[], None]] = None) -> bool: +def is_service_listening(url: str, timeout: float = 5, custom_validator: Callable[[], None] | None = None) -> bool: """ Check if the service is running @@ -222,7 +223,7 @@ def is_service_listening(url: str, timeout: float = 5, custom_validator: Optiona return False -def find_executable(executable: str) -> Optional[str]: +def find_executable(executable: str) -> str | None: path = os.environ['PATH'] paths = path.split(os.pathsep) _, ext = os.path.splitext(executable) @@ -256,8 +257,8 @@ def get_npm() -> str: return result -def get_main_script(node: Optional[str], npm: Optional[str]) -> str: - result: Optional[str] = None +def get_main_script(node: str | None, npm: str | None) -> str: + result: str | None = None npm_path = npm or get_npm() for args in [['root', '-g'], ['root']]: try: @@ -281,26 +282,26 @@ def get_main_script(node: Optional[str], npm: Optional[str]) -> str: return result -def _parse_arg_value(args: List[str], arg_names: Set[str], default: str) -> str: +def _parse_arg_value(args: list[str], arg_names: set[str], default: str) -> str: for idx, arg in enumerate(args): if arg in arg_names and idx < len(args) - 1: return args[idx + 1] return default -def _parse_port(args: List[str]) -> int: +def _parse_port(args: list[str]) -> int: return int(_parse_arg_value(args, {'--port', '-p'}, str(DEFAULT_PORT))) -def _parse_base_path(args: List[str]) -> str: +def _parse_base_path(args: list[str]) -> str: return _parse_arg_value(args, {'--base-path', '-pa'}, DEFAULT_BASE_PATH) -def _parse_host(args: List[str]) -> str: +def _parse_host(args: list[str]) -> str: return _parse_arg_value(args, {'--address', '-a'}, DEFAULT_HOST) -def _parse_protocol(args: List[str]) -> str: +def _parse_protocol(args: list[str]) -> str: return ( 'https' if _parse_arg_value(args, {'--ssl-cert-path'}, '') and _parse_arg_value(args, {'--ssl-key-path'}, '') @@ -308,12 +309,12 @@ def _parse_protocol(args: List[str]) -> str: ) -def _make_status_path(args: List[str]) -> str: +def _make_status_path(args: list[str]) -> str: base_path = _parse_base_path(args) return STATUS_URL if base_path == DEFAULT_BASE_PATH else f'{re.sub(r"/+$", "", base_path)}{STATUS_URL}' -def _make_server_url(args: List[str]) -> str: +def _make_server_url(args: list[str]) -> str: return f'{_parse_protocol(args)}://{_parse_host(args)}:{_parse_port(args)}{_make_status_path(args)}' diff --git a/appium/webdriver/errorhandler.py b/appium/webdriver/errorhandler.py index b2a5cab91..d074b01a8 100644 --- a/appium/webdriver/errorhandler.py +++ b/appium/webdriver/errorhandler.py @@ -13,14 +13,15 @@ # limitations under the License. import json -from typing import Any, Dict, List, Sequence, Type, Union +from collections.abc import Sequence +from typing import Any import selenium.common.exceptions as sel_exceptions from selenium.webdriver.remote import errorhandler import appium.common.exceptions as appium_exceptions -ERROR_TO_EXC_MAPPING: Dict[str, Type[sel_exceptions.WebDriverException]] = { +ERROR_TO_EXC_MAPPING: dict[str, type[sel_exceptions.WebDriverException]] = { 'element click intercepted': sel_exceptions.ElementClickInterceptedException, 'element not interactable': sel_exceptions.ElementNotInteractableException, 'insecure certificate': sel_exceptions.InsecureCertificateException, @@ -55,13 +56,13 @@ } -def format_stacktrace(original: Union[None, str, Sequence]) -> List[str]: +def format_stacktrace(original: None | str | Sequence) -> list[str]: if not original: return [] if isinstance(original, str): return original.split('\n') - result: List[str] = [] + result: list[str] = [] try: for frame in original: if not isinstance(frame, dict): @@ -81,7 +82,7 @@ def format_stacktrace(original: Union[None, str, Sequence]) -> List[str]: class MobileErrorHandler(errorhandler.ErrorHandler): - def check_response(self, response: Dict[str, Any]) -> None: + def check_response(self, response: dict[str, Any]) -> None: """ https://www.w3.org/TR/webdriver/#errors """ @@ -107,7 +108,7 @@ def check_response(self, response: Dict[str, Any]) -> None: # In theory, we should also be checking HTTP status codes. # Java client, for example, prints a warning if the actual `error` # value does not match to the response's HTTP status code. - exception_class: Type[sel_exceptions.WebDriverException] = ERROR_TO_EXC_MAPPING.get( + exception_class: type[sel_exceptions.WebDriverException] = ERROR_TO_EXC_MAPPING.get( error, sel_exceptions.WebDriverException ) if exception_class is sel_exceptions.WebDriverException and message: diff --git a/appium/webdriver/extensions/action_helpers.py b/appium/webdriver/extensions/action_helpers.py index 9c3709223..be32ca9f1 100644 --- a/appium/webdriver/extensions/action_helpers.py +++ b/appium/webdriver/extensions/action_helpers.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TYPE_CHECKING, List, Optional, Tuple, cast +from typing import TYPE_CHECKING, cast from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.actions import interaction @@ -29,7 +29,7 @@ class ActionHelpers: - def scroll(self, origin_el: WebElement, destination_el: WebElement, duration: Optional[int] = None) -> Self: + def scroll(self, origin_el: WebElement, destination_el: WebElement, duration: int | None = None) -> Self: """Scrolls from one element to another Args: @@ -63,7 +63,7 @@ def scroll(self, origin_el: WebElement, destination_el: WebElement, duration: Op actions.perform() return self - def drag_and_drop(self, origin_el: WebElement, destination_el: WebElement, pause: Optional[float] = None) -> Self: + def drag_and_drop(self, origin_el: WebElement, destination_el: WebElement, pause: float | None = None) -> Self: """Drag the origin element to the destination element Args: @@ -84,7 +84,7 @@ def drag_and_drop(self, origin_el: WebElement, destination_el: WebElement, pause actions.perform() return self - def tap(self, positions: List[Tuple[int, int]], duration: Optional[int] = None) -> Self: + def tap(self, positions: list[tuple[int, int]], duration: int | None = None) -> Self: """Taps on an particular place with up to five fingers, holding for a certain time @@ -113,12 +113,10 @@ def tap(self, positions: List[Tuple[int, int]], duration: Optional[int] = None) actions.w3c_actions.pointer_action.release() actions.perform() else: - finger = 0 actions = ActionChains(cast('WebDriver', self)) actions.w3c_actions.devices = [] - for position in positions: - finger += 1 + for finger, position in enumerate(positions, start=1): x = position[0] y = position[1] diff --git a/appium/webdriver/extensions/android/activities.py b/appium/webdriver/extensions/android/activities.py index 76da521b0..cdcfdc25c 100644 --- a/appium/webdriver/extensions/android/activities.py +++ b/appium/webdriver/extensions/android/activities.py @@ -12,35 +12,33 @@ # See the License for the specific language governing permissions and # limitations under the License. -from selenium.common.exceptions import TimeoutException, UnknownMethodException +from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from appium.webdriver.mobilecommand import MobileCommand as Command -class Activities(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class Activities(CanExecuteCommands, CanExecuteScripts): @property def current_activity(self) -> str: """Retrieves the current activity running on the device. + Requires the Appium driver to support the `mobile: getCurrentActivity` execute method. + Returns: str: The current activity name running on the device """ ext_name = 'mobile: getCurrentActivity' - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.GET_CURRENT_ACTIVITY)['value'] + return self.execute_script(ext_name) def wait_activity(self, activity: str, timeout: int, interval: int = 1) -> bool: """Wait for an activity: block until target activity presents or time out. This is an Android-only method. + Requires the Appium driver to support the `mobile: getCurrentActivity` execute method. + Args: activity: target activity timeout: max wait time, in seconds @@ -56,10 +54,3 @@ def wait_activity(self, activity: str, timeout: int, interval: int = 1) -> bool: return True except TimeoutException: return False - - def _add_commands(self) -> None: - self.command_executor.add_command( - Command.GET_CURRENT_ACTIVITY, - 'GET', - '/session/$sessionId/appium/device/current_activity', - ) diff --git a/appium/webdriver/extensions/android/common.py b/appium/webdriver/extensions/android/common.py index fe75260b5..79572107f 100644 --- a/appium/webdriver/extensions/android/common.py +++ b/appium/webdriver/extensions/android/common.py @@ -12,48 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -from selenium.common.exceptions import UnknownMethodException from typing_extensions import Self from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from appium.webdriver.mobilecommand import MobileCommand as Command -class Common(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class Common(CanExecuteCommands, CanExecuteScripts): def open_notifications(self) -> Self: """Open notification shade in Android (API Level 18 and above) Returns: Union['WebDriver', 'Common']: Self instance """ - ext_name = 'mobile: openNotifications' - try: - self.assert_extension_exists(ext_name).execute_script(ext_name) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.OPEN_NOTIFICATIONS, {}) + self.execute_script('mobile: openNotifications') return self @property def current_package(self) -> str: """Retrieves the current package running on the device.""" - ext_name = 'mobile: getCurrentPackage' - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.GET_CURRENT_PACKAGE)['value'] - - def _add_commands(self) -> None: - self.command_executor.add_command( - Command.GET_CURRENT_PACKAGE, - 'GET', - '/session/$sessionId/appium/device/current_package', - ) - self.command_executor.add_command( - Command.OPEN_NOTIFICATIONS, - 'POST', - '/session/$sessionId/appium/device/open_notifications', - ) + return self.execute_script('mobile: getCurrentPackage') diff --git a/appium/webdriver/extensions/android/display.py b/appium/webdriver/extensions/android/display.py index 28abdcbbf..4ee29ba79 100644 --- a/appium/webdriver/extensions/android/display.py +++ b/appium/webdriver/extensions/android/display.py @@ -12,18 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -from selenium.common.exceptions import UnknownMethodException - from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from appium.webdriver.mobilecommand import MobileCommand as Command -class Display(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class Display(CanExecuteCommands, CanExecuteScripts): def get_display_density(self) -> int: """Get the display density, Android only + Requires the Appium driver to support the `mobile: getDisplayDensity` execute method. + Returns: The display density of the Android device(dpi) @@ -34,15 +32,4 @@ def get_display_density(self) -> int: int: The display density """ ext_name = 'mobile: getDisplayDensity' - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.GET_DISPLAY_DENSITY)['value'] - - def _add_commands(self) -> None: - self.command_executor.add_command( - Command.GET_DISPLAY_DENSITY, - 'GET', - '/session/$sessionId/appium/device/display_density', - ) + return self.execute_script(ext_name) diff --git a/appium/webdriver/extensions/android/gsm.py b/appium/webdriver/extensions/android/gsm.py index ed43d3c66..56aedbd53 100644 --- a/appium/webdriver/extensions/android/gsm.py +++ b/appium/webdriver/extensions/android/gsm.py @@ -12,15 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -from selenium.common.exceptions import UnknownMethodException from typing_extensions import Self from appium.common.helper import extract_const_attributes from appium.common.logger import logger from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from appium.webdriver.mobilecommand import MobileCommand as Command class GsmCallActions: @@ -48,7 +45,7 @@ class GsmVoiceState: ON = 'on' -class Gsm(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class Gsm(CanExecuteCommands, CanExecuteScripts): def make_gsm_call(self, phone_number: str, action: str) -> Self: """Make GSM call (Emulator only) @@ -73,11 +70,7 @@ def make_gsm_call(self, phone_number: str, action: str) -> Self: f'(e.g. {GsmCallActions.__name__}.CALL)' ) args = {'phoneNumber': phone_number, 'action': action} - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.MAKE_GSM_CALL, args) + self.execute_script(ext_name, args) return self def set_gsm_signal(self, strength: int) -> Self: @@ -102,13 +95,7 @@ def set_gsm_signal(self, strength: int) -> Self: f'{strength} is out of range. Consider using one of {list(constants.keys())} constants. ' f'(e.g. {GsmSignalStrength.__name__}.GOOD)' ) - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, {'strength': strength}) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute( - Command.SET_GSM_SIGNAL, {'signalStrength': strength, 'signalStrengh': strength} - ) + self.execute_script(ext_name, {'strength': strength}) return self def set_gsm_voice(self, state: str) -> Self: @@ -134,14 +121,5 @@ def set_gsm_voice(self, state: str) -> Self: f'(e.g. {GsmVoiceState.__name__}.HOME)' ) args = {'state': state} - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.SET_GSM_VOICE, args) + self.execute_script(ext_name, args) return self - - def _add_commands(self) -> None: - self.command_executor.add_command(Command.MAKE_GSM_CALL, 'POST', '/session/$sessionId/appium/device/gsm_call') - self.command_executor.add_command(Command.SET_GSM_SIGNAL, 'POST', '/session/$sessionId/appium/device/gsm_signal') - self.command_executor.add_command(Command.SET_GSM_VOICE, 'POST', '/session/$sessionId/appium/device/gsm_voice') diff --git a/appium/webdriver/extensions/android/nativekey.py b/appium/webdriver/extensions/android/nativekey.py index 05b558790..59362681d 100644 --- a/appium/webdriver/extensions/android/nativekey.py +++ b/appium/webdriver/extensions/android/nativekey.py @@ -13,6 +13,50 @@ # limitations under the License. +class AndroidKeyMetastate: + """Keyboard metastate constants for Android key events. + + These constants can be combined with bitwise OR and passed to + Keyboard.press_keycode or Keyboard.long_press_keycode as metastate. + Values are based on android.view.KeyEvent. + https://developer.android.com/reference/android/view/KeyEvent + """ + + # No modifiers. + NONE = 0 + + # This mask is used to check whether one of the SHIFT meta keys is pressed. + META_SHIFT_ON = 0x01 + META_SHIFT_LEFT_ON = 0x40 + META_SHIFT_RIGHT_ON = 0x80 + + # This mask is used to check whether one of the ALT meta keys is pressed. + META_ALT_ON = 0x02 + META_ALT_LEFT_ON = 0x10 + META_ALT_RIGHT_ON = 0x20 + + # This mask is used to check whether one of the SYM meta keys is pressed. + META_SYM_ON = 0x04 + + # This mask is used to check whether the FUNCTION meta key is pressed. + META_FUNCTION_ON = 0x08 + + # This mask is used to check whether one of the CTRL meta keys is pressed. + META_CTRL_ON = 0x1000 + META_CTRL_LEFT_ON = 0x2000 + META_CTRL_RIGHT_ON = 0x4000 + + # This mask is used to check whether one of the META meta keys is pressed. + META_META_ON = 0x10000 + META_META_LEFT_ON = 0x20000 + META_META_RIGHT_ON = 0x40000 + + # Lock key states. + META_CAPS_LOCK_ON = 0x100000 + META_NUM_LOCK_ON = 0x200000 + META_SCROLL_LOCK_ON = 0x400000 + + class AndroidKey: # Key code constant: Unknown key code. UNKNOWN = 0 diff --git a/appium/webdriver/extensions/android/network.py b/appium/webdriver/extensions/android/network.py index 6054e29d9..ad039104c 100644 --- a/appium/webdriver/extensions/android/network.py +++ b/appium/webdriver/extensions/android/network.py @@ -12,15 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -from selenium.common.exceptions import UnknownMethodException from typing_extensions import Self from appium.common.helper import extract_const_attributes from appium.common.logger import logger from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from appium.webdriver.mobilecommand import MobileCommand as Command class NetSpeed: @@ -41,7 +38,7 @@ class NetworkMask: AIRPLANE_MODE = 0b001 -class Network(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class Network(CanExecuteCommands, CanExecuteScripts): @property def network_connection(self) -> int: """Returns an integer bitmask specifying the network connection type. @@ -51,18 +48,19 @@ def network_connection(self) -> int: This API only works reliably on emulators (any version) and real devices since API level 31. + + Requires the Appium driver to support the `mobile: getConnectivity` execute method. + + Returns: + The current network connection bitmask """ ext_name = 'mobile: getConnectivity' - try: - result_map = self.assert_extension_exists(ext_name).execute_script(ext_name) - return ( - (NetworkMask.WIFI if result_map['wifi'] else 0) - | (NetworkMask.DATA if result_map['data'] else 0) - | (NetworkMask.AIRPLANE_MODE if result_map['airplaneMode'] else 0) - ) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.GET_NETWORK_CONNECTION, {})['value'] + result_map = self.execute_script(ext_name) + return ( + (NetworkMask.WIFI if result_map['wifi'] else 0) + | (NetworkMask.DATA if result_map['data'] else 0) + | (NetworkMask.AIRPLANE_MODE if result_map['airplaneMode'] else 0) + ) def set_network_connection(self, connection_type: int) -> int: """Sets the network connection type. Android only. @@ -88,43 +86,39 @@ def set_network_connection(self, connection_type: int) -> int: This API only works reliably on emulators (any version) and real devices since API level 31. + Requires the Appium driver to support the `mobile: setConnectivity` and + `mobile: getConnectivity` execute methods. + Args: connection_type: a member of the enum `appium.webdriver.ConnectionType` - Return: - int: Set network connection type + Returns: + The current network connection bitmask after applying the change """ ext_name = 'mobile: setConnectivity' - try: - return self.assert_extension_exists(ext_name).execute_script( - ext_name, - { - 'wifi': bool(connection_type & NetworkMask.WIFI), - 'data': bool(connection_type & NetworkMask.DATA), - 'airplaneMode': bool(connection_type & NetworkMask.AIRPLANE_MODE), - }, - ) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute( - Command.SET_NETWORK_CONNECTION, {'parameters': {'type': connection_type}} - )['value'] + self.execute_script( + ext_name, + { + 'wifi': bool(connection_type & NetworkMask.WIFI), + 'data': bool(connection_type & NetworkMask.DATA), + 'airplaneMode': bool(connection_type & NetworkMask.AIRPLANE_MODE), + }, + ) + return self.network_connection def toggle_wifi(self) -> Self: """Toggle the wifi on the device, Android only. This API only works reliably on emulators (any version) and real devices since API level 31. + Requires the Appium driver to support the `mobile: getConnectivity` and + `mobile: setConnectivity` execute methods. + Returns: Union['WebDriver', 'Network']: Self instance """ ext_name = 'mobile: setConnectivity' - try: - self.assert_extension_exists(ext_name).execute_script( - ext_name, {'wifi': not (self.network_connection & NetworkMask.WIFI)} - ) - except UnknownMethodException: - self.mark_extension_absence(ext_name).execute(Command.TOGGLE_WIFI, {}) + self.execute_script(ext_name, {'wifi': not (self.network_connection & NetworkMask.WIFI)}) return self def set_network_speed(self, speed_type: str) -> Self: @@ -132,6 +126,8 @@ def set_network_speed(self, speed_type: str) -> Self: Android Emulator only. + Requires the Appium driver to support the `mobile: networkSpeed` execute method. + Args: speed_type: The network speed type. A member of the const appium.webdriver.extensions.android.network.NetSpeed. @@ -149,27 +145,5 @@ def set_network_speed(self, speed_type: str) -> Self: f'(e.g. {NetSpeed.__name__}.LTE)' ) ext_name = 'mobile: networkSpeed' - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, {'speed': speed_type}) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.SET_NETWORK_SPEED, {'netspeed': speed_type}) + self.execute_script(ext_name, {'speed': speed_type}) return self - - def _add_commands(self) -> None: - self.command_executor.add_command(Command.TOGGLE_WIFI, 'POST', '/session/$sessionId/appium/device/toggle_wifi') - self.command_executor.add_command( - Command.GET_NETWORK_CONNECTION, - 'GET', - '/session/$sessionId/network_connection', - ) - self.command_executor.add_command( - Command.SET_NETWORK_CONNECTION, - 'POST', - '/session/$sessionId/network_connection', - ) - self.command_executor.add_command( - Command.SET_NETWORK_SPEED, - 'POST', - '/session/$sessionId/appium/device/network_speed', - ) diff --git a/appium/webdriver/extensions/android/performance.py b/appium/webdriver/extensions/android/performance.py index f5781cf3f..4994eca38 100644 --- a/appium/webdriver/extensions/android/performance.py +++ b/appium/webdriver/extensions/android/performance.py @@ -12,31 +12,27 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, List, Union - -from selenium.common.exceptions import UnknownMethodException from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from appium.webdriver.mobilecommand import MobileCommand as Command -class Performance(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): - def get_performance_data( - self, package_name: str, data_type: str, data_read_timeout: Union[int, None] = None - ) -> List[List[str]]: +class Performance(CanExecuteCommands, CanExecuteScripts): + def get_performance_data(self, package_name: str, data_type: str, data_read_timeout: int | None = None) -> list[list[str]]: """Returns the information of the system state which is supported to read as like cpu, memory, network traffic, and battery. Android only. + Requires the Appium driver to support the `mobile: getPerformanceData` execute method. + Args: package_name: The package name of the application data_type: The type of system state which wants to read. It should be one of the supported performance data types. Check :func:`.get_performance_data_types` for supported types - data_read_timeout: The number of attempts to read + data_read_timeout: Legacy parameter retained for compatibility; ignored by + `mobile: getPerformanceData` Usage: self.driver.get_performance_data('my.app.package', 'cpuinfo', 5) @@ -45,20 +41,16 @@ def get_performance_data( The data along to `data_type` """ ext_name = 'mobile: getPerformanceData' - args: Dict[str, Union[str, int]] = {'packageName': package_name, 'dataType': data_type} - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - # TODO: Remove the fallback - if data_read_timeout is not None: - args['dataReadTimeout'] = data_read_timeout - return self.mark_extension_absence(ext_name).execute(Command.GET_PERFORMANCE_DATA, args)['value'] + args: dict[str, str | int] = {'packageName': package_name, 'dataType': data_type} + return self.execute_script(ext_name, args) - def get_performance_data_types(self) -> List[str]: + def get_performance_data_types(self) -> list[str]: """Returns the information types of the system state which is supported to read as like cpu, memory, network traffic, and battery. Android only. + Requires the Appium driver to support the `mobile: getPerformanceDataTypes` execute method. + Usage: self.driver.get_performance_data_types() @@ -66,20 +58,4 @@ def get_performance_data_types(self) -> List[str]: Available data types """ ext_name = 'mobile: getPerformanceDataTypes' - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.GET_PERFORMANCE_DATA_TYPES)['value'] - - def _add_commands(self) -> None: - self.command_executor.add_command( - Command.GET_PERFORMANCE_DATA, - 'POST', - '/session/$sessionId/appium/getPerformanceData', - ) - self.command_executor.add_command( - Command.GET_PERFORMANCE_DATA_TYPES, - 'POST', - '/session/$sessionId/appium/performanceData/types', - ) + return self.execute_script(ext_name) diff --git a/appium/webdriver/extensions/android/power.py b/appium/webdriver/extensions/android/power.py index 537ab6803..7b8b574ec 100644 --- a/appium/webdriver/extensions/android/power.py +++ b/appium/webdriver/extensions/android/power.py @@ -12,16 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -from selenium.common.exceptions import UnknownMethodException from typing_extensions import Self from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from appium.webdriver.mobilecommand import MobileCommand as Command -class Power(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class Power(CanExecuteCommands, CanExecuteScripts): AC_OFF, AC_ON = 'off', 'on' def set_power_capacity(self, percent: int) -> Self: @@ -29,6 +26,8 @@ def set_power_capacity(self, percent: int) -> Self: Android only. + Requires the Appium driver to support the `mobile: powerCapacity` execute method. + Args: percent: The power capacity to be set. Can be set from 0 to 100 @@ -40,11 +39,7 @@ def set_power_capacity(self, percent: int) -> Self: """ ext_name = 'mobile: powerCapacity' args = {'percent': percent} - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.SET_POWER_CAPACITY, args) + self.execute_script(ext_name, args) return self def set_power_ac(self, ac_state: str) -> Self: @@ -52,6 +47,8 @@ def set_power_ac(self, ac_state: str) -> Self: Android only. + Requires the Appium driver to support the `mobile: powerAC` execute method. + Args: ac_state: The power ac state to be set. Use `Power.AC_OFF`, `Power.AC_ON` @@ -64,17 +61,5 @@ def set_power_ac(self, ac_state: str) -> Self: """ ext_name = 'mobile: powerAC' args = {'state': ac_state} - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.SET_POWER_AC, args) + self.execute_script(ext_name, args) return self - - def _add_commands(self) -> None: - self.command_executor.add_command( - Command.SET_POWER_CAPACITY, - 'POST', - '/session/$sessionId/appium/device/power_capacity', - ) - self.command_executor.add_command(Command.SET_POWER_AC, 'POST', '/session/$sessionId/appium/device/power_ac') diff --git a/appium/webdriver/extensions/android/sms.py b/appium/webdriver/extensions/android/sms.py index f5769c561..c4ada1f50 100644 --- a/appium/webdriver/extensions/android/sms.py +++ b/appium/webdriver/extensions/android/sms.py @@ -12,21 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -from selenium.common.exceptions import UnknownMethodException from typing_extensions import Self from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from appium.webdriver.mobilecommand import MobileCommand as Command -class Sms(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class Sms(CanExecuteCommands, CanExecuteScripts): def send_sms(self, phone_number: str, message: str) -> Self: """Emulate send SMS event on the connected emulator. Android only. + Requires the Appium driver to support the `mobile: sendSms` execute method. + Args: phone_number: The phone number of message sender message: The message to send @@ -39,12 +38,5 @@ def send_sms(self, phone_number: str, message: str) -> Self: """ ext_name = 'mobile: sendSms' args = {'phoneNumber': phone_number, 'message': message} - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.SEND_SMS, args) + self.execute_script(ext_name, args) return self - - def _add_commands(self) -> None: - self.command_executor.add_command(Command.SEND_SMS, 'POST', '/session/$sessionId/appium/device/send_sms') diff --git a/appium/webdriver/extensions/android/system_bars.py b/appium/webdriver/extensions/android/system_bars.py index a02c21f8f..80ea273e2 100644 --- a/appium/webdriver/extensions/android/system_bars.py +++ b/appium/webdriver/extensions/android/system_bars.py @@ -12,22 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, Union - -from selenium.common.exceptions import UnknownMethodException from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from appium.webdriver.mobilecommand import MobileCommand as Command -class SystemBars(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): - def get_system_bars(self) -> Dict[str, Dict[str, Union[int, bool]]]: +class SystemBars(CanExecuteCommands, CanExecuteScripts): + def get_system_bars(self) -> dict[str, dict[str, int | bool]]: """Retrieve visibility and bounds information of the status and navigation bars. Android only. + Requires the Appium driver to support the `mobile: getSystemBars` execute method. + Returns: A dictionary whose keys are - statusBar @@ -44,15 +41,4 @@ def get_system_bars(self) -> Dict[str, Dict[str, Union[int, bool]]]: - height """ ext_name = 'mobile: getSystemBars' - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.GET_SYSTEM_BARS)['value'] - - def _add_commands(self) -> None: - self.command_executor.add_command( - Command.GET_SYSTEM_BARS, - 'GET', - '/session/$sessionId/appium/device/system_bars', - ) + return self.execute_script(ext_name) diff --git a/appium/webdriver/extensions/applications.py b/appium/webdriver/extensions/applications.py index b259422ec..583e8ba5e 100644 --- a/appium/webdriver/extensions/applications.py +++ b/appium/webdriver/extensions/applications.py @@ -11,19 +11,15 @@ # 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 typing import Any, Dict, Union +from typing import Any -from selenium.common.exceptions import InvalidArgumentException, UnknownMethodException from typing_extensions import Self from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from ..mobilecommand import MobileCommand as Command - -class Applications(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class Applications(CanExecuteCommands, CanExecuteScripts): def background_app(self, seconds: int) -> Self: """Puts the application in the background on the device for a certain duration. @@ -37,11 +33,7 @@ def background_app(self, seconds: int) -> Self: """ ext_name = 'mobile: backgroundApp' args = {'seconds': seconds} - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.BACKGROUND, args) + self.execute_script(ext_name, args) return self def is_app_installed(self, bundle_id: str) -> bool: @@ -54,22 +46,13 @@ def is_app_installed(self, bundle_id: str) -> bool: `True` if app is installed """ ext_name = 'mobile: isAppInstalled' - try: - return self.assert_extension_exists(ext_name).execute_script( - ext_name, - { - 'bundleId': bundle_id, - 'appId': bundle_id, - }, - ) - except (UnknownMethodException, InvalidArgumentException): - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute( - Command.IS_APP_INSTALLED, - { - 'bundleId': bundle_id, - }, - )['value'] + return self.execute_script( + ext_name, + { + 'bundleId': bundle_id, + 'appId': bundle_id, + }, + ) def install_app(self, app_path: str, **options: Any) -> Self: """Install the application found at `app_path` on the device. @@ -91,22 +74,14 @@ def install_app(self, app_path: str, **options: Any) -> Self: Returns: Union['WebDriver', 'Applications']: Self instance """ - ext_name = 'mobile: installApp' - try: - self.assert_extension_exists(ext_name).execute_script( - 'mobile: installApp', - { - 'app': app_path, - 'appPath': app_path, - **(options or {}), - }, - ) - except (UnknownMethodException, InvalidArgumentException): - # TODO: Remove the fallback - data: Dict[str, Any] = {'appPath': app_path} - if options: - data.update({'options': options}) - self.mark_extension_absence(ext_name).execute(Command.INSTALL_APP, data) + self.execute_script( + 'mobile: installApp', + { + 'app': app_path, + 'appPath': app_path, + **(options or {}), + }, + ) return self def remove_app(self, app_id: str, **options: Any) -> Self: @@ -125,21 +100,14 @@ def remove_app(self, app_id: str, **options: Any) -> Self: Union['WebDriver', 'Applications']: Self instance """ ext_name = 'mobile: removeApp' - try: - self.assert_extension_exists(ext_name).execute_script( - ext_name, - { - 'appId': app_id, - 'bundleId': app_id, - **(options or {}), - }, - ) - except (UnknownMethodException, InvalidArgumentException): - # TODO: Remove the fallback - data: Dict[str, Any] = {'appId': app_id} - if options: - data.update({'options': options}) - self.mark_extension_absence(ext_name).execute(Command.REMOVE_APP, data) + self.execute_script( + ext_name, + { + 'appId': app_id, + 'bundleId': app_id, + **(options or {}), + }, + ) return self def terminate_app(self, app_id: str, **options: Any) -> bool: @@ -156,21 +124,14 @@ def terminate_app(self, app_id: str, **options: Any) -> bool: True if the app has been successfully terminated """ ext_name = 'mobile: terminateApp' - try: - return self.assert_extension_exists(ext_name).execute_script( - ext_name, - { - 'appId': app_id, - 'bundleId': app_id, - **(options or {}), - }, - ) - except (UnknownMethodException, InvalidArgumentException): - # TODO: Remove the fallback - data: Dict[str, Any] = {'appId': app_id} - if options: - data.update({'options': options}) - return self.mark_extension_absence(ext_name).execute(Command.TERMINATE_APP, data)['value'] + return self.execute_script( + ext_name, + { + 'appId': app_id, + 'bundleId': app_id, + **(options or {}), + }, + ) def activate_app(self, app_id: str) -> Self: """Activates the application if it is not running @@ -183,17 +144,13 @@ def activate_app(self, app_id: str) -> Self: Union['WebDriver', 'Applications']: Self instance """ ext_name = 'mobile: activateApp' - try: - self.assert_extension_exists(ext_name).execute_script( - ext_name, - { - 'appId': app_id, - 'bundleId': app_id, - }, - ) - except (UnknownMethodException, InvalidArgumentException): - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.ACTIVATE_APP, {'appId': app_id}) + self.execute_script( + ext_name, + { + 'appId': app_id, + 'bundleId': app_id, + }, + ) return self def query_app_state(self, app_id: str) -> int: @@ -207,24 +164,15 @@ def query_app_state(self, app_id: str) -> int: class for more details. """ ext_name = 'mobile: queryAppState' - try: - return self.assert_extension_exists(ext_name).execute_script( - ext_name, - { - 'appId': app_id, - 'bundleId': app_id, - }, - ) - except (UnknownMethodException, InvalidArgumentException): - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute( - Command.QUERY_APP_STATE, - { - 'appId': app_id, - }, - )['value'] + return self.execute_script( + ext_name, + { + 'appId': app_id, + 'bundleId': app_id, + }, + ) - def app_strings(self, language: Union[str, None] = None, string_file: Union[str, None] = None) -> Dict[str, str]: + def app_strings(self, language: str | None = None, string_file: str | None = None) -> dict[str, str]: """Returns the application strings from the device for the specified language. @@ -241,34 +189,4 @@ def app_strings(self, language: Union[str, None] = None, string_file: Union[str, data['language'] = language if string_file is not None: data['stringFile'] = string_file - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name, data) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.GET_APP_STRINGS, data)['value'] - - def _add_commands(self) -> None: - self.command_executor.add_command(Command.BACKGROUND, 'POST', '/session/$sessionId/appium/app/background') - self.command_executor.add_command( - Command.IS_APP_INSTALLED, - 'POST', - '/session/$sessionId/appium/device/app_installed', - ) - self.command_executor.add_command(Command.INSTALL_APP, 'POST', '/session/$sessionId/appium/device/install_app') - self.command_executor.add_command(Command.REMOVE_APP, 'POST', '/session/$sessionId/appium/device/remove_app') - self.command_executor.add_command( - Command.TERMINATE_APP, - 'POST', - '/session/$sessionId/appium/device/terminate_app', - ) - self.command_executor.add_command( - Command.ACTIVATE_APP, - 'POST', - '/session/$sessionId/appium/device/activate_app', - ) - self.command_executor.add_command( - Command.QUERY_APP_STATE, - 'POST', - '/session/$sessionId/appium/device/app_state', - ) - self.command_executor.add_command(Command.GET_APP_STRINGS, 'POST', '/session/$sessionId/appium/app/strings') + return self.execute_script(ext_name, data) diff --git a/appium/webdriver/extensions/clipboard.py b/appium/webdriver/extensions/clipboard.py index f5354f2e7..9afe0923c 100644 --- a/appium/webdriver/extensions/clipboard.py +++ b/appium/webdriver/extensions/clipboard.py @@ -13,25 +13,22 @@ # limitations under the License. import base64 -from typing import Optional -from selenium.common.exceptions import UnknownMethodException from typing_extensions import Self from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence from appium.webdriver.clipboard_content_type import ClipboardContentType -from ..mobilecommand import MobileCommand as Command - -class Clipboard(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class Clipboard(CanExecuteCommands, CanExecuteScripts): def set_clipboard( - self, content: bytes, content_type: str = ClipboardContentType.PLAINTEXT, label: Optional[str] = None + self, content: bytes, content_type: str = ClipboardContentType.PLAINTEXT, label: str | None = None ) -> Self: """Set the content of the system clipboard + Requires the Appium driver to support the `mobile: setClipboard` execute method. + Args: content: The content to be set as bytearray string content_type: One of ClipboardContentType items. Only ClipboardContentType.PLAINTEXT @@ -48,16 +45,14 @@ def set_clipboard( } if label: options['label'] = label - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, options) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.SET_CLIPBOARD, options) + self.execute_script(ext_name, options) return self - def set_clipboard_text(self, text: str, label: Optional[str] = None) -> Self: + def set_clipboard_text(self, text: str, label: str | None = None) -> Self: """Copies the given text to the system clipboard + Requires the Appium driver to support the `mobile: setClipboard` execute method. + Args: text: The text to be set label:label argument, which only works for Android @@ -70,6 +65,8 @@ def set_clipboard_text(self, text: str, label: Optional[str] = None) -> Self: def get_clipboard(self, content_type: str = ClipboardContentType.PLAINTEXT) -> bytes: """Receives the content of the system clipboard + Requires the Appium driver to support the `mobile: getClipboard` execute method. + Args: content_type: One of ClipboardContentType items. Only ClipboardContentType.PLAINTEXT is supported on Android @@ -79,29 +76,15 @@ def get_clipboard(self, content_type: str = ClipboardContentType.PLAINTEXT) -> b """ ext_name = 'mobile: getClipboard' options = {'contentType': content_type} - try: - base64_str = self.assert_extension_exists(ext_name).execute_script(ext_name, options) - except UnknownMethodException: - # TODO: Remove the fallback - base64_str = self.mark_extension_absence(ext_name).execute(Command.GET_CLIPBOARD, options)['value'] + base64_str = self.execute_script(ext_name, options) return base64.b64decode(base64_str) def get_clipboard_text(self) -> str: """Receives the text of the system clipboard + Requires the Appium driver to support the `mobile: getClipboard` execute method. + Returns: The actual clipboard text or an empty string if the clipboard is empty """ return self.get_clipboard(ClipboardContentType.PLAINTEXT).decode('UTF-8') - - def _add_commands(self) -> None: - self.command_executor.add_command( - Command.SET_CLIPBOARD, - 'POST', - '/session/$sessionId/appium/device/set_clipboard', - ) - self.command_executor.add_command( - Command.GET_CLIPBOARD, - 'POST', - '/session/$sessionId/appium/device/get_clipboard', - ) diff --git a/appium/webdriver/extensions/context.py b/appium/webdriver/extensions/context.py index 628432e11..fff3ecc30 100644 --- a/appium/webdriver/extensions/context.py +++ b/appium/webdriver/extensions/context.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import List from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands @@ -21,7 +20,7 @@ class Context(CanExecuteCommands): @property - def contexts(self) -> List[str]: + def contexts(self) -> list[str]: """Returns the contexts within the current session. Usage: diff --git a/appium/webdriver/extensions/device_time.py b/appium/webdriver/extensions/device_time.py index 22ac3c25a..3eef3dda9 100644 --- a/appium/webdriver/extensions/device_time.py +++ b/appium/webdriver/extensions/device_time.py @@ -12,35 +12,29 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional - -from selenium.common.exceptions import UnknownMethodException from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence - -from ..mobilecommand import MobileCommand as Command -class DeviceTime(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class DeviceTime(CanExecuteCommands, CanExecuteScripts): @property def device_time(self) -> str: """Returns the date and time from the device. + Requires the Appium driver to support the `mobile: getDeviceTime` execute method. + Return: str: The date and time """ ext_name = 'mobile: getDeviceTime' - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.GET_DEVICE_TIME_GET, {})['value'] + return self.execute_script(ext_name) - def get_device_time(self, format: Optional[str] = None) -> str: + def get_device_time(self, format: str | None = None) -> str: """Returns the date and time from the device. + Requires the Appium driver to support the `mobile: getDeviceTime` execute method. + Args: format: The set of format specifiers. Read https://momentjs.com/docs/ to get the full list of supported datetime format specifiers. @@ -57,19 +51,4 @@ def get_device_time(self, format: Optional[str] = None) -> str: ext_name = 'mobile: getDeviceTime' if format is None: return self.device_time - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name, {'format': format}) - except UnknownMethodException: - return self.mark_extension_absence(ext_name).execute(Command.GET_DEVICE_TIME_POST, {'format': format})['value'] - - def _add_commands(self) -> None: - self.command_executor.add_command( - Command.GET_DEVICE_TIME_GET, - 'GET', - '/session/$sessionId/appium/device/system_time', - ) - self.command_executor.add_command( - Command.GET_DEVICE_TIME_POST, - 'POST', - '/session/$sessionId/appium/device/system_time', - ) + return self.execute_script(ext_name, {'format': format}) diff --git a/appium/webdriver/extensions/execute_driver.py b/appium/webdriver/extensions/execute_driver.py index 698c0218b..aa479ed8a 100644 --- a/appium/webdriver/extensions/execute_driver.py +++ b/appium/webdriver/extensions/execute_driver.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Dict, Optional, Union +from typing import Any from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands @@ -21,7 +21,7 @@ class ExecuteDriver(CanExecuteCommands): # TODO Inner class case - def execute_driver(self, script: str, script_type: str = 'webdriverio', timeout_ms: Optional[int] = None) -> Any: + def execute_driver(self, script: str, script_type: str = 'webdriverio', timeout_ms: int | None = None) -> Any: """Run a set of script against the current session, allowing execution of many commands in one Appium request. Please read http://appium.io/docs/en/commands/session/execute-driver for more details about the acceptable scripts and the output format. @@ -45,11 +45,11 @@ def execute_driver(self, script: str, script_type: str = 'webdriverio', timeout_ """ class Result: - def __init__(self, res: Dict): + def __init__(self, res: dict): self.result = res['result'] self.logs = res['logs'] - option: Dict[str, Union[str, int]] = {'script': script, 'type': script_type} + option: dict[str, str | int] = {'script': script, 'type': script_type} if timeout_ms is not None: option['timeout'] = timeout_ms diff --git a/appium/webdriver/extensions/execute_mobile_command.py b/appium/webdriver/extensions/execute_mobile_command.py index 8d78d418b..2cc8c172a 100644 --- a/appium/webdriver/extensions/execute_mobile_command.py +++ b/appium/webdriver/extensions/execute_mobile_command.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Dict +from typing import Any from typing_extensions import Self @@ -39,7 +39,7 @@ def press_button(self, button_name: str) -> Self: return self @property - def battery_info(self) -> Dict[str, Any]: + def battery_info(self) -> dict[str, Any]: """Retrieves battery information for the device under test. Returns: diff --git a/appium/webdriver/extensions/flutter_integration/flutter_commands.py b/appium/webdriver/extensions/flutter_integration/flutter_commands.py index 5e469cae1..365ee29f4 100644 --- a/appium/webdriver/extensions/flutter_integration/flutter_commands.py +++ b/appium/webdriver/extensions/flutter_integration/flutter_commands.py @@ -13,7 +13,7 @@ # limitations under the License. import os -from typing import Any, Dict, List, Optional, Tuple, Union +from typing import Any, Union from appium.common.helper import encode_file_to_base64 from appium.webdriver.extensions.flutter_integration.flutter_finder import FlutterFinder @@ -30,8 +30,8 @@ def __init__(self, driver: WebDriver) -> None: def wait_for_visible( self, - locator: Union[WebElement, FlutterFinder], - timeout: Optional[float] = None, + locator: WebElement | FlutterFinder, + timeout: float | None = None, ) -> None: """ Waits for a element to become visible. @@ -43,7 +43,7 @@ def wait_for_visible( Returns: None """ - opts: Dict[str, Any] = self.__get_locator_options(locator) + opts: dict[str, Any] = self.__get_locator_options(locator) if timeout is not None: opts['timeout'] = timeout @@ -51,8 +51,8 @@ def wait_for_visible( def wait_for_invisible( self, - locator: Union[WebElement, FlutterFinder], - timeout: Optional[float] = None, + locator: WebElement | FlutterFinder, + timeout: float | None = None, ) -> None: """ Waits for a element to become invisible. @@ -64,7 +64,7 @@ def wait_for_invisible( Returns: None: """ - opts: Dict[str, Any] = self.__get_locator_options(locator) + opts: dict[str, Any] = self.__get_locator_options(locator) if timeout is not None: opts['timeout'] = timeout @@ -72,7 +72,7 @@ def wait_for_invisible( # flutter action commands - def perform_double_click(self, element: WebElement, offset: Optional[Tuple[int, int]] = None) -> None: + def perform_double_click(self, element: WebElement, offset: tuple[int, int] | None = None) -> None: """ Performs a double-click on the given element, with an optional offset. @@ -83,12 +83,12 @@ def perform_double_click(self, element: WebElement, offset: Optional[Tuple[int, Returns: None: """ - opts: Dict[str, Union[WebElement, Dict[str, int]]] = {'origin': element} + opts: dict[str, WebElement | dict[str, int]] = {'origin': element} if offset is not None: opts['offset'] = {'x': offset[0], 'y': offset[1]} self.execute_flutter_command('doubleClick', opts) - def perform_long_press(self, element: WebElement, offset: Optional[Tuple[int, int]] = None) -> None: + def perform_long_press(self, element: WebElement, offset: tuple[int, int] | None = None) -> None: """ Performs a long press on the given element, with an optional offset. @@ -99,7 +99,7 @@ def perform_long_press(self, element: WebElement, offset: Optional[Tuple[int, in Returns: None: """ - opts: Dict[str, Union[WebElement, Dict[str, int]]] = {'origin': element} + opts: dict[str, WebElement | dict[str, int]] = {'origin': element} if offset is not None: opts['offset'] = {'x': offset[0], 'y': offset[1]} self.execute_flutter_command('longPress', opts) @@ -154,10 +154,7 @@ def inject_mock_image(self, value: str) -> str: Returns: str: Image ID of the injected image. """ - if os.path.isfile(value): - base64_encoded_image = encode_file_to_base64(value) - else: - base64_encoded_image = value + base64_encoded_image = encode_file_to_base64(value) if os.path.isfile(value) else value return self.execute_flutter_command('injectImage', {'base64Image': base64_encoded_image}) def activate_injected_image(self, image_id: str) -> None: @@ -174,10 +171,10 @@ def activate_injected_image(self, image_id: str) -> None: def get_render_tree( self, - widget_type: Optional[str] = None, - key: Optional[str] = None, - text: Optional[str] = None, - ) -> List[Optional[Dict]]: + widget_type: str | None = None, + key: str | None = None, + text: str | None = None, + ) -> list[dict | None]: """ Returns the render tree of the root widget. @@ -290,7 +287,7 @@ def execute_flutter_command(self, scriptName: str, params: dict) -> Any: """ return self.driver.execute_script(f'flutter: {scriptName}', params) - def __get_locator_options(self, locator: Union[WebElement, 'FlutterFinder']) -> Dict[str, Union[dict, WebElement]]: + def __get_locator_options(self, locator: Union[WebElement, 'FlutterFinder']) -> dict[str, dict | WebElement]: if isinstance(locator, WebElement): return {'element': locator} return {'locator': locator.to_dict()} diff --git a/appium/webdriver/extensions/flutter_integration/flutter_finder.py b/appium/webdriver/extensions/flutter_integration/flutter_finder.py index 0aed46a9a..a92425f27 100644 --- a/appium/webdriver/extensions/flutter_integration/flutter_finder.py +++ b/appium/webdriver/extensions/flutter_integration/flutter_finder.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from typing import Tuple, Union, cast +from typing import cast from selenium.webdriver.common.by import ByType as SeleniumByType @@ -24,7 +24,7 @@ class FlutterFinder: - def __init__(self, using: Union[SeleniumByType, AppiumByType], value: str) -> None: + def __init__(self, using: SeleniumByType | AppiumByType, value: str) -> None: self.using = using self.value = value @@ -51,5 +51,5 @@ def by_text_containing(value: str) -> 'FlutterFinder': def to_dict(self) -> dict: return {'using': self.using, 'value': self.value} - def as_args(self) -> Tuple[str, str]: + def as_args(self) -> tuple[str, str]: return self.using, self.value diff --git a/appium/webdriver/extensions/hw_actions.py b/appium/webdriver/extensions/hw_actions.py index b6bbb468b..c3bc5527c 100644 --- a/appium/webdriver/extensions/hw_actions.py +++ b/appium/webdriver/extensions/hw_actions.py @@ -12,21 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional -from selenium.common.exceptions import UnknownMethodException from typing_extensions import Self from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from ..mobilecommand import MobileCommand as Command +class HardwareActions(CanExecuteCommands, CanExecuteScripts): + def lock(self, seconds: int | None = None) -> Self: + """Lock the device. No changes are made if the device is already locked. -class HardwareActions(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): - def lock(self, seconds: Optional[int] = None) -> Self: - """Lock the device. No changes are made if the device is already unlocked. + Requires the Appium driver to support the `mobile: lock` execute method. Args: seconds: The duration to lock the device, in seconds. @@ -39,54 +36,44 @@ def lock(self, seconds: Optional[int] = None) -> Self: """ ext_name = 'mobile: lock' args = {'seconds': seconds or 0} - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.LOCK, args) + self.execute_script(ext_name, args) return self def unlock(self) -> Self: - """Unlock the device. No changes are made if the device is already locked. + """Unlock the device. No changes are made if the device is already unlocked. + + Requires the Appium driver to support the `mobile: isLocked` and `mobile: unlock` execute methods. Returns: Union['WebDriver', 'HardwareActions']: Self instance """ ext_name = 'mobile: unlock' - try: - if not self.assert_extension_exists(ext_name).execute_script('mobile: isLocked'): - return self - self.execute_script(ext_name) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.UNLOCK) + if not self.execute_script('mobile: isLocked'): + return self + self.execute_script(ext_name) return self def is_locked(self) -> bool: """Checks whether the device is locked. + Requires the Appium driver to support the `mobile: isLocked` execute method. + Returns: `True` if the device is locked """ ext_name = 'mobile: isLocked' - try: - return self.assert_extension_exists(ext_name).execute_script('mobile: isLocked') - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.IS_LOCKED)['value'] + return self.execute_script(ext_name) def shake(self) -> Self: """Shake the device. + Requires the Appium driver to support the `mobile: shake` execute method. + Returns: Union['WebDriver', 'HardwareActions']: Self instance """ ext_name = 'mobile: shake' - try: - self.assert_extension_exists(ext_name).execute_script(ext_name) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.SHAKE) + self.execute_script(ext_name) return self def touch_id(self, match: bool) -> Self: @@ -118,32 +105,17 @@ def toggle_touch_id_enrollment(self) -> Self: return self def finger_print(self, finger_id: int) -> Self: - """Authenticate users by using their finger print scans on supported Android emulators. + """Authenticate users using a fingerprint scan on supported Android emulators. + + Requires the Appium driver to support the `mobile: fingerprint` execute method. Args: - finger_id: Finger prints stored in Android Keystore system (from 1 to 10) + finger_id: Fingerprint identifier stored in the Android Keystore system (from 1 to 10) + + Returns: + Union['WebDriver', 'HardwareActions']: Self instance """ ext_name = 'mobile: fingerprint' args = {'fingerprintId': finger_id} - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - self.mark_extension_absence(ext_name).execute(Command.FINGER_PRINT, args) + self.execute_script(ext_name, args) return self - - def _add_commands(self) -> None: - self.command_executor.add_command(Command.LOCK, 'POST', '/session/$sessionId/appium/device/lock') - self.command_executor.add_command(Command.UNLOCK, 'POST', '/session/$sessionId/appium/device/unlock') - self.command_executor.add_command(Command.IS_LOCKED, 'POST', '/session/$sessionId/appium/device/is_locked') - self.command_executor.add_command(Command.SHAKE, 'POST', '/session/$sessionId/appium/device/shake') - self.command_executor.add_command(Command.TOUCH_ID, 'POST', '/session/$sessionId/appium/simulator/touch_id') - self.command_executor.add_command( - Command.TOGGLE_TOUCH_ID_ENROLLMENT, - 'POST', - '/session/$sessionId/appium/simulator/toggle_touch_id_enrollment', - ) - self.command_executor.add_command( - Command.FINGER_PRINT, - 'POST', - '/session/$sessionId/appium/device/finger_print', - ) diff --git a/appium/webdriver/extensions/images_comparison.py b/appium/webdriver/extensions/images_comparison.py index cae80168f..98ae3ecf5 100644 --- a/appium/webdriver/extensions/images_comparison.py +++ b/appium/webdriver/extensions/images_comparison.py @@ -12,17 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Dict, Union +from typing import Any from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from ..mobilecommand import MobileCommand as Command -Base64Payload = Union[str, bytes] +Base64Payload = str | bytes class ImagesComparison(CanExecuteCommands): - def match_images_features(self, base64_image1: Base64Payload, base64_image2: Base64Payload, **opts: Any) -> Dict[str, Any]: + def match_images_features(self, base64_image1: Base64Payload, base64_image2: Base64Payload, **opts: Any) -> dict[str, Any]: """Performs images matching by features. Read @@ -78,7 +78,7 @@ def match_images_features(self, base64_image1: Base64Payload, base64_image2: Bas def find_image_occurrence( self, base64_full_image: Base64Payload, base64_partial_image: Base64Payload, **opts: Any - ) -> Dict[str, Union[bytes, Dict]]: + ) -> dict[str, bytes | dict]: """Performs images matching by template to find possible occurrence of the partial image in the full image. @@ -112,7 +112,7 @@ def find_image_occurrence( def get_images_similarity( self, base64_image1: Base64Payload, base64_image2: Base64Payload, **opts: Any - ) -> Dict[str, Union[bytes, Dict]]: + ) -> dict[str, bytes | dict]: """Performs images matching to calculate the similarity score between them. The flow there is similar to the one used in @@ -147,4 +147,7 @@ def _add_commands(self) -> None: def _adjust_image_payload(payload: Base64Payload) -> str: - return payload if isinstance(payload, str) else payload.decode('utf-8') + try: + return payload if isinstance(payload, str) else payload.decode('utf-8') + except UnicodeDecodeError as e: + raise ValueError('The image payload cannot be serialized to a string. Make sure to base64-encode it first') from e diff --git a/appium/webdriver/extensions/keyboard.py b/appium/webdriver/extensions/keyboard.py index 4640b1163..725efafd0 100644 --- a/appium/webdriver/extensions/keyboard.py +++ b/appium/webdriver/extensions/keyboard.py @@ -12,69 +12,53 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, Optional -from selenium.common.exceptions import UnknownMethodException from typing_extensions import Self from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from ..mobilecommand import MobileCommand as Command - -class Keyboard(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): - def hide_keyboard(self, key_name: Optional[str] = None, key: Optional[str] = None, strategy: Optional[str] = None) -> Self: +class Keyboard(CanExecuteCommands, CanExecuteScripts): + def hide_keyboard(self, key_name: str | None = None, key: str | None = None, strategy: str | None = None) -> Self: """Hides the software keyboard on the device. - In iOS, use `key_name` to press - a particular key, or `strategy`. In Android, no parameters are used. + On iOS, use `key_name` or `key` to provide a keyboard key name. + On Android, no parameters are used. `strategy` is retained for compatibility and ignored. + + Requires the Appium driver to support the `mobile: hideKeyboard` execute method. Args: - key_name: key to press - key: - strategy: strategy for closing the keyboard (e.g., `tapOutside`) + key_name: Keyboard key name to use on iOS + key: Alias for `key_name` + strategy: Legacy argument retained for compatibility; ignored by `mobile: hideKeyboard` Returns: Union['WebDriver', 'Keyboard']: Self instance """ ext_name = 'mobile: hideKeyboard' - try: - self.assert_extension_exists(ext_name).execute_script( - ext_name, {**({'keys': [key or key_name]} if key or key_name else {})} - ) - except UnknownMethodException: - # TODO: Remove the fallback - data: Dict[str, Optional[str]] = {} - if key_name is not None: - data['keyName'] = key_name - elif key is not None: - data['key'] = key - elif strategy is None: - strategy = 'tapOutside' - data['strategy'] = strategy - self.mark_extension_absence(ext_name).execute(Command.HIDE_KEYBOARD, data) + self.execute_script(ext_name, {**({'keys': [key or key_name]} if key or key_name else {})}) return self def is_keyboard_shown(self) -> bool: """Attempts to detect whether a software keyboard is present + Requires the Appium driver to support the `mobile: isKeyboardShown` execute method. + Returns: `True` if keyboard is shown """ ext_name = 'mobile: isKeyboardShown' - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name) - except UnknownMethodException: - return self.mark_extension_absence(ext_name).execute(Command.IS_KEYBOARD_SHOWN)['value'] + return self.execute_script(ext_name) - def keyevent(self, keycode: int, metastate: Optional[int] = None) -> Self: + def keyevent(self, keycode: int, metastate: int | None = None) -> Self: """Sends a keycode to the device. Android only. Possible keycodes can be found in http://developer.android.com/reference/android/view/KeyEvent.html. + Requires the Appium driver to support the `mobile: pressKey` execute method. + Args: keycode: the keycode to be sent to the device metastate: meta information about the keycode being sent @@ -84,12 +68,14 @@ def keyevent(self, keycode: int, metastate: Optional[int] = None) -> Self: """ return self.press_keycode(keycode=keycode, metastate=metastate) - def press_keycode(self, keycode: int, metastate: Optional[int] = None, flags: Optional[int] = None) -> Self: + def press_keycode(self, keycode: int, metastate: int | None = None, flags: int | None = None) -> Self: """Sends a keycode to the device. Android only. Possible keycodes can be found in http://developer.android.com/reference/android/view/KeyEvent.html. + Requires the Appium driver to support the `mobile: pressKey` execute method. + Args: keycode: the keycode to be sent to the device metastate: meta information about the keycode being sent @@ -104,19 +90,17 @@ def press_keycode(self, keycode: int, metastate: Optional[int] = None, flags: Op args['metastate'] = metastate if flags is not None: args['flags'] = flags - try: - self.assert_extension_exists(ext_name).execute_script(ext_name, args) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.PRESS_KEYCODE, args) + self.execute_script(ext_name, args) return self - def long_press_keycode(self, keycode: int, metastate: Optional[int] = None, flags: Optional[int] = None) -> Self: + def long_press_keycode(self, keycode: int, metastate: int | None = None, flags: int | None = None) -> Self: """Sends a long press of keycode to the device. Android only. Possible keycodes can be found in http://developer.android.com/reference/android/view/KeyEvent.html. + Requires the Appium driver to support the `mobile: pressKey` execute method. + Args: keycode: the keycode to be sent to the device metastate: meta information about the keycode being sent @@ -131,38 +115,11 @@ def long_press_keycode(self, keycode: int, metastate: Optional[int] = None, flag args['metastate'] = metastate if flags is not None: args['flags'] = flags - try: - self.assert_extension_exists(ext_name).execute_script( - ext_name, - { - **args, - 'isLongPress': True, - }, - ) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute(Command.LONG_PRESS_KEYCODE, args) - return self - - def _add_commands(self) -> None: - self.command_executor.add_command( - Command.HIDE_KEYBOARD, - 'POST', - '/session/$sessionId/appium/device/hide_keyboard', - ) - self.command_executor.add_command( - Command.IS_KEYBOARD_SHOWN, - 'GET', - '/session/$sessionId/appium/device/is_keyboard_shown', - ) - self.command_executor.add_command(Command.KEY_EVENT, 'POST', '/session/$sessionId/appium/device/keyevent') - self.command_executor.add_command( - Command.PRESS_KEYCODE, - 'POST', - '/session/$sessionId/appium/device/press_keycode', - ) - self.command_executor.add_command( - Command.LONG_PRESS_KEYCODE, - 'POST', - '/session/$sessionId/appium/device/long_press_keycode', + self.execute_script( + ext_name, + { + **args, + 'isLongPress': True, + }, ) + return self diff --git a/appium/webdriver/extensions/location.py b/appium/webdriver/extensions/location.py index 3141050ae..9dfd759a5 100644 --- a/appium/webdriver/extensions/location.py +++ b/appium/webdriver/extensions/location.py @@ -12,9 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, Union -from selenium.common.exceptions import UnknownMethodException from typing_extensions import Self from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands @@ -33,20 +31,16 @@ def toggle_location_services(self) -> Self: Returns: Union['WebDriver', 'Location']: Self instance """ - try: - self.execute_script('mobile: toggleGps') - except UnknownMethodException: - # TODO: Remove the fallback - self.execute(Command.TOGGLE_LOCATION_SERVICES) + self.execute_script('mobile: toggleGps') return self def set_location( self, - latitude: Union[float, str], - longitude: Union[float, str], - altitude: Union[float, str, None] = None, - speed: Union[float, str, None] = None, - satellites: Union[float, str, None] = None, + latitude: float | str, + longitude: float | str, + altitude: float | str | None = None, + speed: float | str | None = None, + satellites: float | str | None = None, ) -> Self: """Set the location of the device @@ -76,7 +70,7 @@ def set_location( return self @property - def location(self) -> Dict[str, float]: + def location(self) -> dict[str, float]: """Retrieves the current location Returns: @@ -89,10 +83,5 @@ def location(self) -> Dict[str, float]: def _add_commands(self) -> None: """Add location endpoints. They are not int w3c spec.""" - self.command_executor.add_command( - Command.TOGGLE_LOCATION_SERVICES, - 'POST', - '/session/$sessionId/appium/device/toggle_location_services', - ) self.command_executor.add_command(Command.GET_LOCATION, 'GET', '/session/$sessionId/location') self.command_executor.add_command(Command.SET_LOCATION, 'POST', '/session/$sessionId/location') diff --git a/appium/webdriver/extensions/log_event.py b/appium/webdriver/extensions/log_event.py index 4ca53b3fe..549dd0555 100644 --- a/appium/webdriver/extensions/log_event.py +++ b/appium/webdriver/extensions/log_event.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, List, Union from typing_extensions import Self @@ -22,7 +21,7 @@ class LogEvent(CanExecuteCommands): - def get_events(self, type: Union[List[str], None] = None) -> Dict[str, Union[str, int]]: + def get_events(self, type: list[str] | None = None) -> dict[str, str | int]: """Retrieves events information from the current session (Since Appium 1.16.0) diff --git a/appium/webdriver/extensions/logs.py b/appium/webdriver/extensions/logs.py index 53e165944..1913b79c5 100644 --- a/appium/webdriver/extensions/logs.py +++ b/appium/webdriver/extensions/logs.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Dict, List +from typing import Any from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands @@ -21,7 +21,7 @@ class Logs(CanExecuteCommands): @property - def log_types(self) -> List[str]: + def log_types(self) -> list[str]: """Gets a list of the available log types. This only works with w3c compliant browsers. @@ -32,7 +32,7 @@ def log_types(self) -> List[str]: """ return self.execute(Command.GET_AVAILABLE_LOG_TYPES)['value'] - def get_log(self, log_type: str) -> List[Dict[str, Any]]: + def get_log(self, log_type: str) -> list[dict[str, Any]]: """Gets the log for a given log type. Args: diff --git a/appium/webdriver/extensions/remote_fs.py b/appium/webdriver/extensions/remote_fs.py index 5ccebd37d..83d5716e3 100644 --- a/appium/webdriver/extensions/remote_fs.py +++ b/appium/webdriver/extensions/remote_fs.py @@ -13,22 +13,20 @@ # limitations under the License. import base64 -from typing import Optional -from selenium.common.exceptions import InvalidArgumentException, UnknownMethodException +from selenium.common.exceptions import InvalidArgumentException from typing_extensions import Self from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands from appium.protocols.webdriver.can_execute_scripts import CanExecuteScripts -from appium.protocols.webdriver.can_remember_extension_presence import CanRememberExtensionPresence -from ..mobilecommand import MobileCommand as Command - -class RemoteFS(CanExecuteCommands, CanExecuteScripts, CanRememberExtensionPresence): +class RemoteFS(CanExecuteCommands, CanExecuteScripts): def pull_file(self, path: str) -> str: """Retrieves the file at `path`. + Requires the Appium driver to support the `mobile: pullFile` execute method. + Args: path: the path to the file on the device @@ -36,15 +34,13 @@ def pull_file(self, path: str) -> str: The file's contents encoded as Base64. """ ext_name = 'mobile: pullFile' - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name, {'remotePath': path}) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.PULL_FILE, {'path': path})['value'] + return self.execute_script(ext_name, {'remotePath': path}) def pull_folder(self, path: str) -> str: """Retrieves a folder at `path`. + Requires the Appium driver to support the `mobile: pullFolder` execute method. + Args: path: the path to the folder on the device @@ -52,21 +48,19 @@ def pull_folder(self, path: str) -> str: The folder's contents zipped and encoded as Base64. """ ext_name = 'mobile: pullFolder' - try: - return self.assert_extension_exists(ext_name).execute_script(ext_name, {'remotePath': path}) - except UnknownMethodException: - # TODO: Remove the fallback - return self.mark_extension_absence(ext_name).execute(Command.PULL_FOLDER, {'path': path})['value'] + return self.execute_script(ext_name, {'remotePath': path}) - def push_file(self, destination_path: str, base64data: Optional[str] = None, source_path: Optional[str] = None) -> Self: - """Puts the data from the file at `source_path`, encoded as Base64, in the file specified as `path`. + def push_file(self, destination_path: str, base64data: str | None = None, source_path: str | None = None) -> Self: + """Puts the data from the file at `source_path`, encoded as Base64, at `destination_path`. - Specify either `base64data` or `source_path`, if both specified default to `source_path` + Specify either `base64data` or `source_path`. If both are provided, `source_path` takes precedence. + + Requires the Appium driver to support the `mobile: pushFile` execute method. Args: destination_path: the location on the device/simulator where the local file contents should be saved base64data: file contents, encoded as Base64, to be written - to the file on the device/simulator + to the file on the device/simulator source_path: local file path for the file to be loaded on device Returns: @@ -79,32 +73,17 @@ def push_file(self, destination_path: str, base64data: Optional[str] = None, sou try: with open(source_path, 'rb') as f: file_data = f.read() - except IOError as e: + except OSError as e: message = f'source_path "{source_path}" could not be found. Are you sure the file exists?' raise InvalidArgumentException(message) from e base64data = base64.b64encode(file_data).decode('utf-8') ext_name = 'mobile: pushFile' - try: - self.assert_extension_exists(ext_name).execute_script( - ext_name, - { - 'remotePath': destination_path, - 'payload': base64data, - }, - ) - except UnknownMethodException: - # TODO: Remove the fallback - self.mark_extension_absence(ext_name).execute( - Command.PUSH_FILE, - { - 'path': destination_path, - 'data': base64data, - }, - ) + self.execute_script( + ext_name, + { + 'remotePath': destination_path, + 'payload': base64data, + }, + ) return self - - def _add_commands(self) -> None: - self.command_executor.add_command(Command.PULL_FILE, 'POST', '/session/$sessionId/appium/device/pull_file') - self.command_executor.add_command(Command.PULL_FOLDER, 'POST', '/session/$sessionId/appium/device/pull_folder') - self.command_executor.add_command(Command.PUSH_FILE, 'POST', '/session/$sessionId/appium/device/push_file') diff --git a/appium/webdriver/extensions/screen_record.py b/appium/webdriver/extensions/screen_record.py index 11e26c414..9ca1c9868 100644 --- a/appium/webdriver/extensions/screen_record.py +++ b/appium/webdriver/extensions/screen_record.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Union +from typing import Any from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands @@ -20,7 +20,7 @@ class ScreenRecord(CanExecuteCommands): - def start_recording_screen(self, **options: Any) -> Union[bytes, str]: + def start_recording_screen(self, **options: Any) -> bytes | str: """Start asynchronous screen recording process. +--------------+-----+---------+-----+-------+ @@ -126,8 +126,8 @@ def start_recording_screen(self, **options: Any) -> Union[bytes, str]: The default value is the device's native display resolution (if supported), 1280x720 if not. For best results, use a size supported by your device's Advanced Video Coding (AVC) encoder. - bitRate (int): [Android] The video bit rate for the video, in megabits per second. - The default value is 4. You can increase the bit rate to improve video quality, + bitRate (int): [Android] The video bit rate for the video, in bits per second. + The default value is 4000000 (4 Mbit/s). You can increase the bit rate to improve video quality, but doing so results in larger movie files. bugReport (str): [Android] Makes the recorder to display an additional information on the video overlay, such as a timestamp, that is helpful in videos captured to illustrate bugs. diff --git a/appium/webdriver/extensions/session.py b/appium/webdriver/extensions/session.py index e0bcd8b60..3fb15699b 100644 --- a/appium/webdriver/extensions/session.py +++ b/appium/webdriver/extensions/session.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict from appium.common.logger import logger from appium.protocols.webdriver.can_execute_commands import CanExecuteCommands @@ -22,7 +21,7 @@ class Session(CanExecuteCommands): @property - def events(self) -> Dict: + def events(self) -> dict: """Retrieves events information from the current session Usage: diff --git a/appium/webdriver/extensions/settings.py b/appium/webdriver/extensions/settings.py index d9a55111e..541da5dcc 100644 --- a/appium/webdriver/extensions/settings.py +++ b/appium/webdriver/extensions/settings.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Dict +from typing import Any from typing_extensions import Self @@ -22,7 +22,7 @@ class Settings(CanExecuteCommands): - def get_settings(self) -> Dict[str, Any]: + def get_settings(self) -> dict[str, Any]: """Returns the appium server Settings for the current session. Do not get Settings confused with Desired Capabilities, they are @@ -33,7 +33,7 @@ def get_settings(self) -> Dict[str, Any]: """ return self.execute(Command.GET_SETTINGS, {})['value'] - def update_settings(self, settings: Dict[str, Any]) -> Self: + def update_settings(self, settings: dict[str, Any]) -> Self: """Set settings for the current session. For more on settings, see: https://github.com/appium/appium/blob/master/docs/en/advanced-concepts/settings.md diff --git a/appium/webdriver/locator_converter.py b/appium/webdriver/locator_converter.py index 4c6416c67..004b5b0b5 100644 --- a/appium/webdriver/locator_converter.py +++ b/appium/webdriver/locator_converter.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Tuple from selenium.webdriver.remote.locator_converter import LocatorConverter @@ -25,5 +24,5 @@ class AppiumLocatorConverter(LocatorConverter): to the Appium server as-is. """ - def convert(self, by: str, value: str) -> Tuple[str, str]: + def convert(self, by: str, value: str) -> tuple[str, str]: return (by, value) diff --git a/appium/webdriver/mobilecommand.py b/appium/webdriver/mobilecommand.py index 79ac25e1b..ed8dc6f80 100644 --- a/appium/webdriver/mobilecommand.py +++ b/appium/webdriver/mobilecommand.py @@ -31,7 +31,6 @@ class MobileCommand: SWITCH_TO_CONTEXT = 'switchToContext' BACKGROUND = 'background' - GET_APP_STRINGS = 'getAppStrings' IS_LOCKED = 'isLocked' LOCK = 'lock' @@ -78,13 +77,10 @@ class MobileCommand: GET_AVAILABLE_LOG_TYPES = 'getAvailableLogTypes' # Android - OPEN_NOTIFICATIONS = 'openNotifications' GET_CURRENT_ACTIVITY = 'getCurrentActivity' - GET_CURRENT_PACKAGE = 'getCurrentPackage' GET_SYSTEM_BARS = 'getSystemBars' GET_DISPLAY_DENSITY = 'getDisplayDensity' TOGGLE_WIFI = 'toggleWiFi' - TOGGLE_LOCATION_SERVICES = 'toggleLocationServices' GET_PERFORMANCE_DATA_TYPES = 'getPerformanceDataTypes' GET_PERFORMANCE_DATA = 'getPerformanceData' GET_NETWORK_CONNECTION = 'getNetworkConnection' diff --git a/appium/webdriver/switch_to.py b/appium/webdriver/switch_to.py index ed9db7c76..f61425247 100644 --- a/appium/webdriver/switch_to.py +++ b/appium/webdriver/switch_to.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional from selenium.webdriver.remote.switch_to import SwitchTo from typing_extensions import Self @@ -21,7 +20,7 @@ class MobileSwitchTo(SwitchTo): - def context(self, context_name: Optional[str]) -> Self: + def context(self, context_name: str | None) -> Self: """Sets the context for the current session. Passing `None` is equal to switching to native context. diff --git a/appium/webdriver/webdriver.py b/appium/webdriver/webdriver.py index 06c61f44d..4584824bc 100644 --- a/appium/webdriver/webdriver.py +++ b/appium/webdriver/webdriver.py @@ -12,18 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union +from collections.abc import Callable +from typing import TYPE_CHECKING, Any -from selenium import webdriver from selenium.common.exceptions import ( InvalidArgumentException, SessionNotCreatedException, - UnknownMethodException, WebDriverException, ) from selenium.webdriver.remote.command import Command as RemoteCommand from selenium.webdriver.remote.remote_connection import RemoteConnection -from typing_extensions import Self + +# `selenium.webdriver.Remote` could be used instead, but Pyright wouldn't locate the class properly. +from selenium.webdriver.remote.webdriver import WebDriver as Remote from appium.common.logger import logger from appium.options.common.base import AppiumOptions @@ -160,10 +161,10 @@ def add_command(self): """ - def __init__(self, execute: Callable[[str, Dict], Dict[str, Any]]): + def __init__(self, execute: Callable[[str, dict], dict[str, Any]]): self._execute = execute - def execute(self, parameters: Union[Dict[str, Any], None] = None) -> Any: + def execute(self, parameters: dict[str, Any] | None = None) -> Any: param = {} if parameters: param = parameters @@ -179,7 +180,7 @@ def method_name(self) -> str: """ raise NotImplementedError() - def add_command(self) -> Tuple[str, str]: + def add_command(self) -> tuple[str, str]: """ Expected to define the pair of HTTP method and its URL. """ @@ -187,8 +188,8 @@ def add_command(self) -> Tuple[str, str]: def _get_remote_connection_and_client_config( - command_executor: Union[str, AppiumConnection], client_config: Optional[AppiumClientConfig] = None -) -> tuple[AppiumConnection, Optional[AppiumClientConfig]]: + command_executor: str | AppiumConnection, client_config: AppiumClientConfig | None = None +) -> tuple[AppiumConnection, AppiumClientConfig | None]: """Return the pair of command executor and client config. If the given command executor is a custom one, returned client config will be None since the custom command executor has its own client config already. @@ -208,7 +209,7 @@ def _get_remote_connection_and_client_config( class WebDriver( - webdriver.Remote, + Remote, ActionHelpers, Activities, Applications, @@ -238,10 +239,10 @@ class WebDriver( ): def __init__( self, - command_executor: Union[str, AppiumConnection] = 'http://127.0.0.1:4723', - extensions: Optional[List[Type['ExtensionBase']]] = None, - options: Union[AppiumOptions, List[AppiumOptions], None] = None, - client_config: Optional[AppiumClientConfig] = None, + command_executor: str | AppiumConnection = 'http://127.0.0.1:4723', + extensions: list[type['ExtensionBase']] | None = None, + options: AppiumOptions | list[AppiumOptions] | None = None, + client_config: AppiumClientConfig | None = None, ): command_executor, client_config = _get_remote_connection_and_client_config( command_executor=command_executor, client_config=client_config @@ -264,7 +265,7 @@ def __init__( if client_config and client_config.direct_connection: self._update_command_executor(keep_alive=client_config.keep_alive) - self._absent_extensions: Set[str] = set() + self._absent_extensions: set[str] = set() self._extensions = extensions or [] for extension in self._extensions: @@ -280,10 +281,10 @@ def __init__( if TYPE_CHECKING: - def find_element(self, by: str, value: Union[str, Dict, None] = None) -> 'MobileWebElement': # type: ignore[override] + def find_element(self, by: str, value: str | dict | None = None) -> 'MobileWebElement': # type: ignore[override] ... - def find_elements(self, by: str, value: Union[str, Dict, None] = None) -> List['MobileWebElement']: # type: ignore[override] + def find_elements(self, by: str, value: str | dict | None = None) -> list['MobileWebElement']: # type: ignore[override] ... def delete_extensions(self) -> None: @@ -301,7 +302,8 @@ def _update_command_executor(self, keep_alive: bool) -> None: direct_port = 'directConnectPort' direct_path = 'directConnectPath' - assert self.caps, 'Driver capabilities must be defined' + if not self.caps: + raise ValueError('Driver capabilities must be defined') if not {direct_protocol, direct_host, direct_port, direct_path}.issubset(set(self.caps)): message = 'Direct connect capabilities from server were:\n' for key in [direct_protocol, direct_host, direct_port, direct_path]: @@ -325,7 +327,7 @@ def _update_command_executor(self, keep_alive: bool) -> None: # https://github.com/SeleniumHQ/selenium/blob/06fdf2966df6bca47c0ae45e8201cd30db9b9a49/py/selenium/webdriver/remote/webdriver.py#L277 # noinspection PyAttributeOutsideInit - def start_session(self, capabilities: Union[Dict, AppiumOptions], browser_profile: Optional[str] = None) -> None: + def start_session(self, capabilities: dict | AppiumOptions, browser_profile: str | None = None) -> None: """Creates a new session with the desired capabilities. Override for Appium @@ -348,8 +350,8 @@ def start_session(self, capabilities: Union[Dict, AppiumOptions], browser_profil # Due to a W3C spec parsing misconception some servers # pack the createSession response stuff into 'value' dictionary and # some other put it to the top level of the response JSON nesting hierarchy - get_response_value: Callable[[str], Optional[Any]] = lambda key: response.get(key) or ( - response['value'].get(key) if isinstance(response.get('value'), dict) else None + get_response_value: Callable[[str], Any | None] = lambda key: ( + response.get(key) or (response['value'].get(key) if isinstance(response.get('value'), dict) else None) ) session_id = get_response_value('sessionId') if not session_id: @@ -359,7 +361,7 @@ def start_session(self, capabilities: Union[Dict, AppiumOptions], browser_profil self.session_id = session_id self.caps = get_response_value('capabilities') or {} - def get_status(self) -> Dict: + def get_status(self) -> dict: """ Get the Appium server status @@ -372,7 +374,7 @@ def get_status(self) -> Dict: """ return self.execute(Command.GET_STATUS)['value'] - def create_web_element(self, element_id: Union[int, str]) -> MobileWebElement: + def create_web_element(self, element_id: int | str) -> MobileWebElement: """Creates a web element with the specified element_id. Overrides method in Selenium WebDriver in order to always give them @@ -400,7 +402,7 @@ def switch_to(self) -> MobileSwitchTo: return MobileSwitchTo(self) # MJSONWP for Selenium v4 - @property + @property # type: ignore[override] def orientation(self) -> str: """ Gets the current orientation of the device @@ -433,40 +435,6 @@ def orientation(self, value: str) -> None: else: raise WebDriverException("You can only set the orientation to 'LANDSCAPE' and 'PORTRAIT'") - def assert_extension_exists(self, ext_name: str) -> Self: - """ - Verifies if the given extension is not present in the list of absent extensions - for the given driver instance. - This API is designed for private usage. - - Args: - ext_name: extension name - - Returns: - self instance for chaining - - Raises: - UnknownMethodException: If the extension has been marked as absent once - """ - if ext_name in self._absent_extensions: - raise UnknownMethodException() - return self - - def mark_extension_absence(self, ext_name: str) -> Self: - """ - Marks the given extension as absent for the given driver instance. - This API is designed for private usage. - - Args: - ext_name: extension name - - Returns: - self instance for chaining - """ - logger.debug(f'Marking driver extension "{ext_name}" as absent for the current instance') - self._absent_extensions.add(ext_name) - return self - def _add_commands(self) -> None: # call the overridden command binders from all mixin classes except for # appium.webdriver.webdriver.WebDriver and its sub-classes diff --git a/appium/webdriver/webelement.py b/appium/webdriver/webelement.py index 61076ca37..8494af13f 100644 --- a/appium/webdriver/webelement.py +++ b/appium/webdriver/webelement.py @@ -12,7 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Union +from collections.abc import Callable +from typing import TYPE_CHECKING from selenium.webdriver.common.utils import keys_to_typing from selenium.webdriver.remote.command import Command as RemoteCommand @@ -28,13 +29,13 @@ class WebElement(SeleniumWebElement): if TYPE_CHECKING: - def find_element(self, by: str, value: Union[str, Dict, None] = None) -> Self: # type: ignore[override] + def find_element(self, by: str, value: str | dict | None = None) -> Self: # type: ignore[override] ... - def find_elements(self, by: str, value: Union[str, Dict, None] = None) -> List[Self]: # type: ignore[override] + def find_elements(self, by: str, value: str | dict | None = None) -> list[Self]: # type: ignore[override] ... - def get_attribute(self, name: str) -> Optional[Union[str, Dict]]: # type: ignore[override] + def get_attribute(self, name: str) -> str | dict | None: # type: ignore[override] """Gets the given attribute or property of the element. Override for Appium @@ -102,7 +103,7 @@ def clear(self) -> Self: # type: ignore[override] return self @property - def location_in_view(self) -> Dict[str, int]: + def location_in_view(self) -> dict[str, int]: """Gets the location of an element relative to the view. Usage: diff --git a/pyproject.toml b/pyproject.toml index 11c61525a..fd689685e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,13 @@ [project] name = "Appium-Python-Client" description = "Python client for Appium" -version = "5.2.3" +version = "6.0.0" readme = "README.md" license = "Apache-2.0" license-files = ["LICENSE"] authors = [ - {name = "Isaac Murchie", email = "isaac@saucelabs.com"}, + {name = "Kazuaki Matsuo", email = "kazucocoa1117@gmail.com"}, + {name = "Isaac Murchie"}, ] maintainers = [ {name = "Kazuaki Matsuo"}, @@ -16,41 +17,41 @@ maintainers = [ keywords = ["appium", "selenium", "python client", "mobile automation"] classifiers = [ "Development Status :: 5 - Production/Stable", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Environment :: Console", "Topic :: Software Development :: Testing", ] -requires-python = ">=3.9" +requires-python = ">=3.10" dependencies = [ - "selenium>=4.26,<5.0", - "typing-extensions~=4.13", + "selenium>=4.37.0,<5.0", + "typing-extensions~=4.16", ] [project.urls] -Homepage = "http://appium.io/" +Homepage = "https://appium.io/" Repository = "https://github.com/appium/python-client" Issues = "https://github.com/appium/python-client/issues" Changelog = "https://github.com/appium/python-client/blob/master/CHANGELOG.md" -[tool.uv] -dev-dependencies = [ +[dependency-groups] +dev = [ "httpretty~=1.1", "mock~=5.2", - "mypy~=1.17", - "pre-commit~=4.2", - "pytest~=8.4", - "pytest-cov~=6.2", + "mypy>=1.17,<3.0", + "pre-commit~=4.6", + "pytest>=8.4,<10.0", + "pytest-cov>=6.2,<8.0", "pytest-xdist~=3.8", "python-dateutil~=2.9", - "ruff~=0.12", + "ruff~=0.16", "types-python-dateutil~=2.9", # for release - "python-semantic-release~=10.3.1", + "python-semantic-release>=10.3.1,<10.7.0", # for documentation "sphinx>=4.0,<9.0", @@ -62,11 +63,6 @@ dev-dependencies = [ requires = ["hatchling"] build-backend = "hatchling.build" -[tool.hatch.version] -source = "regex" -path = "appium/version.py" -pattern = "(?P\\d+\\.\\d+\\.\\d+)" - [tool.hatch.build] exclude = [ "test/", diff --git a/setup.py b/setup.py deleted file mode 100644 index f32eab925..000000000 --- a/setup.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# FIXME: Remove this setup.py completely. -# Then, we should bump the major version since the package will not include setup.py. - -try: - # Python 3.11+ - import tomllib -except Exception: - # for older versions - import tomli as tomllib - -with open('pyproject.toml', 'rb') as f: - pyproject = tomllib.load(f) - project = pyproject['project'] - -from setuptools import find_packages, setup - -setup( - name=project['name'], - version=project['version'], - description=project['description'], - keywords=project['keywords'], - author=project['authors'][0]['name'], - author_email=project['authors'][0]['email'], - maintainer=', '.join([maintainer['name'] for maintainer in project['maintainers']]), - url=project['urls']['Homepage'], - package_data={'appium': ['py.typed']}, - packages=find_packages(include=['appium*']), - license=project['license'], - classifiers=project['classifiers'], - install_requires=project['dependencies'], -) diff --git a/test/apps/ApiDemos-debug.apk.zip b/test/apps/ApiDemos-debug.apk.zip deleted file mode 100644 index fcb29ca77..000000000 Binary files a/test/apps/ApiDemos-debug.apk.zip and /dev/null differ diff --git a/test/apps/TestApp.app.zip b/test/apps/TestApp.app.zip deleted file mode 100644 index 19668e47f..000000000 Binary files a/test/apps/TestApp.app.zip and /dev/null differ diff --git a/test/apps/UICatalog.app.zip b/test/apps/UICatalog.app.zip deleted file mode 100644 index 479d92e50..000000000 Binary files a/test/apps/UICatalog.app.zip and /dev/null differ diff --git a/test/functional/android/appium_service_tests.py b/test/functional/android/appium_service_tests.py index 6c346f734..e35e5e381 100644 --- a/test/functional/android/appium_service_tests.py +++ b/test/functional/android/appium_service_tests.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Generator +from collections.abc import Generator import pytest @@ -22,6 +21,7 @@ @pytest.fixture def appium_service() -> Generator[AppiumService, None, None]: + """Create and configure Appium service for testing.""" service = AppiumService() service.start( args=[ @@ -33,12 +33,13 @@ def appium_service() -> Generator[AppiumService, None, None]: '/wd/hub', ] ) - try: - yield service - finally: - service.stop() + + yield service + + service.stop() def test_appium_service(appium_service: AppiumService) -> None: + """Test that Appium service is running and listening.""" assert appium_service.is_running assert appium_service.is_listening diff --git a/test/functional/android/bidi_tests.py b/test/functional/android/bidi_tests.py index f37a2d94e..1e8b463f4 100644 --- a/test/functional/android/bidi_tests.py +++ b/test/functional/android/bidi_tests.py @@ -12,17 +12,26 @@ # See the License for the specific language governing permissions and # limitations under the License. +from collections.abc import Generator +from typing import TYPE_CHECKING + +import pytest from selenium.webdriver.common.bidi.common import command_builder from appium import webdriver -from appium.options.common import AppiumOptions from appium.webdriver.client_config import AppiumClientConfig +from test.functional.test_helper import is_ci from test.helpers.constants import SERVER_URL_BASE -from .helper.desired_capabilities import get_desired_capabilities +from .options import make_options + +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver class AppiumLogEntry: + """Represents a log entry from Appium BiDi.""" + event_class = 'log.entryAdded' def __init__(self, level, text, timestamp, source, type): @@ -47,35 +56,36 @@ def from_json(cls, json: dict): ) -class TestChromeWithBiDi: - """This test requires selenium python client which supports 'command_builder'""" +@pytest.fixture +def driver() -> Generator['WebDriver', None, None]: + """Create and configure Chrome driver with BiDi support for testing.""" + client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) + client_config.timeout = 600 + options = make_options() + options.web_socket_url = True + driver = webdriver.Remote(SERVER_URL_BASE, options=options, client_config=client_config) - def setup_method(self) -> None: - client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) - client_config.timeout = 600 - caps = get_desired_capabilities() - caps['webSocketUrl'] = True - self.driver = webdriver.Remote( - SERVER_URL_BASE, options=AppiumOptions().load_capabilities(caps), client_config=client_config - ) + yield driver + + driver.quit() - def teardown_method(self) -> None: - self.driver.quit() - def test_bidi_log(self) -> None: - log_entries = [] - bidi_log_param = {'events': ['log.entryAdded'], 'contexts': ['NATIVE_APP']} +@pytest.mark.skipif(is_ci(), reason='Flaky on CI') +def test_bidi_log(driver: 'WebDriver') -> None: + """Test BiDi logging functionality with Chrome driver.""" + log_entries = [] + bidi_log_param = {'events': ['log.entryAdded'], 'contexts': ['NATIVE_APP']} - self.driver.script.conn.execute(command_builder('session.subscribe', bidi_log_param)) + driver.script.conn.execute(command_builder('session.subscribe', bidi_log_param)) - def _log(entry: AppiumLogEntry): - # e.g. {'type': 'syslog', 'level': 'info', 'source': {'realm': ''}, 'text': '08-05 13:30:32.617 29677 29709 I appium : channel read: GET /session/d7c38859-8930-4eb0-960a-8f917c9e6a38/source', 'timestamp': 1754368241565} - log_entries.append(entry.json) + def _log(entry: AppiumLogEntry): + # e.g. {'type': 'syslog', 'level': 'info', 'source': {'realm': ''}, 'text': '08-05 13:30:32.617 29677 29709 I appium : channel read: GET /session/d7c38859-8930-4eb0-960a-8f917c9e6a38/source', 'timestamp': 1754368241565} + log_entries.append(entry.json) - try: - callback_id = self.driver.script.conn.add_callback(AppiumLogEntry, _log) - self.driver.page_source - assert len(log_entries) != 0 - self.driver.script.conn.remove_callback(AppiumLogEntry, callback_id) - finally: - self.driver.script.conn.execute(command_builder('session.unsubscribe', bidi_log_param)) + try: + callback_id = driver.script.conn.add_callback(AppiumLogEntry, _log) + driver.page_source + assert len(log_entries) != 0 + driver.script.conn.remove_callback(AppiumLogEntry, callback_id) + finally: + driver.script.conn.execute(command_builder('session.unsubscribe', bidi_log_param)) diff --git a/test/functional/android/chrome_tests.py b/test/functional/android/chrome_tests.py index 000bc5dc3..8db22e197 100644 --- a/test/functional/android/chrome_tests.py +++ b/test/functional/android/chrome_tests.py @@ -12,31 +12,40 @@ # See the License for the specific language governing permissions and # limitations under the License. +from collections.abc import Generator +from typing import TYPE_CHECKING + +import pytest + from appium import webdriver -from appium.options.common import AppiumOptions from appium.webdriver.client_config import AppiumClientConfig from appium.webdriver.common.appiumby import AppiumBy from test.helpers.constants import SERVER_URL_BASE -from .helper.desired_capabilities import get_desired_capabilities +from .options import make_options + +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver + + +@pytest.fixture +def driver() -> Generator['WebDriver', None, None]: + """Create and configure Chrome driver for testing.""" + client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) + client_config.timeout = 600 + options = make_options() + options.browser_name = 'Chrome' + driver = webdriver.Remote(SERVER_URL_BASE, options=options, client_config=client_config) + yield driver -class TestChrome(object): - def setup_method(self) -> None: - client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) - client_config.timeout = 600 - caps = get_desired_capabilities() - caps['browserName'] = 'Chrome' - self.driver = webdriver.Remote( - SERVER_URL_BASE, options=AppiumOptions().load_capabilities(caps), client_config=client_config - ) + driver.quit() - def teardown_method(self) -> None: - self.driver.quit() - def test_find_single_element(self) -> None: - e = self.driver.find_element(by=AppiumBy.XPATH, value='//body') - assert e.text == '' +def test_find_single_element(driver: 'WebDriver') -> None: + """Test finding a single element in Chrome browser.""" + e = driver.find_element(by=AppiumBy.XPATH, value='//body') + assert e.text == '' - # Chrome browser's default page - assert '' in self.driver.page_source + # Chrome browser's default page + assert '' in driver.page_source diff --git a/test/functional/android/helper/__init__.py b/test/functional/android/helper/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/functional/android/helper/desired_capabilities.py b/test/functional/android/helper/desired_capabilities.py deleted file mode 100644 index ef400ffff..000000000 --- a/test/functional/android/helper/desired_capabilities.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -from typing import Any, Dict, Optional - -# Returns abs path relative to this file and not cwd - - -def PATH(p: str) -> str: - return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', p)) - - -def get_desired_capabilities(app: Optional[str] = None) -> Dict[str, Any]: - desired_caps: Dict[str, Any] = { - 'platformName': 'Android', - 'deviceName': 'Android Emulator', - 'newCommandTimeout': 240, - 'automationName': 'UIAutomator2', - 'uiautomator2ServerInstallTimeout': 120000, - 'adbExecTimeout': 120000, - } - - if app is not None: - desired_caps['app'] = PATH(os.path.join('../..', 'apps', app)) - - return desired_caps diff --git a/test/functional/android/helper/test_helper.py b/test/functional/android/helper/test_helper.py deleted file mode 100644 index 7f113f210..000000000 --- a/test/functional/android/helper/test_helper.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import base64 -import os - -from appium import webdriver -from appium.options.android import UiAutomator2Options -from appium.webdriver.client_config import AppiumClientConfig -from test.functional.test_helper import is_ci -from test.helpers.constants import SERVER_URL_BASE - -from . import desired_capabilities - -# the emulator is sometimes slow and needs time to think -SLEEPY_TIME = 10 - -# The package name of ApiDemos-debug.apk.zip -APIDEMO_PKG_NAME = 'io.appium.android.apis' - - -class BaseTestCase: - def setup_method(self, method) -> None: # type: ignore - caps = desired_capabilities.get_desired_capabilities('ApiDemos-debug.apk.zip') - client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) - client_config.timeout = 600 - self.driver = webdriver.Remote(options=UiAutomator2Options().load_capabilities(caps), client_config=client_config) - if is_ci(): - self.driver.start_recording_screen() - - def teardown_method(self, method) -> None: # type: ignore - if not hasattr(self, 'driver'): - return - - if is_ci(): - payload = self.driver.stop_recording_screen() - video_path = os.path.join(os.getcwd(), method.__name__ + '.mp4') - with open(video_path, 'wb') as fd: - fd.write(base64.b64decode(payload)) - self.driver.quit() diff --git a/test/functional/android/options.py b/test/functional/android/options.py new file mode 100644 index 000000000..c9d3afda9 --- /dev/null +++ b/test/functional/android/options.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from appium.options.android import UiAutomator2Options +from test.functional.test_helper import get_worker_info + + +def make_options(app: str | None = None) -> UiAutomator2Options: + """Get UiAutomator2 options configured for Android testing with parallel execution support.""" + options = UiAutomator2Options() + + # Set basic Android capabilities + options.device_name = android_device_name() + options.platform_name = 'Android' + options.automation_name = 'UIAutomator2' + options.new_command_timeout = 240 + options.uiautomator2_server_install_timeout = 120000 + options.adb_exec_timeout = 120000 + + if app is not None: + options.app = app + + return options + + +def android_device_name() -> str: + """ + Get a unique device name for the current worker. + Uses the base device name and appends the port number for uniqueness. + """ + prefix = os.getenv('ANDROID_MODEL') or 'Android Emulator' + worker_info = get_worker_info() + + if worker_info.is_parallel: + # For parallel execution, we can use different device names or ports + # This is a simplified approach - in practice you might want to use different emulators + return f'{prefix} - Worker {worker_info.worker_id}' + + return prefix diff --git a/test/functional/flutter_integration/commands_test.py b/test/functional/flutter_integration/commands_test.py index f256222e0..7afe4156e 100644 --- a/test/functional/flutter_integration/commands_test.py +++ b/test/functional/flutter_integration/commands_test.py @@ -13,122 +13,136 @@ # limitations under the License. import os +from typing import TYPE_CHECKING from appium.webdriver.common.appiumby import AppiumBy from appium.webdriver.extensions.flutter_integration.flutter_finder import FlutterFinder from appium.webdriver.extensions.flutter_integration.scroll_directions import ScrollDirection -from test.functional.flutter_integration.helper.test_helper import BaseTestCase +if TYPE_CHECKING: + from appium.webdriver.extensions.flutter_integration.flutter_commands import FlutterCommand + from appium.webdriver.webdriver import WebDriver -class TestFlutterCommands(BaseTestCase): - def test_wait_command(self) -> None: - self.__open_screen('Lazy Loading') - message_field_finder = FlutterFinder.by_key('message_field') - toggle_button_finder = FlutterFinder.by_key('toggle_button') +def _open_screen(driver: 'WebDriver', flutter_command: 'FlutterCommand', screen_name: str) -> None: + """Helper function to open a specific screen in the Flutter app.""" + driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Login').click() + element = flutter_command.scroll_till_visible(FlutterFinder.by_text(screen_name)) + element.click() - message_field = self.driver.find_element(*message_field_finder.as_args()) - toggle_button = self.driver.find_element(*toggle_button_finder.as_args()) - assert message_field.is_displayed() == True - assert message_field.text == 'Hello world' - toggle_button.click() - self.flutter_command.wait_for_invisible(message_field_finder) - assert len(self.driver.find_elements(*message_field_finder.as_args())) == 0 +def test_wait_command(driver: 'WebDriver', flutter_command: 'FlutterCommand') -> None: + """Test Flutter wait commands for element visibility.""" + _open_screen(driver, flutter_command, 'Lazy Loading') - toggle_button.click() - self.flutter_command.wait_for_visible(message_field) - assert len(self.driver.find_elements(*message_field_finder.as_args())) == 1 + message_field_finder = FlutterFinder.by_key('message_field') + toggle_button_finder = FlutterFinder.by_key('toggle_button') - def test_scroll_till_visible_command(self) -> None: - self.__open_screen('Vertical Swiping') + message_field = driver.find_element(*message_field_finder.as_args()) + toggle_button = driver.find_element(*toggle_button_finder.as_args()) + assert message_field.is_displayed() == True + assert message_field.text == 'Hello world' - java_text_finder = FlutterFinder.by_text('Java') - protractor_text_finder = FlutterFinder.by_text('Protractor') + toggle_button.click() + flutter_command.wait_for_invisible(message_field_finder) + assert len(driver.find_elements(*message_field_finder.as_args())) == 0 - first_element = self.flutter_command.scroll_till_visible(java_text_finder) - assert first_element.get_attribute('displayed') == 'true' + toggle_button.click() + flutter_command.wait_for_visible(message_field) + assert len(driver.find_elements(*message_field_finder.as_args())) == 1 - second_element = self.flutter_command.scroll_till_visible(protractor_text_finder) - assert second_element.get_attribute('displayed') == 'true' - assert first_element.get_attribute('displayed') == 'false' - first_element = self.flutter_command.scroll_till_visible(java_text_finder, ScrollDirection.UP) - assert second_element.get_attribute('displayed') == 'false' - assert first_element.get_attribute('displayed') == 'true' +def test_scroll_till_visible_command(driver: 'WebDriver', flutter_command: 'FlutterCommand') -> None: + """Test Flutter scroll till visible command.""" + _open_screen(driver, flutter_command, 'Vertical Swiping') - def test_scroll_till_visible_with_scroll_params_command(self) -> None: - self.__open_screen('Vertical Swiping') + java_text_finder = FlutterFinder.by_text('Java') + protractor_text_finder = FlutterFinder.by_text('Protractor') - scroll_params = { - 'scrollView': FlutterFinder.by_type('Scrollable').to_dict(), - 'delta': 30, - 'maxScrolls': 30, - 'settleBetweenScrollsTimeout': 5000, - 'dragDuration': 35, - } - first_element = self.flutter_command.scroll_till_visible( - FlutterFinder.by_text('Playwright'), scroll_direction=ScrollDirection.DOWN, **scroll_params - ) - assert first_element.get_attribute('displayed') == 'true' + first_element = flutter_command.scroll_till_visible(java_text_finder) + assert first_element.get_attribute('displayed') == 'true' - def test_double_click_command(self) -> None: - self.__open_screen('Double Tap') + second_element = flutter_command.scroll_till_visible(protractor_text_finder) + assert second_element.get_attribute('displayed') == 'true' + assert first_element.get_attribute('displayed') == 'false' - double_tap_button = self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'double_tap_button').find_element( - AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Double Tap' - ) - assert double_tap_button.text == 'Double Tap' + first_element = flutter_command.scroll_till_visible(java_text_finder, ScrollDirection.UP) + assert second_element.get_attribute('displayed') == 'false' + assert first_element.get_attribute('displayed') == 'true' - self.flutter_command.perform_double_click(double_tap_button) - assert ( - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Successful').text == 'Double Tap Successful' - ) - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Ok').click() - self.flutter_command.perform_double_click(double_tap_button, (10, 2)) - assert ( - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Successful').text == 'Double Tap Successful' - ) +def test_scroll_till_visible_with_scroll_params_command(driver: 'WebDriver', flutter_command: 'FlutterCommand') -> None: + """Test Flutter scroll till visible command with custom scroll parameters.""" + _open_screen(driver, flutter_command, 'Vertical Swiping') - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Ok').click() + scroll_params = { + 'scrollView': FlutterFinder.by_type('Scrollable').to_dict(), + 'delta': 30, + 'maxScrolls': 30, + 'settleBetweenScrollsTimeout': 5000, + 'dragDuration': 35, + } + first_element = flutter_command.scroll_till_visible( + FlutterFinder.by_text('Playwright'), scroll_direction=ScrollDirection.DOWN, **scroll_params + ) + assert first_element.get_attribute('displayed') == 'true' - def test_long_press_command(self) -> None: - self.__open_screen('Long Press') - long_press_button = self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'long_press_button') - self.flutter_command.perform_long_press(long_press_button) +def test_double_click_command(driver: 'WebDriver', flutter_command: 'FlutterCommand') -> None: + """Test Flutter double click command.""" + _open_screen(driver, flutter_command, 'Double Tap') - success_pop_up = self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'It was a long press') - assert success_pop_up.text == 'It was a long press' - assert success_pop_up.is_displayed() == True + double_tap_button = driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'double_tap_button').find_element( + AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Double Tap' + ) + assert double_tap_button.text == 'Double Tap' - def test_drag_and_drop_command(self) -> None: - self.__open_screen('Drag & Drop') + flutter_command.perform_double_click(double_tap_button) + assert driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Successful').text == 'Double Tap Successful' - drag_element = self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'drag_me') - drop_element = self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'drop_zone') - self.flutter_command.perform_drag_and_drop(drag_element, drop_element) - assert self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'The box is dropped').is_displayed() == True + driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Ok').click() + flutter_command.perform_double_click(double_tap_button, (10, 2)) + assert driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Successful').text == 'Double Tap Successful' - def test_camera_mocking(self) -> None: - self.__open_screen('Image Picker') + driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Ok').click() - success_qr_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'file', 'success_qr.png') - second_qr_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'file', 'second_qr.png') - image_id = self.flutter_command.inject_mock_image(success_qr_file_path) - self.flutter_command.inject_mock_image(second_qr_file_path) - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'capture_image').click() - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'PICK').click() - assert self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'SecondInjectedImage').is_displayed() == True - - self.flutter_command.activate_injected_image(image_id) - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'capture_image').click() - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'PICK').click() - assert self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Success!').is_displayed() == True - - def __open_screen(self, screen_name: str) -> None: - self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Login').click() - element = self.flutter_command.scroll_till_visible(FlutterFinder.by_text(screen_name)) - element.click() +def test_long_press_command(driver: 'WebDriver', flutter_command: 'FlutterCommand') -> None: + """Test Flutter long press command.""" + _open_screen(driver, flutter_command, 'Long Press') + + long_press_button = driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'long_press_button') + flutter_command.perform_long_press(long_press_button) + + success_pop_up = driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'It was a long press') + assert success_pop_up.text == 'It was a long press' + assert success_pop_up.is_displayed() == True + + +def test_drag_and_drop_command(driver: 'WebDriver', flutter_command: 'FlutterCommand') -> None: + """Test Flutter drag and drop command.""" + _open_screen(driver, flutter_command, 'Drag & Drop') + + drag_element = driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'drag_me') + drop_element = driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'drop_zone') + flutter_command.perform_drag_and_drop(drag_element, drop_element) + assert driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'The box is dropped').is_displayed() == True + + +def test_camera_mocking(driver: 'WebDriver', flutter_command: 'FlutterCommand') -> None: + """Test Flutter camera mocking functionality.""" + _open_screen(driver, flutter_command, 'Image Picker') + + success_qr_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'file', 'success_qr.png') + second_qr_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'file', 'second_qr.png') + + image_id = flutter_command.inject_mock_image(success_qr_file_path) + flutter_command.inject_mock_image(second_qr_file_path) + driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'capture_image').click() + driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'PICK').click() + assert driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'SecondInjectedImage').is_displayed() == True + + flutter_command.activate_injected_image(image_id) + driver.find_element(AppiumBy.FLUTTER_INTEGRATION_KEY, 'capture_image').click() + driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'PICK').click() + assert driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Success!').is_displayed() == True diff --git a/test/functional/flutter_integration/conftest.py b/test/functional/flutter_integration/conftest.py new file mode 100644 index 000000000..011338bb5 --- /dev/null +++ b/test/functional/flutter_integration/conftest.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from collections.abc import Generator +from typing import TYPE_CHECKING + +import pytest + +from appium import webdriver +from appium.webdriver.client_config import AppiumClientConfig +from appium.webdriver.extensions.flutter_integration.flutter_commands import FlutterCommand +from test.helpers.constants import SERVER_URL_BASE + +from .helper.options import make_options + +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver + + +@pytest.fixture +def driver() -> Generator['WebDriver', None, None]: + """Create and configure Flutter driver for testing.""" + options = make_options() + + client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) + client_config.timeout = 600 + + driver = webdriver.Remote(options=options, client_config=client_config) + + yield driver + + driver.quit() + + +@pytest.fixture +def flutter_command(driver: 'WebDriver') -> FlutterCommand: + """Create FlutterCommand instance for the driver.""" + return FlutterCommand(driver) diff --git a/test/functional/flutter_integration/finder_test.py b/test/functional/flutter_integration/finder_test.py index d9bc3f56b..5357fc6f1 100644 --- a/test/functional/flutter_integration/finder_test.py +++ b/test/functional/flutter_integration/finder_test.py @@ -12,45 +12,58 @@ # See the License for the specific language governing permissions and # limitations under the License. +from typing import TYPE_CHECKING + from appium.webdriver.common.appiumby import AppiumBy from appium.webdriver.extensions.flutter_integration.flutter_finder import FlutterFinder -from test.functional.flutter_integration.helper.test_helper import BaseTestCase + +if TYPE_CHECKING: + from appium.webdriver.extensions.flutter_integration.flutter_commands import FlutterCommand + from appium.webdriver.webdriver import WebDriver LOGIN_BUTTON_FINDER = FlutterFinder.by_text('Login') -class TestFlutterFinders(BaseTestCase): - def test_by_flutter_key(self) -> None: - user_name_field_finder = FlutterFinder.by_key('username_text_field') - user_name_field = self.driver.find_element(*user_name_field_finder.as_args()) - assert user_name_field.text == 'admin' - - user_name_field.clear() - user_name_field = self.driver.find_element(*user_name_field_finder.as_args()).send_keys('admin123') - assert user_name_field.text == 'admin123' - - def test_by_flutter_type(self) -> None: - login_button = self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TYPE, 'ElevatedButton') - assert login_button.find_element(AppiumBy.FLUTTER_INTEGRATION_TYPE, 'Text').text == 'Login' - - def test_by_flutter_text(self) -> None: - login_button = self.driver.find_element(*LOGIN_BUTTON_FINDER.as_args()) - assert login_button.text == 'Login' - - login_button.click() - slider = self.driver.find_elements(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Slider') - assert len(slider) == 1 - - def test_by_flutter_text_containing(self) -> None: - login_button = self.driver.find_element(*LOGIN_BUTTON_FINDER.as_args()) - login_button.click() - vertical_swipe_label = self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Vertical') - assert vertical_swipe_label.text == 'Vertical Swiping' - - def test_by_flutter_semantics_label(self) -> None: - login_button = self.driver.find_element(*LOGIN_BUTTON_FINDER.as_args()) - login_button.click() - element = self.flutter_command.scroll_till_visible(FlutterFinder.by_text('Lazy Loading')) - element.click() - message_field = self.driver.find_element(AppiumBy.FLUTTER_INTEGRATION_SEMANTICS_LABEL, 'message_field') - assert message_field.text == 'Hello world' +def test_by_flutter_key(driver: 'WebDriver') -> None: + """Test finding elements by Flutter key.""" + user_name_field_finder = FlutterFinder.by_key('username_text_field') + user_name_field = driver.find_element(*user_name_field_finder.as_args()) + assert user_name_field.text == 'admin' + + user_name_field.clear() + user_name_field = driver.find_element(*user_name_field_finder.as_args()).send_keys('admin123') + assert user_name_field.text == 'admin123' + + +def test_by_flutter_type(driver: 'WebDriver') -> None: + """Test finding elements by Flutter type.""" + login_button = driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TYPE, 'ElevatedButton') + assert login_button.find_element(AppiumBy.FLUTTER_INTEGRATION_TYPE, 'Text').text == 'Login' + + +def test_by_flutter_text(driver: 'WebDriver') -> None: + """Test finding elements by Flutter text.""" + login_button = driver.find_element(*LOGIN_BUTTON_FINDER.as_args()) + assert login_button.text == 'Login' + + login_button.click() + slider = driver.find_elements(AppiumBy.FLUTTER_INTEGRATION_TEXT, 'Slider') + assert len(slider) == 1 + + +def test_by_flutter_text_containing(driver: 'WebDriver') -> None: + """Test finding elements by Flutter text containing.""" + login_button = driver.find_element(*LOGIN_BUTTON_FINDER.as_args()) + login_button.click() + vertical_swipe_label = driver.find_element(AppiumBy.FLUTTER_INTEGRATION_TEXT_CONTAINING, 'Vertical') + assert vertical_swipe_label.text == 'Vertical Swiping' + + +def test_by_flutter_semantics_label(driver: 'WebDriver', flutter_command: 'FlutterCommand') -> None: + """Test finding elements by Flutter semantics label.""" + login_button = driver.find_element(*LOGIN_BUTTON_FINDER.as_args()) + login_button.click() + element = flutter_command.scroll_till_visible(FlutterFinder.by_text('Lazy Loading')) + element.click() + message_field = driver.find_element(AppiumBy.FLUTTER_INTEGRATION_SEMANTICS_LABEL, 'message_field') + assert message_field.text == 'Hello world' diff --git a/test/functional/flutter_integration/helper/desired_capabilities.py b/test/functional/flutter_integration/helper/desired_capabilities.py deleted file mode 100644 index b03053418..000000000 --- a/test/functional/flutter_integration/helper/desired_capabilities.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -from typing import Any, Dict - - -def get_desired_capabilities(platform_name: str) -> Dict[str, Any]: - desired_caps: Dict[str, Any] = {} - if platform_name == 'android': - desired_caps.update( - { - 'platformName': 'Android', - 'deviceName': 'Android Emulator', - 'newCommandTimeout': 120, - 'uiautomator2ServerInstallTimeout': 120000, - 'adbExecTimeout': 120000, - 'app': os.getenv('FLUTTER_ANDROID_APP'), - 'autoGrantPermissions': True, - } - ) - else: - desired_caps.update( - { - 'deviceName': os.getenv('IPHONE_MODEL'), - 'platformName': 'iOS', - 'platformVersion': os.getenv('IOS_VERSION'), - 'allowTouchIdEnroll': True, - 'wdaLaunchTimeout': 240000, - 'wdaLocalPort': 8100, - 'eventTimings': True, - 'app': os.getenv('FLUTTER_IOS_APP'), - } - ) - - return desired_caps diff --git a/test/functional/flutter_integration/helper/options.py b/test/functional/flutter_integration/helper/options.py new file mode 100644 index 000000000..5cad7de31 --- /dev/null +++ b/test/functional/flutter_integration/helper/options.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +from typing import Any + +from appium.options.flutter_integration.base import FlutterOptions +from test.functional.test_helper import get_wda_port, get_worker_info + + +def is_platform_android() -> bool: + """Check if the current platform is Android.""" + return os.getenv('PLATFORM', 'android').lower() == 'android' + + +def get_flutter_system_port() -> int: + """ + Get a unique Flutter system port for the current worker. + Uses base port 9999 and increments by worker number. + """ + worker_info = get_worker_info() + return 9999 + (worker_info.worker_number or 0) + + +def make_options() -> FlutterOptions: + """Get Flutter options configured for testing with parallel execution support.""" + options = FlutterOptions() + + # Set Flutter-specific capabilities + options.flutter_system_port = get_flutter_system_port() + options.flutter_enable_mock_camera = True + options.flutter_element_wait_timeout = 10000 + options.flutter_server_launch_timeout = 120000 + + caps: dict[str, Any] = ( + { + 'platformName': 'Android', + 'deviceName': device_name(), + 'newCommandTimeout': 120, + 'uiautomator2ServerInstallTimeout': 120000, + 'adbExecTimeout': 120000, + 'app': os.environ['FLUTTER_ANDROID_APP'], + 'autoGrantPermissions': True, + } + if is_platform_android() + else { + 'deviceName': device_name(), + 'platformName': 'iOS', + 'platformVersion': os.environ['IOS_VERSION'], + 'allowTouchIdEnroll': True, + 'wdaLaunchTimeout': 240000, + 'wdaLocalPort': get_wda_port(), + 'eventTimings': True, + 'app': os.environ['FLUTTER_IOS_APP'], + } + ) + + if local_prebuilt_wda := os.getenv('LOCAL_PREBUILT_WDA'): + caps.update( + { + 'usePreinstalledWDA': True, + 'prebuiltWDAPath': local_prebuilt_wda, + } + ) + + return options.load_capabilities(caps) + + +def device_name() -> str: + """ + Get a unique device name for the current worker. + Uses the base device name and appends the port number for uniqueness. + """ + prefix = 'Android Emulator' if is_platform_android() else os.environ['IPHONE_MODEL'] + + worker_info = get_worker_info() + + if worker_info.is_parallel: + port = get_flutter_system_port() if is_platform_android() else get_wda_port() + return f'{prefix} - {port}' + + return prefix diff --git a/test/functional/flutter_integration/helper/test_helper.py b/test/functional/flutter_integration/helper/test_helper.py deleted file mode 100644 index 19c669754..000000000 --- a/test/functional/flutter_integration/helper/test_helper.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -from appium import webdriver -from appium.options.flutter_integration.base import FlutterOptions -from appium.webdriver.client_config import AppiumClientConfig -from appium.webdriver.extensions.flutter_integration.flutter_commands import FlutterCommand -from test.helpers.constants import SERVER_URL_BASE - -from . import desired_capabilities - - -class BaseTestCase(object): - def setup_method(self) -> None: - platform_name = os.getenv('PLATFORM', 'android').lower() - - # set flutter options - flutterOptions = FlutterOptions() - flutterOptions.flutter_system_port = 9999 - flutterOptions.flutter_enable_mock_camera = True - flutterOptions.flutter_element_wait_timeout = 10000 - flutterOptions.flutter_server_launch_timeout = 120000 - - desired_caps = desired_capabilities.get_desired_capabilities(platform_name) - - client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) - client_config.timeout = 600 - - self.driver = webdriver.Remote(options=flutterOptions.load_capabilities(desired_caps), client_config=client_config) - self.flutter_command = FlutterCommand(self.driver) - - def teardown_method(self) -> None: # type: ignore - if not hasattr(self, 'driver'): - return - self.driver.quit() diff --git a/test/functional/ios/helper/desired_capabilities.py b/test/functional/ios/helper/desired_capabilities.py deleted file mode 100644 index c26fc7a89..000000000 --- a/test/functional/ios/helper/desired_capabilities.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os -from typing import Any, Dict, Optional - -# Returns abs path relative to this file and not cwd - - -def PATH(p: str) -> str: - return os.path.abspath(os.path.join(os.path.dirname(__file__), p)) - - -BUNDLE_ID = 'com.example.apple-samplecode.UICatalog' - - -def get_desired_capabilities(app: Optional[str] = None) -> Dict[str, Any]: - desired_caps: Dict[str, Any] = { - 'deviceName': iphone_device_name(), - 'platformName': 'iOS', - 'platformVersion': os.getenv('IOS_VERSION') or '17.4', - 'automationName': 'XCUITest', - 'allowTouchIdEnroll': True, - 'wdaLocalPort': wda_port(), - 'simpleIsVisibleCheck': True, - } - - if app is not None: - desired_caps['app'] = PATH(os.path.join('../../..', 'apps', app)) - - local_prebuilt_wda = os.getenv('LOCAL_PREBUILT_WDA') - if local_prebuilt_wda: - desired_caps['usePreinstalledWDA'] = True - desired_caps['prebuiltWDAPath'] = local_prebuilt_wda - - return desired_caps - - -class PytestXdistWorker: - NUMBER: Optional[str] = os.getenv('PYTEST_XDIST_WORKER') - COUNT: Optional[str] = os.getenv('PYTEST_XDIST_WORKER_COUNT') # Return 2 if `-n 2` is passed - - @staticmethod - def gw(number: int) -> str: - if PytestXdistWorker.COUNT is None: - return '0' - - if number >= int(PytestXdistWorker.COUNT): - return 'gw0' - - return f'gw{number}' - - -# If you run tests with pytest-xdist, you can run tests in parallel. - - -def wda_port() -> int: - if PytestXdistWorker.NUMBER == PytestXdistWorker.gw(1): - return 8101 - - return 8100 - - -# Before running tests, you must have iOS simulators named 'iPhone 12 - 8100' and 'iPhone 12 - 8101' - - -def iphone_device_name() -> str: - prefix = os.getenv('IPHONE_MODEL') or 'iPhone 15 Plus' - if PytestXdistWorker.NUMBER == PytestXdistWorker.gw(0): - return f'{prefix} - 8100' - elif PytestXdistWorker.NUMBER == PytestXdistWorker.gw(1): - return f'{prefix} - 8101' - - return prefix diff --git a/test/functional/ios/helper/options.py b/test/functional/ios/helper/options.py new file mode 100644 index 000000000..c2d2fc3f9 --- /dev/null +++ b/test/functional/ios/helper/options.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +from appium.options.ios import XCUITestOptions +from test.functional.test_helper import get_wda_port, get_worker_info + + +def make_options(app: str | None = None) -> XCUITestOptions: + """Get XCUITest options configured for iOS testing with parallel execution support.""" + options = XCUITestOptions() + + # Set basic iOS capabilities + options.device_name = iphone_device_name() + options.platform_version = os.getenv('IOS_VERSION') or '17.4' + options.allow_touch_id_enroll = True + options.wda_local_port = get_wda_port() + options.simple_is_visible_check = True + + if app is not None: + options.app = app + + if local_prebuilt_wda := os.getenv('LOCAL_PREBUILT_WDA'): + options.use_preinstalled_wda = True + options.prebuilt_wda_path = local_prebuilt_wda + + return options + + +def iphone_device_name() -> str: + """ + Get a unique device name for the current worker. + Uses the base device name and appends the port number for uniqueness. + """ + prefix = os.getenv('IPHONE_MODEL') or 'iPhone 15 Plus' + worker_info = get_worker_info() + + if worker_info.is_parallel: + port = get_wda_port() + return f'{prefix} - {port}' + + return prefix diff --git a/test/functional/ios/helper/test_helper.py b/test/functional/ios/helper/test_helper.py deleted file mode 100644 index 435ca4b45..000000000 --- a/test/functional/ios/helper/test_helper.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import os - -from appium import webdriver -from appium.options.ios import XCUITestOptions -from appium.webdriver.client_config import AppiumClientConfig -from test.functional.test_helper import is_ci -from test.helpers.constants import SERVER_URL_BASE - -from . import desired_capabilities - - -class BaseTestCase(object): - IOS_UICATALOG_APP_NAME = 'UIKitCatalog' - - def setup_method(self) -> None: - desired_caps = desired_capabilities.get_desired_capabilities('UICatalog.app.zip') - client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) - client_config.timeout = 600 - self.driver = webdriver.Remote(options=XCUITestOptions().load_capabilities(desired_caps), client_config=client_config) - if is_ci(): - self.driver.start_recording_screen() - - def teardown_method(self, method) -> None: # type: ignore - if not hasattr(self, 'driver'): - return - - if is_ci(): - payload = self.driver.stop_recording_screen() - video_path = os.path.join(os.getcwd(), method.__name__ + '.mp4') - with open(video_path, 'wb') as fd: - fd.write(base64.b64decode(payload)) - self.driver.quit() diff --git a/test/functional/ios/safari_tests.py b/test/functional/ios/safari_tests.py index c7bd997c1..211995879 100644 --- a/test/functional/ios/safari_tests.py +++ b/test/functional/ios/safari_tests.py @@ -13,62 +13,68 @@ # limitations under the License. import time +from collections.abc import Generator +from typing import TYPE_CHECKING + +import pytest from appium import webdriver -from appium.options.common import AppiumOptions from appium.webdriver.client_config import AppiumClientConfig from test.helpers.constants import SERVER_URL_BASE -from .helper.desired_capabilities import get_desired_capabilities - - -class TestSafari: - def setup_method(self) -> None: - caps = get_desired_capabilities() - caps.update( - { - 'bundleId': 'com.apple.mobilesafari', - 'nativeWebTap': True, - 'safariIgnoreFraudWarning': True, - 'webviewConnectTimeout': 100000, - } - ) - client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) - client_config.timeout = 600 - self.driver = webdriver.Remote(options=AppiumOptions().load_capabilities(caps), client_config=client_config) - - # Fresh iOS 17.4 simulator may not show up the webview context with "safari" - # after a fresh simlator instance creation. - # Re-launch the process could be a workaround in my debugging. - self.driver.terminate_app('com.apple.mobilesafari') - self.driver.activate_app('com.apple.mobilesafari') - - def teardown_method(self) -> None: - self.driver.quit() - - def test_context(self) -> None: - contexts = self.driver.contexts - assert 'NATIVE_APP' == contexts[0] - assert contexts[1].startswith('WEBVIEW_') - self.driver.switch_to.context(contexts[1]) - assert 'WEBVIEW_' in self.driver.current_context - - def test_get(self) -> None: - ok = False - contexts = self.driver.contexts - for context in contexts: - if context.startswith('WEBVIEW_'): - self.driver.switch_to.context(context) - ok = True - break - - if ok is False: - assert False, 'Could not set WEBVIEW context' - - self.driver.get('http://google.com') - for _ in range(5): - time.sleep(0.5) - if 'Google' == self.driver.title: - return - - assert False, 'The title was wrong' +from .helper.options import make_options + +if TYPE_CHECKING: + from appium.webdriver.webdriver import WebDriver + + +@pytest.fixture +def driver() -> Generator['WebDriver', None, None]: + """Create and configure Safari driver for testing.""" + options = make_options() + options.bundle_id = 'com.apple.mobilesafari' + options.native_web_tap = True + options.safari_ignore_fraud_warning = True + options.webview_connect_timeout = 100000 + + client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) + client_config.timeout = 600 + driver = webdriver.Remote(options=options, client_config=client_config) + + # Fresh iOS 17.4 simulator may not show up the webview context with "safari" + # after a fresh simlator instance creation. + # Re-launch the process could be a workaround in my debugging. + driver.terminate_app('com.apple.mobilesafari') + driver.activate_app('com.apple.mobilesafari') + + yield driver + + driver.quit() + + +def test_context(driver: 'WebDriver') -> None: + """Test Safari context switching.""" + contexts = driver.contexts + assert contexts[0] == 'NATIVE_APP' + assert contexts[1].startswith('WEBVIEW_') + driver.switch_to.context(contexts[1]) + assert 'WEBVIEW_' in driver.current_context + + +def test_navigation(driver: 'WebDriver') -> None: + """Test Safari navigation to Google.""" + contexts = driver.contexts + for context in contexts: + if context.startswith('WEBVIEW_'): + driver.switch_to.context(context) + break + else: + pytest.fail('Could not set WEBVIEW context') + + driver.get('http://google.com') + for _ in range(5): + time.sleep(0.5) + if driver.title == 'Google': + return + + pytest.fail('The title was wrong') diff --git a/test/functional/mac/helper/desired_capabilities.py b/test/functional/mac/helper/desired_capabilities.py index 648420efb..6b3947cf9 100644 --- a/test/functional/mac/helper/desired_capabilities.py +++ b/test/functional/mac/helper/desired_capabilities.py @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Dict +from typing import Any -def get_desired_capabilities() -> Dict[str, Any]: - desired_caps: Dict[str, Any] = {'platformName': 'mac', 'automationName': 'Mac2', 'bundleId': 'com.apple.TextEdit'} +def get_desired_capabilities() -> dict[str, Any]: + desired_caps: dict[str, Any] = {'platformName': 'mac', 'automationName': 'Mac2', 'bundleId': 'com.apple.TextEdit'} return desired_caps diff --git a/test/functional/mac/helper/test_helper.py b/test/functional/mac/helper/test_helper.py index 0b7463dac..edee8395b 100644 --- a/test/functional/mac/helper/test_helper.py +++ b/test/functional/mac/helper/test_helper.py @@ -20,7 +20,7 @@ from .desired_capabilities import get_desired_capabilities -class BaseTestCase(object): +class BaseTestCase: def setup_method(self) -> None: client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE) client_config.timeout = 600 diff --git a/test/functional/test_helper.py b/test/functional/test_helper.py index 817f833ea..550c26e4a 100644 --- a/test/functional/test_helper.py +++ b/test/functional/test_helper.py @@ -1,8 +1,10 @@ import os import socket import time +from collections.abc import Callable +from dataclasses import dataclass from time import sleep -from typing import TYPE_CHECKING, Any, Callable +from typing import TYPE_CHECKING, Any from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait @@ -95,3 +97,47 @@ def wait_for_element(driver: 'WebDriver', locator: str, value: str, timeout_sec: The found WebElement """ return WebDriverWait(driver, timeout_sec).until(EC.presence_of_element_located((locator, value))) + + +@dataclass +class WorkerInfo: + """Information about the current test worker in parallel execution.""" + + worker_number: int | None + total_workers: int | None + + @property + def is_parallel(self) -> bool: + """Check if running in parallel mode.""" + return self.worker_number is not None and self.total_workers is not None + + +def get_worker_info() -> WorkerInfo: + """ + Get current worker number and total worker count from pytest-xdist environment variables. + + Returns: + WorkerInfo: Worker information or None values if not running in parallel + """ + worker_number = os.getenv('PYTEST_XDIST_WORKER') + worker_count = os.getenv('PYTEST_XDIST_WORKER_COUNT') + + if worker_number and worker_count: + # Extract number from worker string like 'gw0', 'gw1', etc. + try: + worker_num = int(worker_number.replace('gw', '')) + total_workers = int(worker_count) + return WorkerInfo(worker_number=worker_num, total_workers=total_workers) + except (ValueError, AttributeError): + pass + + return WorkerInfo(worker_number=None, total_workers=None) + + +def get_wda_port() -> int: + """ + Get a unique WDA port for the current worker. + Uses base port 8100 and increments by worker number. + """ + worker_info = get_worker_info() + return 8100 + (worker_info.worker_number or 0) diff --git a/test/helpers/constants.py b/test/helpers/constants.py index 9f453add8..f2cff27db 100644 --- a/test/helpers/constants.py +++ b/test/helpers/constants.py @@ -1 +1,3 @@ -SERVER_URL_BASE = 'http://127.0.0.1:4723' +import os + +SERVER_URL_BASE = f'http://{os.getenv("APPIUM_TEST_SERVER_HOST", "127.0.0.1")}:{os.getenv("APPIUM_TEST_SERVER_PORT", "4723")}' diff --git a/test/unit/helper/test_helper.py b/test/unit/helper/test_helper.py index 58e358176..b31d5457a 100644 --- a/test/unit/helper/test_helper.py +++ b/test/unit/helper/test_helper.py @@ -13,7 +13,7 @@ # limitations under the License. import json -from typing import TYPE_CHECKING, Any, Dict +from typing import TYPE_CHECKING, Any import httpretty @@ -199,6 +199,6 @@ def flutter_w3c_driver() -> 'WebDriver': return driver -def get_httpretty_request_body(request: 'HTTPrettyRequestEmpty') -> Dict[str, Any]: +def get_httpretty_request_body(request: 'HTTPrettyRequestEmpty') -> dict[str, Any]: """Returns utf-8 decoded request body""" return json.loads(request.body.decode('utf-8')) diff --git a/test/unit/webdriver/app_test.py b/test/unit/webdriver/app_test.py index 347675358..e0051167d 100644 --- a/test/unit/webdriver/app_test.py +++ b/test/unit/webdriver/app_test.py @@ -26,10 +26,10 @@ def test_install_app(driver_func): httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') result = driver.install_app('path/to/app') - assert { + assert get_httpretty_request_body(httpretty.last_request()) == { 'args': [{'app': 'path/to/app', 'appPath': 'path/to/app'}], 'script': 'mobile: installApp', - } == get_httpretty_request_body(httpretty.last_request()) + } assert isinstance(result, WebDriver) @@ -40,10 +40,10 @@ def test_remove_app(driver_func): httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') result = driver.remove_app('com.app.id') - assert { + assert get_httpretty_request_body(httpretty.last_request()) == { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], 'script': 'mobile: removeApp', - } == get_httpretty_request_body(httpretty.last_request()) + } assert isinstance(result, WebDriver) @@ -54,10 +54,10 @@ def test_app_installed(driver_func): httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') result = driver.is_app_installed('com.app.id') - assert { + assert get_httpretty_request_body(httpretty.last_request()) == { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], 'script': 'mobile: isAppInstalled', - } == get_httpretty_request_body(httpretty.last_request()) + } assert result is True @@ -68,10 +68,10 @@ def test_terminate_app(driver_func): httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') result = driver.terminate_app('com.app.id') - assert { + assert get_httpretty_request_body(httpretty.last_request()) == { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], 'script': 'mobile: terminateApp', - } == get_httpretty_request_body(httpretty.last_request()) + } assert result is True @@ -82,10 +82,10 @@ def test_activate_app(driver_func): httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') result = driver.activate_app('com.app.id') - assert { + assert get_httpretty_request_body(httpretty.last_request()) == { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], 'script': 'mobile: activateApp', - } == get_httpretty_request_body(httpretty.last_request()) + } assert isinstance(result, WebDriver) @@ -96,7 +96,7 @@ def test_background_app(driver_func): httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') result = driver.background_app(0) - assert {'args': [{'seconds': 0}], 'script': 'mobile: backgroundApp'} == get_httpretty_request_body(httpretty.last_request()) + assert get_httpretty_request_body(httpretty.last_request()) == {'args': [{'seconds': 0}], 'script': 'mobile: backgroundApp'} assert isinstance(result, WebDriver) @@ -107,10 +107,10 @@ def test_query_app_state(driver_func): httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": 3}') result = driver.query_app_state('com.app.id') - assert { + assert get_httpretty_request_body(httpretty.last_request()) == { 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], 'script': 'mobile: queryAppState', - } == get_httpretty_request_body(httpretty.last_request()) + } assert result is ApplicationState.RUNNING_IN_BACKGROUND @@ -125,8 +125,8 @@ def test_app_strings(driver_func): ) result = driver.app_strings() - assert {'args': [{}], 'script': 'mobile: getAppStrings'} == get_httpretty_request_body(httpretty.last_request()) - assert "You can't wipe my data, you are a monkey!" == result['monkey_wipe_data'], result + assert get_httpretty_request_body(httpretty.last_request()) == {'args': [{}], 'script': 'mobile: getAppStrings'} + assert result['monkey_wipe_data'] == "You can't wipe my data, you are a monkey!", result @pytest.mark.parametrize('driver_func', [android_w3c_driver, ios_w3c_driver]) @@ -140,10 +140,11 @@ def test_app_strings_with_lang(driver_func): ) result = driver.app_strings('en') - assert {'args': [{'language': 'en'}], 'script': 'mobile: getAppStrings'} == get_httpretty_request_body( - httpretty.last_request() - ) - assert "You can't wipe my data, you are a monkey!" == result['monkey_wipe_data'], result + assert get_httpretty_request_body(httpretty.last_request()) == { + 'args': [{'language': 'en'}], + 'script': 'mobile: getAppStrings', + } + assert result['monkey_wipe_data'] == "You can't wipe my data, you are a monkey!", result @pytest.mark.parametrize('driver_func', [android_w3c_driver, ios_w3c_driver]) @@ -157,8 +158,8 @@ def test_app_strings_with_lang_and_file(driver_func): ) result = driver.app_strings('en', 'some_file') - assert { + assert get_httpretty_request_body(httpretty.last_request()) == { 'args': [{'language': 'en', 'stringFile': 'some_file'}], 'script': 'mobile: getAppStrings', - } == get_httpretty_request_body(httpretty.last_request()) - assert "You can't wipe my data, you are a monkey!" == result['monkey_wipe_data'], result + } + assert result['monkey_wipe_data'] == "You can't wipe my data, you are a monkey!", result diff --git a/test/unit/webdriver/appium_service_test.py b/test/unit/webdriver/appium_service_test.py index 763a6a374..784c6e549 100644 --- a/test/unit/webdriver/appium_service_test.py +++ b/test/unit/webdriver/appium_service_test.py @@ -15,6 +15,6 @@ from appium.webdriver.appium_service import AppiumService -class TestAppiumService(object): +class TestAppiumService: def test_get_instance(self): assert AppiumService() diff --git a/test/unit/webdriver/context_test.py b/test/unit/webdriver/context_test.py index 80c2c0f78..7198984c7 100644 --- a/test/unit/webdriver/context_test.py +++ b/test/unit/webdriver/context_test.py @@ -17,7 +17,7 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverContext(object): +class TestWebDriverContext: @httpretty.activate def test_current_contexts(self): driver = android_w3c_driver() @@ -31,7 +31,7 @@ def test_get_contexts(self): httpretty.GET, appium_command('/session/1234567890/contexts'), body='{"value": ["NATIVE_APP", "CHROMIUM"]}' ) - assert ['NATIVE_APP', 'CHROMIUM'] == driver.contexts + assert driver.contexts == ['NATIVE_APP', 'CHROMIUM'] @httpretty.activate def test_switch_to_context(self): @@ -40,7 +40,7 @@ def test_switch_to_context(self): driver.switch_to.context(None) - assert {'name': None} == get_httpretty_request_body(httpretty.last_request()) + assert get_httpretty_request_body(httpretty.last_request()) == {'name': None} @httpretty.activate def test_switch_to_context_native_app(self): @@ -49,4 +49,4 @@ def test_switch_to_context_native_app(self): driver.switch_to.context('NATIVE_APP') - assert {'name': 'NATIVE_APP'} == get_httpretty_request_body(httpretty.last_request()) + assert get_httpretty_request_body(httpretty.last_request()) == {'name': 'NATIVE_APP'} diff --git a/test/unit/webdriver/device/activities_test.py b/test/unit/webdriver/device/activities_test.py index 2374ba6cc..15df9b783 100644 --- a/test/unit/webdriver/device/activities_test.py +++ b/test/unit/webdriver/device/activities_test.py @@ -17,15 +17,10 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command -class TestWebDriverActivities(object): +class TestWebDriverActivities: @httpretty.activate def test_current_activity(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.GET, - appium_command('/session/1234567890/appium/device/current_activity'), - body='{"value": ".ExampleActivity"}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -36,11 +31,6 @@ def test_current_activity(self): @httpretty.activate def test_wait_activity(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.GET, - appium_command('/session/1234567890/appium/device/current_activity'), - body='{"value": ".ExampleActivity"}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), diff --git a/test/unit/webdriver/device/clipboard_test.py b/test/unit/webdriver/device/clipboard_test.py index 7e21797a0..4f313b2fe 100644 --- a/test/unit/webdriver/device/clipboard_test.py +++ b/test/unit/webdriver/device/clipboard_test.py @@ -18,19 +18,16 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body, ios_w3c_driver -class TestWebDriverClipboard(object): +class TestWebDriverClipboard: @httpretty.activate def test_set_clipboard_with_url(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/set_clipboard'), body='{"value": ""}' - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}', ) - driver.set_clipboard(bytes(str('http://appium.io/'), 'UTF-8'), ClipboardContentType.URL, 'label for android') + driver.set_clipboard(bytes('http://appium.io/', 'UTF-8'), ClipboardContentType.URL, 'label for android') d = get_httpretty_request_body(httpretty.last_request()) assert d['args'][0]['content'] == 'aHR0cDovL2FwcGl1bS5pby8=' @@ -40,9 +37,6 @@ def test_set_clipboard_with_url(self): @httpretty.activate def test_set_clipboard_text(self): driver = ios_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/set_clipboard'), body='{"value": ""}' - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), diff --git a/test/unit/webdriver/device/common_test.py b/test/unit/webdriver/device/common_test.py index 43b069a08..596e988e6 100644 --- a/test/unit/webdriver/device/common_test.py +++ b/test/unit/webdriver/device/common_test.py @@ -18,25 +18,21 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverCommon(object): +class TestWebDriverCommon: @httpretty.activate def test_open_notifications(self): driver = android_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.open_notifications(), WebDriver) - assert {'args': [], 'script': 'mobile: openNotifications'} == get_httpretty_request_body(httpretty.last_request()) + assert get_httpretty_request_body(httpretty.last_request()) == {'args': [], 'script': 'mobile: openNotifications'} @httpretty.activate def test_current_package(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.GET, - appium_command('/session/1234567890/appium/device/current_package'), - body='{"value": ".ExamplePackage"}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ".ExamplePackage"}', ) assert driver.current_package == '.ExamplePackage' + assert get_httpretty_request_body(httpretty.last_request()) == {'args': [], 'script': 'mobile: getCurrentPackage'} diff --git a/test/unit/webdriver/device/device_time_test.py b/test/unit/webdriver/device/device_time_test.py index 8c6f5e0b9..98d01336f 100644 --- a/test/unit/webdriver/device/device_time_test.py +++ b/test/unit/webdriver/device/device_time_test.py @@ -17,15 +17,10 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverDeviceTime(object): +class TestWebDriverDeviceTime: @httpretty.activate def test_device_time(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.GET, - appium_command('/session/1234567890/appium/device/system_time'), - body='{"value": "2019-01-05T14:46:44+09:00"}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -36,11 +31,6 @@ def test_device_time(self): @httpretty.activate def test_get_device_time(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.GET, - appium_command('/session/1234567890/appium/device/system_time'), - body='{"value": "2019-01-05T14:46:44+09:00"}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -51,11 +41,6 @@ def test_get_device_time(self): @httpretty.activate def test_get_formatted_device_time(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/system_time'), - body='{"value": "2019-01-08"}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -64,4 +49,5 @@ def test_get_formatted_device_time(self): assert driver.get_device_time('YYYY-MM-DD') == '2019-01-08' d = get_httpretty_request_body(httpretty.last_request()) - assert d.get('format', d['args'][0]['format']) == 'YYYY-MM-DD' + assert d['script'] == 'mobile: getDeviceTime' + assert d['args'][0]['format'] == 'YYYY-MM-DD' diff --git a/test/unit/webdriver/device/display_test.py b/test/unit/webdriver/device/display_test.py index bce0b4e43..cc93c86a6 100644 --- a/test/unit/webdriver/device/display_test.py +++ b/test/unit/webdriver/device/display_test.py @@ -17,12 +17,9 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command -class TestWebDriverDisplay(object): +class TestWebDriverDisplay: @httpretty.activate def test_get_display_density(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.GET, appium_command('/session/1234567890/appium/device/display_density'), body='{"value": 560}' - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": 560}') assert driver.get_display_density() == 560 diff --git a/test/unit/webdriver/device/fingerprint_test.py b/test/unit/webdriver/device/fingerprint_test.py index e6facf86d..93b027842 100644 --- a/test/unit/webdriver/device/fingerprint_test.py +++ b/test/unit/webdriver/device/fingerprint_test.py @@ -18,15 +18,10 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverFingerprint(object): +class TestWebDriverFingerprint: @httpretty.activate def test_finger_print(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/finger_print'), - # body is None - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -36,4 +31,5 @@ def test_finger_print(self): assert isinstance(driver.finger_print(1), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) - assert d.get('fingerprintId', d['args'][0]['fingerprintId']) == 1 + assert d['script'] == 'mobile: fingerprint' + assert d['args'][0]['fingerprintId'] == 1 diff --git a/test/unit/webdriver/device/gsm_test.py b/test/unit/webdriver/device/gsm_test.py index cd776a94a..b40f2df5a 100644 --- a/test/unit/webdriver/device/gsm_test.py +++ b/test/unit/webdriver/device/gsm_test.py @@ -19,7 +19,7 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriveGsm(object): +class TestWebDriveGsm: @httpretty.activate def test_make_gsm_call(self): driver = android_w3c_driver() diff --git a/test/unit/webdriver/device/keyboard_test.py b/test/unit/webdriver/device/keyboard_test.py index 526f1826f..68f77bdbf 100644 --- a/test/unit/webdriver/device/keyboard_test.py +++ b/test/unit/webdriver/device/keyboard_test.py @@ -14,100 +14,91 @@ import httpretty +from appium.webdriver.extensions.android.nativekey import AndroidKeyMetastate from appium.webdriver.webdriver import WebDriver from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body, ios_w3c_driver -class TestWebDriverKeyboardAndroid(object): +class TestWebDriverKeyboardAndroid: @httpretty.activate def test_hide_keyboard(self): driver = android_w3c_driver() - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/hide_keyboard')) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.hide_keyboard(), WebDriver) @httpretty.activate def test_press_keycode(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/press_keycode'), body='{"value": "86"}' - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": "86"}') driver.press_keycode(86) - d = get_httpretty_request_body((httpretty.last_request())) - assert d.get('keycode', d['args'][0]['keycode']) == 86 + d = get_httpretty_request_body(httpretty.last_request()) + assert d['script'] == 'mobile: pressKey' + assert d['args'][0]['keycode'] == 86 @httpretty.activate def test_long_press_keycode(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/long_press_keycode'), - body='{"value": "86"}', - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": "86"}') driver.long_press_keycode(86) - d = get_httpretty_request_body((httpretty.last_request())) - assert d.get('keycode', d['args'][0]['keycode']) == 86 + d = get_httpretty_request_body(httpretty.last_request()) + assert d['script'] == 'mobile: pressKey' + assert d['args'][0]['keycode'] == 86 + assert d['args'][0]['isLongPress'] is True @httpretty.activate def test_keyevent(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/keyevent'), body='{keycode: 86}' - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": "86"}') assert isinstance(driver.keyevent(86), WebDriver) @httpretty.activate def test_press_keycode_with_flags(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/press_keycode'), - body='{keycode: 86, metastate: 2097153, flags: 44}', - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) # metastate is META_SHIFT_ON and META_NUM_LOCK_ON # flags is CANCELFLAG_CANCELEDED, FLAG_KEEP_TOUCH_MODE, FLAG_FROM_SYSTEM assert isinstance( - driver.press_keycode(86, metastate=0x00000001 | 0x00200000, flags=0x20 | 0x00000004 | 0x00000008), + driver.press_keycode( + 86, + metastate=AndroidKeyMetastate.META_SHIFT_ON | AndroidKeyMetastate.META_NUM_LOCK_ON, + flags=0x20 | 0x00000004 | 0x00000008, + ), WebDriver, ) @httpretty.activate def test_long_press_keycode_with_flags(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/long_press_keycode'), - body='{keycode: 86, metastate: 2097153, flags: 44}', - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) # metastate is META_SHIFT_ON and META_NUM_LOCK_ON # flags is CANCELFLAG_CANCELEDED, FLAG_KEEP_TOUCH_MODE, FLAG_FROM_SYSTEM assert isinstance( - driver.long_press_keycode(86, metastate=0x00000001 | 0x00200000, flags=0x20 | 0x00000004 | 0x00000008), + driver.long_press_keycode( + 86, + metastate=AndroidKeyMetastate.META_SHIFT_ON | AndroidKeyMetastate.META_NUM_LOCK_ON, + flags=0x20 | 0x00000004 | 0x00000008, + ), WebDriver, ) -class TestWebDriverKeyboardIOS(object): +class TestWebDriverKeyboardIOS: @httpretty.activate def test_hide_keyboard(self): driver = ios_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.hide_keyboard(), WebDriver) - assert {'args': [{}], 'script': 'mobile: hideKeyboard'} == get_httpretty_request_body(httpretty.last_request()) + assert get_httpretty_request_body(httpretty.last_request()) == {'args': [{}], 'script': 'mobile: hideKeyboard'} @httpretty.activate def test_hide_keyboard_with_key(self): driver = ios_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.hide_keyboard(key_name='Done'), WebDriver) - assert {'args': [{'keys': ['Done']}], 'script': 'mobile: hideKeyboard'} == get_httpretty_request_body( - httpretty.last_request() - ) + assert get_httpretty_request_body(httpretty.last_request()) == { + 'args': [{'keys': ['Done']}], + 'script': 'mobile: hideKeyboard', + } @httpretty.activate def test_hide_keyboard_with_key_and_strategy(self): @@ -115,22 +106,24 @@ def test_hide_keyboard_with_key_and_strategy(self): httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.hide_keyboard(strategy='pressKey', key='Done'), WebDriver) # only 'keys' works - assert {'args': [{'keys': ['Done']}], 'script': 'mobile: hideKeyboard'} == get_httpretty_request_body( - httpretty.last_request() - ) + assert get_httpretty_request_body(httpretty.last_request()) == { + 'args': [{'keys': ['Done']}], + 'script': 'mobile: hideKeyboard', + } @httpretty.activate def test_is_keyboard_shown(self): driver = ios_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) driver.is_keyboard_shown(), WebDriver - assert {'script': 'mobile: isKeyboardShown', 'args': []} == get_httpretty_request_body(httpretty.last_request()) + assert get_httpretty_request_body(httpretty.last_request()) == {'script': 'mobile: isKeyboardShown', 'args': []} @httpretty.activate def test_press_button(self): driver = ios_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) driver.press_button('Home') - assert {'script': 'mobile: pressButton', 'args': [{'name': 'Home'}]} == get_httpretty_request_body( - httpretty.last_request() - ) + assert get_httpretty_request_body(httpretty.last_request()) == { + 'script': 'mobile: pressButton', + 'args': [{'name': 'Home'}], + } diff --git a/test/unit/webdriver/device/location_test.py b/test/unit/webdriver/device/location_test.py index fb0112bc5..7fd423e3a 100644 --- a/test/unit/webdriver/device/location_test.py +++ b/test/unit/webdriver/device/location_test.py @@ -20,14 +20,16 @@ FLT_EPSILON = 1e-9 -class TestWebDriverLocation(object): +class TestWebDriverLocation: @httpretty.activate def test_toggle_location_services(self): driver = android_w3c_driver() - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/toggle_location_services')) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.toggle_location_services(), WebDriver) + d = get_httpretty_request_body(httpretty.last_request()) + assert d['script'] == 'mobile: toggleGps' + @httpretty.activate def test_set_location_float(self): driver = android_w3c_driver() diff --git a/test/unit/webdriver/device/lock_test.py b/test/unit/webdriver/device/lock_test.py index b54698543..603efffbd 100644 --- a/test/unit/webdriver/device/lock_test.py +++ b/test/unit/webdriver/device/lock_test.py @@ -18,114 +18,95 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body, ios_w3c_driver -class TestWebDriverLockAndroid(object): +class TestWebDriverLockAndroid: @httpretty.activate def test_lock(self): driver = android_w3c_driver() - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}') httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') driver.lock(1) d = get_httpretty_request_body(httpretty.last_request()) - assert d.get('seconds', d['args'][0]['seconds']) == 1 + assert d['script'] == 'mobile: lock' + assert d['args'][0]['seconds'] == 1 @httpretty.activate def test_lock_no_args(self): driver = android_w3c_driver() - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}') httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') driver.lock() @httpretty.activate def test_islocked_false(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": false}' - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": false}') assert driver.is_locked() is False @httpretty.activate def test_islocked_true(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": true}' - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') assert driver.is_locked() is True @httpretty.activate def test_unlock(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/unlock'), - ) - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') assert isinstance(driver.unlock(), WebDriver) + assert get_httpretty_request_body(httpretty.last_request())['script'] == 'mobile: unlock' -class TestWebDriverLockIOS(object): +class TestWebDriverLockIOS: @httpretty.activate def test_lock(self): driver = ios_w3c_driver() - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}') httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') driver.lock(1) d = get_httpretty_request_body(httpretty.last_request()) - assert d.get('seconds', d['args'][0]['seconds']) == 1 + assert d['script'] == 'mobile: lock' + assert d['args'][0]['seconds'] == 1 @httpretty.activate def test_lock_no_args(self): driver = ios_w3c_driver() - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}') httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') driver.lock() @httpretty.activate def test_islocked_false(self): driver = ios_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": false}' - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": false}') assert driver.is_locked() is False @httpretty.activate def test_islocked_true(self): driver = ios_w3c_driver() - httpretty.register_uri( - httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": true}' - ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') assert driver.is_locked() is True @httpretty.activate def test_unlock(self): driver = ios_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/unlock'), - ) - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}') assert isinstance(driver.unlock(), WebDriver) + assert get_httpretty_request_body(httpretty.last_request())['script'] == 'mobile: unlock' @httpretty.activate def test_touch_id(self): driver = ios_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.touch_id(True), WebDriver) - assert { + assert get_httpretty_request_body(httpretty.last_request()) == { 'script': 'mobile: sendBiometricMatch', 'args': [{'match': True, 'type': 'touchId'}], - } == get_httpretty_request_body(httpretty.last_request()) + } @httpretty.activate def test_enroll_biometric(self): driver = ios_w3c_driver() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.toggle_touch_id_enrollment(), WebDriver) - assert {'script': 'mobile: enrollBiometric', 'args': [{'isEnabled': True}]} == get_httpretty_request_body( - httpretty.last_request() - ) + assert get_httpretty_request_body(httpretty.last_request()) == { + 'script': 'mobile: enrollBiometric', + 'args': [{'isEnabled': True}], + } diff --git a/test/unit/webdriver/device/power_test.py b/test/unit/webdriver/device/power_test.py index 2d87a8d4c..ea5fe1dc7 100644 --- a/test/unit/webdriver/device/power_test.py +++ b/test/unit/webdriver/device/power_test.py @@ -19,14 +19,10 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverPower(object): +class TestWebDriverPower: @httpretty.activate def test_set_power_capacity(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/power_capacity'), - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -34,15 +30,12 @@ def test_set_power_capacity(self): assert isinstance(driver.set_power_capacity(50), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) + assert d['script'] == 'mobile: powerCapacity' assert d['args'][0]['percent'] == 50 @httpretty.activate def test_set_power_ac(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/power_ac'), - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -50,4 +43,5 @@ def test_set_power_ac(self): assert isinstance(driver.set_power_ac(Power.AC_ON), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) + assert d['script'] == 'mobile: powerAC' assert d['args'][0]['state'] == Power.AC_ON diff --git a/test/unit/webdriver/device/remote_fs_test.py b/test/unit/webdriver/device/remote_fs_test.py index 4de3a85fe..f1fca0df5 100644 --- a/test/unit/webdriver/device/remote_fs_test.py +++ b/test/unit/webdriver/device/remote_fs_test.py @@ -22,14 +22,10 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverRemoteFs(object): +class TestWebDriverRemoteFs: @httpretty.activate def test_push_file(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/push_file'), - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -40,16 +36,13 @@ def test_push_file(self): assert isinstance(driver.push_file(dest_path, data), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) - assert d.get('path', d['args'][0]['remotePath']) == dest_path - assert d.get('data', d['args'][0]['payload']) == str(data) + assert d['script'] == 'mobile: pushFile' + assert d['args'][0]['remotePath'] == dest_path + assert d['args'][0]['payload'] == str(data) @httpretty.activate def test_push_file_invalid_arg_exception_without_src_path_and_base64data(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/push_file'), - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -62,14 +55,6 @@ def test_push_file_invalid_arg_exception_without_src_path_and_base64data(self): @httpretty.activate def test_push_file_invalid_arg_exception_with_src_file_not_found(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/push_file'), - ) - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/push_file'), - ) dest_path = '/dest_path/to/file.txt' src_path = '/src_path/to/file.txt' @@ -79,11 +64,6 @@ def test_push_file_invalid_arg_exception_with_src_file_not_found(self): @httpretty.activate def test_pull_file(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/pull_file'), - body='{"value": "SGVsbG9Xb3JsZA=="}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -94,16 +74,12 @@ def test_pull_file(self): assert driver.pull_file(dest_path) == str(base64.b64encode(bytes('HelloWorld', 'utf-8')).decode('utf-8')) d = get_httpretty_request_body(httpretty.last_request()) - assert d.get('path', d['args'][0]['remotePath']) == dest_path + assert d['script'] == 'mobile: pullFile' + assert d['args'][0]['remotePath'] == dest_path @httpretty.activate def test_pull_folder(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/pull_folder'), - body='{"value": "base64EncodedZippedFolderData"}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -114,4 +90,5 @@ def test_pull_folder(self): assert driver.pull_folder(dest_path) == 'base64EncodedZippedFolderData' d = get_httpretty_request_body(httpretty.last_request()) - assert d.get('path', d['args'][0]['remotePath']) == dest_path + assert d['script'] == 'mobile: pullFolder' + assert d['args'][0]['remotePath'] == dest_path diff --git a/test/unit/webdriver/device/shake_test.py b/test/unit/webdriver/device/shake_test.py index 0371852f1..8c796255a 100644 --- a/test/unit/webdriver/device/shake_test.py +++ b/test/unit/webdriver/device/shake_test.py @@ -19,14 +19,10 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command -class TestWebDriverShake(object): +class TestWebDriverShake: @httpretty.activate def test_shake(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/shake'), - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), diff --git a/test/unit/webdriver/device/sms_test.py b/test/unit/webdriver/device/sms_test.py index 1323f50c4..a7200dca0 100644 --- a/test/unit/webdriver/device/sms_test.py +++ b/test/unit/webdriver/device/sms_test.py @@ -18,14 +18,10 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverSms(object): +class TestWebDriverSms: @httpretty.activate def test_send_sms(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/send_sms'), - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -33,5 +29,6 @@ def test_send_sms(self): assert isinstance(driver.send_sms('555-123-4567', 'Hey lol'), WebDriver) d = get_httpretty_request_body(httpretty.last_request()) + assert d['script'] == 'mobile: sendSms' assert d['args'][0]['phoneNumber'] == '555-123-4567' assert d['args'][0]['message'] == 'Hey lol' diff --git a/test/unit/webdriver/device/system_bars_test.py b/test/unit/webdriver/device/system_bars_test.py index 79e7c680c..3592c0059 100644 --- a/test/unit/webdriver/device/system_bars_test.py +++ b/test/unit/webdriver/device/system_bars_test.py @@ -17,7 +17,7 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command -class TestWebDriverSystemBars(object): +class TestWebDriverSystemBars: @httpretty.activate def test_get_system_bars(self): driver = android_w3c_driver() @@ -26,11 +26,6 @@ def test_get_system_bars(self): {"visible": true, "x": 0, "y": 0, "width": 1080, "height": 1920}, "navigationBar": {"visible": true, "x": 0, "y": 0, "width": 1080, "height": 126}}}""" - httpretty.register_uri( - httpretty.GET, - appium_command('/session/1234567890/appium/device/system_bars'), - body=body, - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), diff --git a/test/unit/webdriver/execute_driver_test.py b/test/unit/webdriver/execute_driver_test.py index 250b8cc84..65cdbbd2b 100644 --- a/test/unit/webdriver/execute_driver_test.py +++ b/test/unit/webdriver/execute_driver_test.py @@ -19,7 +19,7 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverExecuteDriver(object): +class TestWebDriverExecuteDriver: @httpretty.activate def test_batch(self): driver = android_w3c_driver() diff --git a/test/unit/webdriver/flutter_integration/flutter_actions_test.py b/test/unit/webdriver/flutter_integration/flutter_actions_test.py index 50a42e599..8c54a357c 100644 --- a/test/unit/webdriver/flutter_integration/flutter_actions_test.py +++ b/test/unit/webdriver/flutter_integration/flutter_actions_test.py @@ -24,7 +24,7 @@ from test.unit.helper.test_helper import appium_command, flutter_w3c_driver, get_httpretty_request_body -class TestFlutterActions(object): +class TestFlutterActions: @httpretty.activate def test_double_click(self): driver = flutter_w3c_driver() diff --git a/test/unit/webdriver/flutter_integration/flutter_search_context_test.py b/test/unit/webdriver/flutter_integration/flutter_search_context_test.py index 36e378437..d25c6c5cd 100644 --- a/test/unit/webdriver/flutter_integration/flutter_search_context_test.py +++ b/test/unit/webdriver/flutter_integration/flutter_search_context_test.py @@ -18,7 +18,7 @@ from test.unit.helper.test_helper import appium_command, flutter_w3c_driver, get_httpretty_request_body -class TestFlutterSearchContext(object): +class TestFlutterSearchContext: @httpretty.activate def test_find_element_by_flutter_key(self): driver = flutter_w3c_driver() diff --git a/test/unit/webdriver/flutter_integration/flutter_waits_test.py b/test/unit/webdriver/flutter_integration/flutter_waits_test.py index 62f9f7c1c..a0d5669d4 100644 --- a/test/unit/webdriver/flutter_integration/flutter_waits_test.py +++ b/test/unit/webdriver/flutter_integration/flutter_waits_test.py @@ -20,7 +20,7 @@ from test.unit.helper.test_helper import appium_command, flutter_w3c_driver, get_httpretty_request_body -class TestFlutterWaits(object): +class TestFlutterWaits: @httpretty.activate def test_wait_for_visible_with_finder(self): driver = flutter_w3c_driver() diff --git a/test/unit/webdriver/log_events_test.py b/test/unit/webdriver/log_events_test.py index 14d41442e..2469efc39 100644 --- a/test/unit/webdriver/log_events_test.py +++ b/test/unit/webdriver/log_events_test.py @@ -20,7 +20,7 @@ from test.unit.helper.test_helper import appium_command, get_httpretty_request_body, ios_w3c_driver -class TestWebDriverLogEvents(object): +class TestWebDriverLogEvents: @httpretty.activate def test_get_events(self): driver = ios_w3c_driver() @@ -33,7 +33,7 @@ def test_get_events(self): assert events['appium:funEvent'] == [12347] d = get_httpretty_request_body(httpretty.last_request()) - assert 'type' not in d.keys() + assert 'type' not in d @httpretty.activate def test_get_events_args(self): diff --git a/test/unit/webdriver/log_test.py b/test/unit/webdriver/log_test.py index f3b76d351..f7f554bf5 100644 --- a/test/unit/webdriver/log_test.py +++ b/test/unit/webdriver/log_test.py @@ -43,4 +43,4 @@ def test_get_log(): assert log_types == ['logs as array'] d = get_httpretty_request_body(httpretty.last_request()) - assert {'type': 'syslog'} == d + assert d == {'type': 'syslog'} diff --git a/test/unit/webdriver/nativekey_test.py b/test/unit/webdriver/nativekey_test.py index 733f6159b..ba38abe98 100644 --- a/test/unit/webdriver/nativekey_test.py +++ b/test/unit/webdriver/nativekey_test.py @@ -13,7 +13,10 @@ # limitations under the License. -from appium.webdriver.extensions.android.nativekey import AndroidKey +from appium.webdriver.extensions.android.nativekey import ( + AndroidKey, + AndroidKeyMetastate, +) class TestAndroidKey: @@ -23,6 +26,12 @@ def test_has_some_codes(self): assert AndroidKey.CAMERA == 27 assert AndroidKey.SPACE == 62 + def test_has_some_metastates(self): + assert AndroidKeyMetastate.NONE == 0 + assert AndroidKeyMetastate.META_SHIFT_ON == 0x00000001 + assert AndroidKeyMetastate.META_NUM_LOCK_ON == 0x00200000 + assert (AndroidKeyMetastate.META_SHIFT_ON | AndroidKeyMetastate.META_NUM_LOCK_ON) == 0x00000001 | 0x00200000 + def test_is_gamepad_key(self): assert AndroidKey.is_gamepad_button(AndroidKey.BUTTON_8) assert not AndroidKey.is_gamepad_button(250) diff --git a/test/unit/webdriver/network_test.py b/test/unit/webdriver/network_test.py index a9cf7ea9e..cc1938dd3 100644 --- a/test/unit/webdriver/network_test.py +++ b/test/unit/webdriver/network_test.py @@ -20,11 +20,10 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverNetwork(object): +class TestWebDriverNetwork: @httpretty.activate def test_network_connection(self): driver = android_w3c_driver() - httpretty.register_uri(httpretty.GET, appium_command('/session/1234567890/network_connection'), body='{"value": 2}') httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -35,24 +34,20 @@ def test_network_connection(self): @httpretty.activate def test_set_network_connection(self): driver = android_w3c_driver() - httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/network_connection'), body='{"value": ""}') httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": {"wifi": true, "data": false, "airplaneMode": false}}', ) - driver.set_network_connection(2) + assert driver.set_network_connection(2) == 2 - d = get_httpretty_request_body(httpretty.last_request()) + d = get_httpretty_request_body(httpretty.latest_requests()[-4]) + assert d['script'] == 'mobile: setConnectivity' assert d['args'][0]['wifi'] is True @httpretty.activate def test_set_network_speed(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/network_speed'), - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -65,10 +60,6 @@ def test_set_network_speed(self): @httpretty.activate def test_toggle_wifi(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/device/toggle_wifi'), - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), diff --git a/test/unit/webdriver/performance_test.py b/test/unit/webdriver/performance_test.py index d4534c903..c21f720ec 100644 --- a/test/unit/webdriver/performance_test.py +++ b/test/unit/webdriver/performance_test.py @@ -17,15 +17,10 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverPerformance(object): +class TestWebDriverPerformance: @httpretty.activate def test_get_performance_data(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/getPerformanceData'), - body='{"value": [["user", "kernel"], ["2.5", "1.3"]]}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), @@ -34,17 +29,13 @@ def test_get_performance_data(self): assert driver.get_performance_data('my.app.package', 'cpuinfo', 5) == [['user', 'kernel'], ['2.5', '1.3']] d = get_httpretty_request_body(httpretty.last_request()) + assert d['script'] == 'mobile: getPerformanceData' assert d['args'][0]['packageName'] == 'my.app.package' assert d['args'][0]['dataType'] == 'cpuinfo' @httpretty.activate def test_get_performance_data_types(self): driver = android_w3c_driver() - httpretty.register_uri( - httpretty.POST, - appium_command('/session/1234567890/appium/performanceData/types'), - body='{"value": ["cpuinfo", "memoryinfo", "batteryinfo", "networkinfo"]}', - ) httpretty.register_uri( httpretty.POST, appium_command('/session/1234567890/execute/sync'), diff --git a/test/unit/webdriver/screen_record_test.py b/test/unit/webdriver/screen_record_test.py index da470cebf..c56da8c73 100644 --- a/test/unit/webdriver/screen_record_test.py +++ b/test/unit/webdriver/screen_record_test.py @@ -12,7 +12,7 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body, ios_w3c_driver -class TestWebDriverScreenRecordAndroid(object): +class TestWebDriverScreenRecordAndroid: @httpretty.activate def test_start_recording_screen(self): driver = android_w3c_driver() @@ -25,7 +25,7 @@ def test_start_recording_screen(self): d = get_httpretty_request_body(httpretty.last_request()) assert d['options']['user'] == 'userA' assert d['options']['pass'] == '12345' - assert 'password' not in d['options'].keys() + assert 'password' not in d['options'] @httpretty.activate def test_stop_recording_screen(self): @@ -40,10 +40,10 @@ def test_stop_recording_screen(self): d = get_httpretty_request_body(httpretty.last_request()) assert d['options']['user'] == 'userA' assert d['options']['pass'] == '12345' - assert 'password' not in d['options'].keys() + assert 'password' not in d['options'] -class TestWebDriverScreenRecordIOS(object): +class TestWebDriverScreenRecordIOS: @httpretty.activate def test_start_recording_screen(self): driver = ios_w3c_driver() @@ -56,7 +56,7 @@ def test_start_recording_screen(self): d = get_httpretty_request_body(httpretty.last_request()) assert d['options']['user'] == 'userA' assert d['options']['pass'] == '12345' - assert 'password' not in d['options'].keys() + assert 'password' not in d['options'] @httpretty.activate def test_stop_recording_screen(self): @@ -71,4 +71,4 @@ def test_stop_recording_screen(self): d = get_httpretty_request_body(httpretty.last_request()) assert d['options']['user'] == 'userA' assert d['options']['pass'] == '12345' - assert 'password' not in d['options'].keys() + assert 'password' not in d['options'] diff --git a/test/unit/webdriver/search_context/android_test.py b/test/unit/webdriver/search_context/android_test.py index 879d78f53..cab932f22 100644 --- a/test/unit/webdriver/search_context/android_test.py +++ b/test/unit/webdriver/search_context/android_test.py @@ -21,7 +21,7 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverAndroidSearchContext(object): +class TestWebDriverAndroidSearchContext: @httpretty.activate def test_find_element_by_id(self): driver = android_w3c_driver() diff --git a/test/unit/webdriver/search_context/ios_test.py b/test/unit/webdriver/search_context/ios_test.py index d6b288a41..fece30ac2 100644 --- a/test/unit/webdriver/search_context/ios_test.py +++ b/test/unit/webdriver/search_context/ios_test.py @@ -19,7 +19,7 @@ from test.unit.helper.test_helper import appium_command, get_httpretty_request_body, ios_w3c_driver -class TestWebDriverIOSSearchContext(object): +class TestWebDriverIOSSearchContext: @httpretty.activate def test_find_element_by_ios_predicate(self): driver = ios_w3c_driver() diff --git a/test/unit/webdriver/settings_test.py b/test/unit/webdriver/settings_test.py index de9a0e00c..da14fe886 100644 --- a/test/unit/webdriver/settings_test.py +++ b/test/unit/webdriver/settings_test.py @@ -18,7 +18,7 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebDriverSettings(object): +class TestWebDriverSettings: @httpretty.activate def test_get_settings_bool(self): driver = android_w3c_driver() diff --git a/test/unit/webdriver/webdriver_test.py b/test/unit/webdriver/webdriver_test.py index 443885d54..36102735a 100644 --- a/test/unit/webdriver/webdriver_test.py +++ b/test/unit/webdriver/webdriver_test.py @@ -13,10 +13,10 @@ # limitations under the License. import json +from unittest.mock import patch import httpretty import urllib3 -from mock import patch from appium import webdriver from appium.options.android import UiAutomator2Options @@ -132,8 +132,8 @@ def test_create_session_register_uridirect(self): client_config=client_config, ) - assert 'http://localhost2:4800/special/path/wd/hub' == driver.command_executor._client_config.remote_server_addr - assert ['NATIVE_APP', 'CHROMIUM'] == driver.contexts + assert driver.command_executor._client_config.remote_server_addr == 'http://localhost2:4800/special/path/wd/hub' + assert driver.contexts == ['NATIVE_APP', 'CHROMIUM'] assert isinstance(driver.command_executor, AppiumConnection) @httpretty.activate @@ -171,8 +171,8 @@ def test_create_session_register_uridirect_no_direct_connect_path(self): SERVER_URL_BASE, options=UiAutomator2Options().load_capabilities(desired_caps), client_config=client_config ) - assert SERVER_URL_BASE == driver.command_executor._client_config.remote_server_addr - assert ['NATIVE_APP', 'CHROMIUM'] == driver.contexts + assert driver.command_executor._client_config.remote_server_addr == SERVER_URL_BASE + assert driver.contexts == ['NATIVE_APP', 'CHROMIUM'] assert isinstance(driver.command_executor, AppiumConnection) @httpretty.activate @@ -211,7 +211,7 @@ def test_create_session_remote_server_addr_treatment_with_appiumclientconfig(sel client_config=client_config, ) - assert SERVER_URL_BASE == driver.command_executor._client_config.remote_server_addr + assert driver.command_executor._client_config.remote_server_addr == SERVER_URL_BASE assert isinstance(driver.command_executor, AppiumConnection) @httpretty.activate @@ -415,10 +415,10 @@ def test_extention_command_check(self): ) is True ) - assert { + assert get_httpretty_request_body(httpretty.last_request()) == { 'args': [{'component': 'io.appium.android.apis/.accessibility.AccessibilityNodeProviderActivity'}], 'script': 'mobile: startActivity', - } == get_httpretty_request_body(httpretty.last_request()) + } def test_get_client_config_and_connection_with_empty_config(self): command_executor, client_config = _get_remote_connection_and_client_config( @@ -472,7 +472,7 @@ def __init__(self, command_executor, options=None): ) -class TestSubModuleWebDriver(object): +class TestSubModuleWebDriver: def android_w3c_driver(self, driver_class): response_body_json = json.dumps( { diff --git a/test/unit/webdriver/webelement_test.py b/test/unit/webdriver/webelement_test.py index 23268c3ac..a37c2ec68 100644 --- a/test/unit/webdriver/webelement_test.py +++ b/test/unit/webdriver/webelement_test.py @@ -21,7 +21,7 @@ from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body -class TestWebElement(object): +class TestWebElement: @httpretty.activate def test_status(self): driver = android_w3c_driver() @@ -49,15 +49,12 @@ def test_send_key(self): @httpretty.activate def test_send_key_with_file(self): driver = android_w3c_driver() - # Should not send this file - tmp_f = tempfile.NamedTemporaryFile() httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/element/element_id/value')) - try: + # Should not send this file + with tempfile.NamedTemporaryFile() as tmp_f: element = MobileWebElement(driver, 'element_id') element.send_keys(tmp_f.name) - finally: - tmp_f.close() d = get_httpretty_request_body(httpretty.last_request()) assert d['text'] == ''.join(d['value']) diff --git a/uv.lock b/uv.lock index a5996f499..39e8b09c6 100644 --- a/uv.lock +++ b/uv.lock @@ -1,32 +1,16 @@ version = 1 revision = 3 -requires-python = ">=3.9" +requires-python = ">=3.10" resolution-markers = [ - "python_full_version >= '3.11'", - "python_full_version == '3.10.*'", - "python_full_version < '3.10'", -] - -[[package]] -name = "alabaster" -version = "0.7.16" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/3e/13dd8e5ed9094e734ac430b5d0eb4f2bb001708a8b7856cbf8e084e001ba/alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65", size = 23776, upload-time = "2024-01-10T00:56:10.189Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/34/d4e1c02d3bee589efb5dfa17f88ea08bdb3e3eac12bc475462aec52ed223/alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92", size = 13511, upload-time = "2024-01-10T00:56:08.388Z" }, + "python_full_version >= '3.15'", + "python_full_version >= '3.11' and python_full_version < '3.15'", + "python_full_version < '3.11'", ] [[package]] name = "alabaster" version = "1.0.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.11'", - "python_full_version == '3.10.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, @@ -43,7 +27,7 @@ wheels = [ [[package]] name = "appium-python-client" -version = "5.2.3" +version = "6.0.0" source = { editable = "." } dependencies = [ { name = "selenium" }, @@ -62,8 +46,7 @@ dev = [ { name = "python-dateutil" }, { name = "python-semantic-release" }, { name = "ruff" }, - { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx-rtd-theme" }, { name = "sphinxcontrib-apidoc" }, @@ -72,35 +55,76 @@ dev = [ [package.metadata] requires-dist = [ - { name = "selenium", specifier = ">=4.26,<5.0" }, - { name = "typing-extensions", specifier = "~=4.13" }, + { name = "selenium", specifier = ">=4.37.0,<5.0" }, + { name = "typing-extensions", specifier = "~=4.16" }, ] [package.metadata.requires-dev] dev = [ { name = "httpretty", specifier = "~=1.1" }, { name = "mock", specifier = "~=5.2" }, - { name = "mypy", specifier = "~=1.17" }, - { name = "pre-commit", specifier = "~=4.2" }, - { name = "pytest", specifier = "~=8.4" }, - { name = "pytest-cov", specifier = "~=6.2" }, + { name = "mypy", specifier = ">=1.17,<3.0" }, + { name = "pre-commit", specifier = "~=4.6" }, + { name = "pytest", specifier = ">=8.4,<10.0" }, + { name = "pytest-cov", specifier = ">=6.2,<8.0" }, { name = "pytest-xdist", specifier = "~=3.8" }, { name = "python-dateutil", specifier = "~=2.9" }, - { name = "python-semantic-release", specifier = "~=10.3.1" }, - { name = "ruff", specifier = "~=0.12" }, + { name = "python-semantic-release", specifier = ">=10.3.1,<10.7.0" }, + { name = "ruff", specifier = "~=0.16" }, { name = "sphinx", specifier = ">=4.0,<9.0" }, { name = "sphinx-rtd-theme", specifier = "~=3.0" }, { name = "sphinxcontrib-apidoc", specifier = "~=0.6" }, { name = "types-python-dateutil", specifier = "~=2.9" }, ] +[[package]] +name = "ast-serialize" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/ad/0d70a3a2d6e01968d985415259e8ec7ad3f777903f9b1c1f3c8c44642c60/ast_serialize-0.6.0.tar.gz", hash = "sha256:aadd3ffcf4858c9726bf3515f7b199c7eadbe504f96028e4a87172c0da65a8fe", size = 61489, upload-time = "2026-06-30T20:02:55.555Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/12/3e5f575f156555547c250a8b0d1347517a3a20fc7f4492e9703a69d4f45e/ast_serialize-0.6.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:a7520b672827885bafeae7501f684d14d47d17e5f45256f9df547686cca52264", size = 1177640, upload-time = "2026-06-30T20:02:06.708Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a4/921a9e27951627983b0f368859ea00f8330a551dc0bf4c2fdcb11855a98b/ast_serialize-0.6.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a14191beec7e0c078d2fc1f6edc0aee88bcd4db9f18e1bc9f8052b559c22dddc", size = 1168111, upload-time = "2026-06-30T20:02:08.366Z" }, + { url = "https://files.pythonhosted.org/packages/00/69/950cf404de7b8782cf95e5c1237e25e2aa46177b287f39f9eeddf481fd6f/ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32ef62ec34cf6be20ad77d4799556638fbdf187f3ae10698dfb20ef9f2c89516", size = 1227656, upload-time = "2026-06-30T20:02:09.843Z" }, + { url = "https://files.pythonhosted.org/packages/4c/a8/46f8f6a6479d9d2273980957bb091a506c55f5b95d3c029ee58518a78407/ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13b7769970a39983b0adf2f38917b1cd3b8946f76df045756c3d741bc689f089", size = 1227706, upload-time = "2026-06-30T20:02:11.367Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b9/9ac415bda0a40e49eab8fea3b2741c19c98bb84d57d62c4cfc6230eb67be/ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f7a408601bb3edaefb3bc67a4c01f5235e3253653b6a5729a2ee2382b35341c", size = 1431705, upload-time = "2026-06-30T20:02:12.737Z" }, + { url = "https://files.pythonhosted.org/packages/e5/06/8807115d441444879f7561b5eede5ac18fc80392f11826d61ccf31f503b1/ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8670bfa51208a2c0c8d138928e40e998fab158f9200d53bb80c088b5b8eda7b8", size = 1249533, upload-time = "2026-06-30T20:02:14.571Z" }, + { url = "https://files.pythonhosted.org/packages/3e/c0/c2ba82ef9618650357d9421a1fdb27ffec862a7f57e8e2de82a3ccd11e12/ast_serialize-0.6.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4826809eb8597a8cd59fd924b6d7c285b8969a1e0007e2cb652cab62376270f", size = 1252619, upload-time = "2026-06-30T20:02:16.219Z" }, + { url = "https://files.pythonhosted.org/packages/0f/a7/fa31d52dd4102cede29fb9634e98d214129b2783b4f95528c6dc6a8f6587/ast_serialize-0.6.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:577a6c189068686869f5f1ddc38363f3ae1808a4753b577266f9202071a7bb66", size = 1242983, upload-time = "2026-06-30T20:02:17.813Z" }, + { url = "https://files.pythonhosted.org/packages/b1/20/ddf742b5ad3c4bafd3466f2265037cfd99bc1b9a5ee46a5d58c90d523242/ast_serialize-0.6.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:085de7f62dc9cc247eb01e965a362707d1d90b1d89a82c5bf78301a60a3c417b", size = 1296148, upload-time = "2026-06-30T20:02:19.146Z" }, + { url = "https://files.pythonhosted.org/packages/24/cb/9f6f217cce8b3b632c5568b478d195a35e79dce4dbe309438cb89ba6ea4f/ast_serialize-0.6.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:9f8a8b78b13173de6a9ec22111d9be674874cd5bdccda04f14ae5ebc2bef403a", size = 1403826, upload-time = "2026-06-30T20:02:20.696Z" }, + { url = "https://files.pythonhosted.org/packages/2d/f8/9d16d4f0107a183924425cc0e7618d8bf76f96b45afa9ff19f924ed1ad57/ast_serialize-0.6.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:f2ff3baffc3a29c1f15bc9098aa0c09763410262d5e6cef42116f7356c184554", size = 1502943, upload-time = "2026-06-30T20:02:22.034Z" }, + { url = "https://files.pythonhosted.org/packages/80/dd/bbc1c38756350dddf7e24acae1c9482ef42051c267417e019aecc1ed4075/ast_serialize-0.6.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0067b25fce104eaae5b88383de9ab803faeb671831e14ca698b771b356e2600f", size = 1497632, upload-time = "2026-06-30T20:02:23.517Z" }, + { url = "https://files.pythonhosted.org/packages/42/7e/9daffefcf5b97e6bb4c3e0b3c024c1aee9722f23d3cf7cd2ff80d6fb4a40/ast_serialize-0.6.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c617417f9cbb0cb144f6283c3cbe0d2e0f01beaf9f608f662b21191058a626ec", size = 1448858, upload-time = "2026-06-30T20:02:24.889Z" }, + { url = "https://files.pythonhosted.org/packages/e5/1f/f9baaab81a677ea0af7d2458cac2f94ebcc85958f8a3c15ba9d9e5dab653/ast_serialize-0.6.0-cp314-cp314t-win32.whl", hash = "sha256:5337cb256dcea3df9288205213d1601581536526b8f4da44b6974f1180f3252a", size = 1052600, upload-time = "2026-06-30T20:02:26.263Z" }, + { url = "https://files.pythonhosted.org/packages/9e/1f/41b535866519512d8cf6669cb2cff7823b7672bb6279c0333b4ff89d7d9f/ast_serialize-0.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2d947e45cafc4b09bd7528917fa84c517654a43de173c79785574b7b3068ac24", size = 1095570, upload-time = "2026-06-30T20:02:27.639Z" }, + { url = "https://files.pythonhosted.org/packages/50/64/e472fe3e3a2d33d874b987e8518aedf24562919e3b6161a4fa1797e89c0f/ast_serialize-0.6.0-cp314-cp314t-win_arm64.whl", hash = "sha256:6e15ec740436e1a0d62de848641abe5f3a2f89a7f94907d534795ac91bbacf14", size = 1067267, upload-time = "2026-06-30T20:02:28.949Z" }, + { url = "https://files.pythonhosted.org/packages/52/19/ac8348ae8711c9b5ae834634f635780cab62a0f5e6f988882e048b89c2ae/ast_serialize-0.6.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:093cb8bb91b720d8523580498d031791bb1bbaa048599c3d21085d380e11a596", size = 1185367, upload-time = "2026-06-30T20:02:30.427Z" }, + { url = "https://files.pythonhosted.org/packages/c1/f6/ec7ec652c51db77c2f61d8573338e13e4704303265ccc658cb4031d9f354/ast_serialize-0.6.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:e61580a69faf47e3689795367ed211f2a10fd741478cc0f36a0f128793360aad", size = 1178657, upload-time = "2026-06-30T20:02:31.964Z" }, + { url = "https://files.pythonhosted.org/packages/6f/02/613a7534a41d0122f37d1e0c64aa8ac78bfb831f8c92f6db057a311abb3c/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:305802f2ce2a7c4e87835078ea85c58b586ddda8095b92fe2ead9364ae19c80a", size = 1238620, upload-time = "2026-06-30T20:02:33.664Z" }, + { url = "https://files.pythonhosted.org/packages/4d/21/087957bba486242afc52f49b2d9e21c9dad00289356cf9efe67084015a9d/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c7b8b8f0c42f752ea00b2b7d7c090b3f80d9c1c5c75cadf16423790a0cc74081", size = 1236075, upload-time = "2026-06-30T20:02:34.936Z" }, + { url = "https://files.pythonhosted.org/packages/82/04/78128bbb170071c2c72a210a181f1c00e11cc1cec60a8beef747b07f9201/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd5b91b9e6f2356ace3a556963b0cd783b395fbbb0bb17b4defc283415466e77", size = 1441348, upload-time = "2026-06-30T20:02:36.245Z" }, + { url = "https://files.pythonhosted.org/packages/64/64/62fb99d6faf199b4c3e5b08a07136e9a0d7664bb249c6de3670e5b63e9b6/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d6ef91590258ada18909b9caea344dac4de2013906b035473cd674a43f4b790", size = 1258580, upload-time = "2026-06-30T20:02:37.53Z" }, + { url = "https://files.pythonhosted.org/packages/ca/87/b4d6c38e0ccd5e85dc54cecdf933a152c60b28fe5d993a6d8a72fa6d5896/ast_serialize-0.6.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcbed41e9386059fc0261d602445ede0976c2ecec2939688bcbcb9ed0b6f28b7", size = 1261693, upload-time = "2026-06-30T20:02:39.123Z" }, + { url = "https://files.pythonhosted.org/packages/0e/4b/3676ca2191f39bafb75f93f99b2f429ec464586158fece2165f3572805dc/ast_serialize-0.6.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:cdc4e6f930b9090c2f92c9036ad12ffb8e6e44d4a5ba06f1458a05d60f203f7b", size = 1252517, upload-time = "2026-06-30T20:02:40.511Z" }, + { url = "https://files.pythonhosted.org/packages/f3/58/494ef8c4b4acb2f4a265ac934caf45f792a08fe27d6b853de35ad991941a/ast_serialize-0.6.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:897ac47b5637be41c0c07061c8a912fafa967ef1dc73fa115e4bfa70882a093b", size = 1304843, upload-time = "2026-06-30T20:02:41.961Z" }, + { url = "https://files.pythonhosted.org/packages/b1/f2/13736d920ab3d49bbee80ef1a277dd7b7aaf3b3545efd9d2a8114fe05525/ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c4af9a1386166e40ed01464991806f89038a2d89782576c7774876fa77034e32", size = 1413698, upload-time = "2026-06-30T20:02:44.179Z" }, + { url = "https://files.pythonhosted.org/packages/a8/5a/e046f3899e2acba4677d7427b76431443a1aa1a0e583dfb05b55b69d55cf/ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:c901adbd750029b9ac4ad3d6aa56853e0ad4875119fbf52b7b8298afc223828b", size = 1512209, upload-time = "2026-06-30T20:02:45.584Z" }, + { url = "https://files.pythonhosted.org/packages/cc/c7/e42aaca7bb2d22a7c06d5a8c7930086c5a334e93d716e6fa5e6647a4515f/ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:3ae22a366b752ab4496191525b78b097b5b72d531752e3c1dd7e383a8f2c8a1a", size = 1508464, upload-time = "2026-06-30T20:02:46.942Z" }, + { url = "https://files.pythonhosted.org/packages/95/93/5524a3dc6c3f593de3228ed9cbef73afa047625b7000ec21b7f58e6eb4d4/ast_serialize-0.6.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4ed29121da8b3fdc291002801a1de0f76248fa07dce89157a5f277842cf6126e", size = 1457164, upload-time = "2026-06-30T20:02:48.294Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c0/36a6ffb4d653cf621427b4c4928671f53ad800c453474de2b82564a44ad9/ast_serialize-0.6.0-cp39-abi3-pyemscripten_2026_0_wasm32.whl", hash = "sha256:b1dac4e09d341c1300ba69cdcbe62867b32a8c75d90db9bf4d083bec3b039f0b", size = 863014, upload-time = "2026-06-30T20:02:49.742Z" }, + { url = "https://files.pythonhosted.org/packages/09/c7/7d5ad8b49e1278e1c2a1e0274bd7850560b3f09313aa00c13bc8d5544792/ast_serialize-0.6.0-cp39-abi3-win32.whl", hash = "sha256:82c312a7844d2fdeb4d5c48bd3d215bf940dafd4704e1a9bcf252a99010a99b1", size = 1063165, upload-time = "2026-06-30T20:02:50.98Z" }, + { url = "https://files.pythonhosted.org/packages/47/ae/6710c14ecb276031cf10249f6adf5a59e2d3fdb3b5183bd59f70524067ee/ast_serialize-0.6.0-cp39-abi3-win_amd64.whl", hash = "sha256:113b58346f9ceb664352032770caca817d4a3c86f611c6088e6ef65ddaa70f0e", size = 1101444, upload-time = "2026-06-30T20:02:52.554Z" }, + { url = "https://files.pythonhosted.org/packages/66/40/c53deb2cd0c9b0fb636d24d9f40924cf2e65028e6b20b10cd5c1eeb2c730/ast_serialize-0.6.0-cp39-abi3-win_arm64.whl", hash = "sha256:ccd132fe8db56f61fe743b1f644d01b8d65b83248a8da506f3132bda86d6ed5e", size = 1072965, upload-time = "2026-06-30T20:02:54.097Z" }, +] + [[package]] name = "attrs" -version = "25.3.0" +version = "25.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, ] [[package]] @@ -114,116 +138,137 @@ wheels = [ [[package]] name = "certifi" -version = "2025.8.3" +version = "2026.6.17" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, + { url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" }, ] [[package]] name = "cffi" -version = "1.17.1" +version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804, upload-time = "2024-09-04T20:43:48.186Z" }, - { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299, upload-time = "2024-09-04T20:43:49.812Z" }, - { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727, upload-time = "2024-09-04T20:44:09.481Z" }, - { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400, upload-time = "2024-09-04T20:44:10.873Z" }, - { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, - { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, - { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" }, - { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, - { url = "https://files.pythonhosted.org/packages/cb/b5/fd9f8b5a84010ca169ee49f4e4ad6f8c05f4e3545b72ee041dbbcb159882/cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", size = 171820, upload-time = "2024-09-04T20:45:18.762Z" }, - { url = "https://files.pythonhosted.org/packages/8c/52/b08750ce0bce45c143e1b5d7357ee8c55341b52bdef4b0f081af1eb248c2/cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", size = 181290, upload-time = "2024-09-04T20:45:20.226Z" }, + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/cc/027d7fb82e58c48ea717149b03bcadcbdc293553edb283af792bd4bcbb3f/cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", size = 172184, upload-time = "2025-09-08T23:22:23.328Z" }, + { url = "https://files.pythonhosted.org/packages/33/fa/072dd15ae27fbb4e06b437eb6e944e75b068deb09e2a2826039e49ee2045/cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", size = 182790, upload-time = "2025-09-08T23:22:24.752Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, ] [[package]] name = "cfgv" -version = "3.4.0" +version = "3.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, + { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, ] [[package]] name = "charset-normalizer" -version = "3.4.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/98/f3b8013223728a99b908c9344da3aa04ee6e3fa235f19409033eda92fb78/charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72", size = 207695, upload-time = "2025-08-09T07:55:36.452Z" }, - { url = "https://files.pythonhosted.org/packages/21/40/5188be1e3118c82dcb7c2a5ba101b783822cfb413a0268ed3be0468532de/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe", size = 147153, upload-time = "2025-08-09T07:55:38.467Z" }, - { url = "https://files.pythonhosted.org/packages/37/60/5d0d74bc1e1380f0b72c327948d9c2aca14b46a9efd87604e724260f384c/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601", size = 160428, upload-time = "2025-08-09T07:55:40.072Z" }, - { url = "https://files.pythonhosted.org/packages/85/9a/d891f63722d9158688de58d050c59dc3da560ea7f04f4c53e769de5140f5/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c", size = 157627, upload-time = "2025-08-09T07:55:41.706Z" }, - { url = "https://files.pythonhosted.org/packages/65/1a/7425c952944a6521a9cfa7e675343f83fd82085b8af2b1373a2409c683dc/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2", size = 152388, upload-time = "2025-08-09T07:55:43.262Z" }, - { url = "https://files.pythonhosted.org/packages/f0/c9/a2c9c2a355a8594ce2446085e2ec97fd44d323c684ff32042e2a6b718e1d/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0", size = 150077, upload-time = "2025-08-09T07:55:44.903Z" }, - { url = "https://files.pythonhosted.org/packages/3b/38/20a1f44e4851aa1c9105d6e7110c9d020e093dfa5836d712a5f074a12bf7/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0", size = 161631, upload-time = "2025-08-09T07:55:46.346Z" }, - { url = "https://files.pythonhosted.org/packages/a4/fa/384d2c0f57edad03d7bec3ebefb462090d8905b4ff5a2d2525f3bb711fac/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0", size = 159210, upload-time = "2025-08-09T07:55:47.539Z" }, - { url = "https://files.pythonhosted.org/packages/33/9e/eca49d35867ca2db336b6ca27617deed4653b97ebf45dfc21311ce473c37/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a", size = 153739, upload-time = "2025-08-09T07:55:48.744Z" }, - { url = "https://files.pythonhosted.org/packages/2a/91/26c3036e62dfe8de8061182d33be5025e2424002125c9500faff74a6735e/charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f", size = 99825, upload-time = "2025-08-09T07:55:50.305Z" }, - { url = "https://files.pythonhosted.org/packages/e2/c6/f05db471f81af1fa01839d44ae2a8bfeec8d2a8b4590f16c4e7393afd323/charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669", size = 107452, upload-time = "2025-08-09T07:55:51.461Z" }, - { url = "https://files.pythonhosted.org/packages/7f/b5/991245018615474a60965a7c9cd2b4efbaabd16d582a5547c47ee1c7730b/charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b", size = 204483, upload-time = "2025-08-09T07:55:53.12Z" }, - { url = "https://files.pythonhosted.org/packages/c7/2a/ae245c41c06299ec18262825c1569c5d3298fc920e4ddf56ab011b417efd/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64", size = 145520, upload-time = "2025-08-09T07:55:54.712Z" }, - { url = "https://files.pythonhosted.org/packages/3a/a4/b3b6c76e7a635748c4421d2b92c7b8f90a432f98bda5082049af37ffc8e3/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91", size = 158876, upload-time = "2025-08-09T07:55:56.024Z" }, - { url = "https://files.pythonhosted.org/packages/e2/e6/63bb0e10f90a8243c5def74b5b105b3bbbfb3e7bb753915fe333fb0c11ea/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f", size = 156083, upload-time = "2025-08-09T07:55:57.582Z" }, - { url = "https://files.pythonhosted.org/packages/87/df/b7737ff046c974b183ea9aa111b74185ac8c3a326c6262d413bd5a1b8c69/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07", size = 150295, upload-time = "2025-08-09T07:55:59.147Z" }, - { url = "https://files.pythonhosted.org/packages/61/f1/190d9977e0084d3f1dc169acd060d479bbbc71b90bf3e7bf7b9927dec3eb/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30", size = 148379, upload-time = "2025-08-09T07:56:00.364Z" }, - { url = "https://files.pythonhosted.org/packages/4c/92/27dbe365d34c68cfe0ca76f1edd70e8705d82b378cb54ebbaeabc2e3029d/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14", size = 160018, upload-time = "2025-08-09T07:56:01.678Z" }, - { url = "https://files.pythonhosted.org/packages/99/04/baae2a1ea1893a01635d475b9261c889a18fd48393634b6270827869fa34/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c", size = 157430, upload-time = "2025-08-09T07:56:02.87Z" }, - { url = "https://files.pythonhosted.org/packages/2f/36/77da9c6a328c54d17b960c89eccacfab8271fdaaa228305330915b88afa9/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae", size = 151600, upload-time = "2025-08-09T07:56:04.089Z" }, - { url = "https://files.pythonhosted.org/packages/64/d4/9eb4ff2c167edbbf08cdd28e19078bf195762e9bd63371689cab5ecd3d0d/charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849", size = 99616, upload-time = "2025-08-09T07:56:05.658Z" }, - { url = "https://files.pythonhosted.org/packages/f4/9c/996a4a028222e7761a96634d1820de8a744ff4327a00ada9c8942033089b/charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c", size = 107108, upload-time = "2025-08-09T07:56:07.176Z" }, - { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655, upload-time = "2025-08-09T07:56:08.475Z" }, - { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223, upload-time = "2025-08-09T07:56:09.708Z" }, - { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366, upload-time = "2025-08-09T07:56:11.326Z" }, - { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104, upload-time = "2025-08-09T07:56:13.014Z" }, - { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830, upload-time = "2025-08-09T07:56:14.428Z" }, - { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854, upload-time = "2025-08-09T07:56:16.051Z" }, - { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670, upload-time = "2025-08-09T07:56:17.314Z" }, - { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501, upload-time = "2025-08-09T07:56:18.641Z" }, - { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173, upload-time = "2025-08-09T07:56:20.289Z" }, - { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822, upload-time = "2025-08-09T07:56:21.551Z" }, - { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543, upload-time = "2025-08-09T07:56:23.115Z" }, - { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326, upload-time = "2025-08-09T07:56:24.721Z" }, - { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008, upload-time = "2025-08-09T07:56:26.004Z" }, - { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196, upload-time = "2025-08-09T07:56:27.25Z" }, - { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819, upload-time = "2025-08-09T07:56:28.515Z" }, - { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350, upload-time = "2025-08-09T07:56:29.716Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644, upload-time = "2025-08-09T07:56:30.984Z" }, - { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468, upload-time = "2025-08-09T07:56:32.252Z" }, - { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187, upload-time = "2025-08-09T07:56:33.481Z" }, - { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699, upload-time = "2025-08-09T07:56:34.739Z" }, - { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580, upload-time = "2025-08-09T07:56:35.981Z" }, - { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366, upload-time = "2025-08-09T07:56:37.339Z" }, - { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342, upload-time = "2025-08-09T07:56:38.687Z" }, - { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995, upload-time = "2025-08-09T07:56:40.048Z" }, - { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640, upload-time = "2025-08-09T07:56:41.311Z" }, - { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636, upload-time = "2025-08-09T07:56:43.195Z" }, - { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939, upload-time = "2025-08-09T07:56:44.819Z" }, - { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580, upload-time = "2025-08-09T07:56:46.684Z" }, - { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870, upload-time = "2025-08-09T07:56:47.941Z" }, - { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797, upload-time = "2025-08-09T07:56:49.756Z" }, - { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" }, - { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" }, - { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ca/9a0983dd5c8e9733565cf3db4df2b0a2e9a82659fd8aa2a868ac6e4a991f/charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05", size = 207520, upload-time = "2025-08-09T07:57:11.026Z" }, - { url = "https://files.pythonhosted.org/packages/39/c6/99271dc37243a4f925b09090493fb96c9333d7992c6187f5cfe5312008d2/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e", size = 147307, upload-time = "2025-08-09T07:57:12.4Z" }, - { url = "https://files.pythonhosted.org/packages/e4/69/132eab043356bba06eb333cc2cc60c6340857d0a2e4ca6dc2b51312886b3/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99", size = 160448, upload-time = "2025-08-09T07:57:13.712Z" }, - { url = "https://files.pythonhosted.org/packages/04/9a/914d294daa4809c57667b77470533e65def9c0be1ef8b4c1183a99170e9d/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7", size = 157758, upload-time = "2025-08-09T07:57:14.979Z" }, - { url = "https://files.pythonhosted.org/packages/b0/a8/6f5bcf1bcf63cb45625f7c5cadca026121ff8a6c8a3256d8d8cd59302663/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7", size = 152487, upload-time = "2025-08-09T07:57:16.332Z" }, - { url = "https://files.pythonhosted.org/packages/c4/72/d3d0e9592f4e504f9dea08b8db270821c909558c353dc3b457ed2509f2fb/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19", size = 150054, upload-time = "2025-08-09T07:57:17.576Z" }, - { url = "https://files.pythonhosted.org/packages/20/30/5f64fe3981677fe63fa987b80e6c01042eb5ff653ff7cec1b7bd9268e54e/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312", size = 161703, upload-time = "2025-08-09T07:57:20.012Z" }, - { url = "https://files.pythonhosted.org/packages/e1/ef/dd08b2cac9284fd59e70f7d97382c33a3d0a926e45b15fc21b3308324ffd/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc", size = 159096, upload-time = "2025-08-09T07:57:21.329Z" }, - { url = "https://files.pythonhosted.org/packages/45/8c/dcef87cfc2b3f002a6478f38906f9040302c68aebe21468090e39cde1445/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34", size = 153852, upload-time = "2025-08-09T07:57:22.608Z" }, - { url = "https://files.pythonhosted.org/packages/63/86/9cbd533bd37883d467fcd1bd491b3547a3532d0fbb46de2b99feeebf185e/charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432", size = 99840, upload-time = "2025-08-09T07:57:23.883Z" }, - { url = "https://files.pythonhosted.org/packages/ce/d6/7e805c8e5c46ff9729c49950acc4ee0aeb55efb8b3a56687658ad10c3216/charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca", size = 107438, upload-time = "2025-08-09T07:57:25.287Z" }, - { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" }, +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/b8/6d51fc1d52cbd52cd4ccedd5b5b2f0f6a11bbf6765c782298b0f3e808541/charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d", size = 209709, upload-time = "2025-10-14T04:40:11.385Z" }, + { url = "https://files.pythonhosted.org/packages/5c/af/1f9d7f7faafe2ddfb6f72a2e07a548a629c61ad510fe60f9630309908fef/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8", size = 148814, upload-time = "2025-10-14T04:40:13.135Z" }, + { url = "https://files.pythonhosted.org/packages/79/3d/f2e3ac2bbc056ca0c204298ea4e3d9db9b4afe437812638759db2c976b5f/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad", size = 144467, upload-time = "2025-10-14T04:40:14.728Z" }, + { url = "https://files.pythonhosted.org/packages/ec/85/1bf997003815e60d57de7bd972c57dc6950446a3e4ccac43bc3070721856/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8", size = 162280, upload-time = "2025-10-14T04:40:16.14Z" }, + { url = "https://files.pythonhosted.org/packages/3e/8e/6aa1952f56b192f54921c436b87f2aaf7c7a7c3d0d1a765547d64fd83c13/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d", size = 159454, upload-time = "2025-10-14T04:40:17.567Z" }, + { url = "https://files.pythonhosted.org/packages/36/3b/60cbd1f8e93aa25d1c669c649b7a655b0b5fb4c571858910ea9332678558/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313", size = 153609, upload-time = "2025-10-14T04:40:19.08Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/6a13396948b8fd3c4b4fd5bc74d045f5637d78c9675585e8e9fbe5636554/charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e", size = 151849, upload-time = "2025-10-14T04:40:20.607Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7a/59482e28b9981d105691e968c544cc0df3b7d6133152fb3dcdc8f135da7a/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93", size = 151586, upload-time = "2025-10-14T04:40:21.719Z" }, + { url = "https://files.pythonhosted.org/packages/92/59/f64ef6a1c4bdd2baf892b04cd78792ed8684fbc48d4c2afe467d96b4df57/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0", size = 145290, upload-time = "2025-10-14T04:40:23.069Z" }, + { url = "https://files.pythonhosted.org/packages/6b/63/3bf9f279ddfa641ffa1962b0db6a57a9c294361cc2f5fcac997049a00e9c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84", size = 163663, upload-time = "2025-10-14T04:40:24.17Z" }, + { url = "https://files.pythonhosted.org/packages/ed/09/c9e38fc8fa9e0849b172b581fd9803bdf6e694041127933934184e19f8c3/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e", size = 151964, upload-time = "2025-10-14T04:40:25.368Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d1/d28b747e512d0da79d8b6a1ac18b7ab2ecfd81b2944c4c710e166d8dd09c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db", size = 161064, upload-time = "2025-10-14T04:40:26.806Z" }, + { url = "https://files.pythonhosted.org/packages/bb/9a/31d62b611d901c3b9e5500c36aab0ff5eb442043fb3a1c254200d3d397d9/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6", size = 155015, upload-time = "2025-10-14T04:40:28.284Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/107e008fa2bff0c8b9319584174418e5e5285fef32f79d8ee6a430d0039c/charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f", size = 99792, upload-time = "2025-10-14T04:40:29.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/66/e396e8a408843337d7315bab30dbf106c38966f1819f123257f5520f8a96/charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d", size = 107198, upload-time = "2025-10-14T04:40:30.644Z" }, + { url = "https://files.pythonhosted.org/packages/b5/58/01b4f815bf0312704c267f2ccb6e5d42bcc7752340cd487bc9f8c3710597/charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69", size = 100262, upload-time = "2025-10-14T04:40:32.108Z" }, + { url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" }, + { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" }, + { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" }, + { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" }, + { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" }, + { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" }, + { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" }, + { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" }, + { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" }, + { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" }, + { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" }, + { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" }, + { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" }, + { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" }, + { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" }, + { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, + { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, + { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, + { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, + { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, + { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, ] [[package]] @@ -240,14 +285,14 @@ wheels = [ [[package]] name = "click-option-group" -version = "0.5.7" +version = "0.5.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/9f/1f917934da4e07ae7715a982347e3c2179556d8a58d1108c5da3e8f09c76/click_option_group-0.5.7.tar.gz", hash = "sha256:8dc780be038712fc12c9fecb3db4fe49e0d0723f9c171d7cda85c20369be693c", size = 22110, upload-time = "2025-03-24T13:24:55.897Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ef/ff/d291d66595b30b83d1cb9e314b2c9be7cfc7327d4a0d40a15da2416ea97b/click_option_group-0.5.9.tar.gz", hash = "sha256:f94ed2bc4cf69052e0f29592bd1e771a1789bd7bfc482dd0bc482134aff95823", size = 22222, upload-time = "2025-10-09T09:38:01.474Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/27/bf74dc1494625c3b14dbcdb93740defd7b8c58dae3736be8d264f2a643fb/click_option_group-0.5.7-py3-none-any.whl", hash = "sha256:96b9f52f397ef4d916f81929bd6c1f85e89046c7a401a64e72a61ae74ad35c24", size = 11483, upload-time = "2025-03-24T13:24:54.611Z" }, + { url = "https://files.pythonhosted.org/packages/75/45/54bb2d8d4138964a94bef6e9afe48b0be4705ba66ac442ae7d8a8dc4ffef/click_option_group-0.5.9-py3-none-any.whl", hash = "sha256:ad2599248bd373e2e19bec5407967c3eec1d0d4fc4a5e77b08a0481e75991080", size = 11553, upload-time = "2025-10-09T09:38:00.066Z" }, ] [[package]] @@ -261,97 +306,101 @@ wheels = [ [[package]] name = "coverage" -version = "7.10.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/76/17780846fc7aade1e66712e1e27dd28faa0a5d987a1f433610974959eaa8/coverage-7.10.2.tar.gz", hash = "sha256:5d6e6d84e6dd31a8ded64759626627247d676a23c1b892e1326f7c55c8d61055", size = 820754, upload-time = "2025-08-04T00:35:17.511Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d8/5f/5ce748ab3f142593698aff5f8a0cf020775aa4e24b9d8748b5a56b64d3f8/coverage-7.10.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:79f0283ab5e6499fd5fe382ca3d62afa40fb50ff227676a3125d18af70eabf65", size = 215003, upload-time = "2025-08-04T00:33:02.977Z" }, - { url = "https://files.pythonhosted.org/packages/f4/ed/507088561217b000109552139802fa99c33c16ad19999c687b601b3790d0/coverage-7.10.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4545e906f595ee8ab8e03e21be20d899bfc06647925bc5b224ad7e8c40e08b8", size = 215391, upload-time = "2025-08-04T00:33:05.645Z" }, - { url = "https://files.pythonhosted.org/packages/79/1b/0f496259fe137c4c5e1e8eaff496fb95af88b71700f5e57725a4ddbe742b/coverage-7.10.2-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:ae385e1d58fbc6a9b1c315e5510ac52281e271478b45f92ca9b5ad42cf39643f", size = 242367, upload-time = "2025-08-04T00:33:07.189Z" }, - { url = "https://files.pythonhosted.org/packages/b9/8e/5a8835fb0122a2e2a108bf3527931693c4625fdc4d953950a480b9625852/coverage-7.10.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6f0cbe5f7dd19f3a32bac2251b95d51c3b89621ac88a2648096ce40f9a5aa1e7", size = 243627, upload-time = "2025-08-04T00:33:08.809Z" }, - { url = "https://files.pythonhosted.org/packages/c3/96/6a528429c2e0e8d85261764d0cd42e51a429510509bcc14676ee5d1bb212/coverage-7.10.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fd17f427f041f6b116dc90b4049c6f3e1230524407d00daa2d8c7915037b5947", size = 245485, upload-time = "2025-08-04T00:33:10.29Z" }, - { url = "https://files.pythonhosted.org/packages/bf/82/1fba935c4d02c33275aca319deabf1f22c0f95f2c0000bf7c5f276d6f7b4/coverage-7.10.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7f10ca4cde7b466405cce0a0e9971a13eb22e57a5ecc8b5f93a81090cc9c7eb9", size = 243429, upload-time = "2025-08-04T00:33:11.909Z" }, - { url = "https://files.pythonhosted.org/packages/fc/a8/c8dc0a57a729fc93be33ab78f187a8f52d455fa8f79bfb379fe23b45868d/coverage-7.10.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3b990df23dd51dccce26d18fb09fd85a77ebe46368f387b0ffba7a74e470b31b", size = 242104, upload-time = "2025-08-04T00:33:13.467Z" }, - { url = "https://files.pythonhosted.org/packages/b9/6f/0b7da1682e2557caeed299a00897b42afde99a241a01eba0197eb982b90f/coverage-7.10.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc3902584d25c7eef57fb38f440aa849a26a3a9f761a029a72b69acfca4e31f8", size = 242397, upload-time = "2025-08-04T00:33:14.682Z" }, - { url = "https://files.pythonhosted.org/packages/2d/e4/54dc833dadccd519c04a28852f39a37e522bad35d70cfe038817cdb8f168/coverage-7.10.2-cp310-cp310-win32.whl", hash = "sha256:9dd37e9ac00d5eb72f38ed93e3cdf2280b1dbda3bb9b48c6941805f265ad8d87", size = 217502, upload-time = "2025-08-04T00:33:16.254Z" }, - { url = "https://files.pythonhosted.org/packages/c3/e7/2f78159c4c127549172f427dff15b02176329327bf6a6a1fcf1f603b5456/coverage-7.10.2-cp310-cp310-win_amd64.whl", hash = "sha256:99d16f15cb5baf0729354c5bd3080ae53847a4072b9ba1e10957522fb290417f", size = 218388, upload-time = "2025-08-04T00:33:17.4Z" }, - { url = "https://files.pythonhosted.org/packages/6e/53/0125a6fc0af4f2687b4e08b0fb332cd0d5e60f3ca849e7456f995d022656/coverage-7.10.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c3b210d79925a476dfc8d74c7d53224888421edebf3a611f3adae923e212b27", size = 215119, upload-time = "2025-08-04T00:33:19.101Z" }, - { url = "https://files.pythonhosted.org/packages/0e/2e/960d9871de9152dbc9ff950913c6a6e9cf2eb4cc80d5bc8f93029f9f2f9f/coverage-7.10.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bf67d1787cd317c3f8b2e4c6ed1ae93497be7e30605a0d32237ac37a37a8a322", size = 215511, upload-time = "2025-08-04T00:33:20.32Z" }, - { url = "https://files.pythonhosted.org/packages/3f/34/68509e44995b9cad806d81b76c22bc5181f3535bca7cd9c15791bfd8951e/coverage-7.10.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:069b779d03d458602bc0e27189876e7d8bdf6b24ac0f12900de22dd2154e6ad7", size = 245513, upload-time = "2025-08-04T00:33:21.896Z" }, - { url = "https://files.pythonhosted.org/packages/ef/d4/9b12f357413248ce40804b0f58030b55a25b28a5c02db95fb0aa50c5d62c/coverage-7.10.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4c2de4cb80b9990e71c62c2d3e9f3ec71b804b1f9ca4784ec7e74127e0f42468", size = 247350, upload-time = "2025-08-04T00:33:23.917Z" }, - { url = "https://files.pythonhosted.org/packages/b6/40/257945eda1f72098e4a3c350b1d68fdc5d7d032684a0aeb6c2391153ecf4/coverage-7.10.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75bf7ab2374a7eb107602f1e07310cda164016cd60968abf817b7a0b5703e288", size = 249516, upload-time = "2025-08-04T00:33:25.5Z" }, - { url = "https://files.pythonhosted.org/packages/ff/55/8987f852ece378cecbf39a367f3f7ec53351e39a9151b130af3a3045b83f/coverage-7.10.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3f37516458ec1550815134937f73d6d15b434059cd10f64678a2068f65c62406", size = 247241, upload-time = "2025-08-04T00:33:26.767Z" }, - { url = "https://files.pythonhosted.org/packages/df/ae/da397de7a42a18cea6062ed9c3b72c50b39e0b9e7b2893d7172d3333a9a1/coverage-7.10.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:de3c6271c482c250d3303fb5c6bdb8ca025fff20a67245e1425df04dc990ece9", size = 245274, upload-time = "2025-08-04T00:33:28.494Z" }, - { url = "https://files.pythonhosted.org/packages/4e/64/7baa895eb55ec0e1ec35b988687ecd5d4475ababb0d7ae5ca3874dd90ee7/coverage-7.10.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:98a838101321ac3089c9bb1d4bfa967e8afed58021fda72d7880dc1997f20ae1", size = 245882, upload-time = "2025-08-04T00:33:30.048Z" }, - { url = "https://files.pythonhosted.org/packages/24/6c/1fd76a0bd09ae75220ae9775a8290416d726f0e5ba26ea72346747161240/coverage-7.10.2-cp311-cp311-win32.whl", hash = "sha256:f2a79145a531a0e42df32d37be5af069b4a914845b6f686590739b786f2f7bce", size = 217541, upload-time = "2025-08-04T00:33:31.376Z" }, - { url = "https://files.pythonhosted.org/packages/5f/2d/8c18fb7a6e74c79fd4661e82535bc8c68aee12f46c204eabf910b097ccc9/coverage-7.10.2-cp311-cp311-win_amd64.whl", hash = "sha256:e4f5f1320f8ee0d7cfa421ceb257bef9d39fd614dd3ddcfcacd284d4824ed2c2", size = 218426, upload-time = "2025-08-04T00:33:32.976Z" }, - { url = "https://files.pythonhosted.org/packages/da/40/425bb35e4ff7c7af177edf5dffd4154bc2a677b27696afe6526d75c77fec/coverage-7.10.2-cp311-cp311-win_arm64.whl", hash = "sha256:d8f2d83118f25328552c728b8e91babf93217db259ca5c2cd4dd4220b8926293", size = 217116, upload-time = "2025-08-04T00:33:34.302Z" }, - { url = "https://files.pythonhosted.org/packages/4e/1e/2c752bdbbf6f1199c59b1a10557fbb6fb3dc96b3c0077b30bd41a5922c1f/coverage-7.10.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:890ad3a26da9ec7bf69255b9371800e2a8da9bc223ae5d86daeb940b42247c83", size = 215311, upload-time = "2025-08-04T00:33:35.524Z" }, - { url = "https://files.pythonhosted.org/packages/68/6a/84277d73a2cafb96e24be81b7169372ba7ff28768ebbf98e55c85a491b0f/coverage-7.10.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38fd1ccfca7838c031d7a7874d4353e2f1b98eb5d2a80a2fe5732d542ae25e9c", size = 215550, upload-time = "2025-08-04T00:33:37.109Z" }, - { url = "https://files.pythonhosted.org/packages/b5/e7/5358b73b46ac76f56cc2de921eeabd44fabd0b7ff82ea4f6b8c159c4d5dc/coverage-7.10.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:76c1ffaaf4f6f0f6e8e9ca06f24bb6454a7a5d4ced97a1bc466f0d6baf4bd518", size = 246564, upload-time = "2025-08-04T00:33:38.33Z" }, - { url = "https://files.pythonhosted.org/packages/7c/0e/b0c901dd411cb7fc0cfcb28ef0dc6f3049030f616bfe9fc4143aecd95901/coverage-7.10.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:86da8a3a84b79ead5c7d0e960c34f580bc3b231bb546627773a3f53c532c2f21", size = 248993, upload-time = "2025-08-04T00:33:39.555Z" }, - { url = "https://files.pythonhosted.org/packages/0e/4e/a876db272072a9e0df93f311e187ccdd5f39a190c6d1c1f0b6e255a0d08e/coverage-7.10.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:99cef9731c8a39801830a604cc53c93c9e57ea8b44953d26589499eded9576e0", size = 250454, upload-time = "2025-08-04T00:33:41.023Z" }, - { url = "https://files.pythonhosted.org/packages/64/d6/1222dc69f8dd1be208d55708a9f4a450ad582bf4fa05320617fea1eaa6d8/coverage-7.10.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ea58b112f2966a8b91eb13f5d3b1f8bb43c180d624cd3283fb33b1cedcc2dd75", size = 248365, upload-time = "2025-08-04T00:33:42.376Z" }, - { url = "https://files.pythonhosted.org/packages/62/e3/40fd71151064fc315c922dd9a35e15b30616f00146db1d6a0b590553a75a/coverage-7.10.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:20f405188d28da9522b7232e51154e1b884fc18d0b3a10f382d54784715bbe01", size = 246562, upload-time = "2025-08-04T00:33:43.663Z" }, - { url = "https://files.pythonhosted.org/packages/fc/14/8aa93ddcd6623ddaef5d8966268ac9545b145bce4fe7b1738fd1c3f0d957/coverage-7.10.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:64586ce42bbe0da4d9f76f97235c545d1abb9b25985a8791857690f96e23dc3b", size = 247772, upload-time = "2025-08-04T00:33:45.068Z" }, - { url = "https://files.pythonhosted.org/packages/07/4e/dcb1c01490623c61e2f2ea85cb185fa6a524265bb70eeb897d3c193efeb9/coverage-7.10.2-cp312-cp312-win32.whl", hash = "sha256:bc2e69b795d97ee6d126e7e22e78a509438b46be6ff44f4dccbb5230f550d340", size = 217710, upload-time = "2025-08-04T00:33:46.378Z" }, - { url = "https://files.pythonhosted.org/packages/79/16/e8aab4162b5f80ad2e5e1f54b1826e2053aa2f4db508b864af647f00c239/coverage-7.10.2-cp312-cp312-win_amd64.whl", hash = "sha256:adda2268b8cf0d11f160fad3743b4dfe9813cd6ecf02c1d6397eceaa5b45b388", size = 218499, upload-time = "2025-08-04T00:33:48.048Z" }, - { url = "https://files.pythonhosted.org/packages/06/7f/c112ec766e8f1131ce8ce26254be028772757b2d1e63e4f6a4b0ad9a526c/coverage-7.10.2-cp312-cp312-win_arm64.whl", hash = "sha256:164429decd0d6b39a0582eaa30c67bf482612c0330572343042d0ed9e7f15c20", size = 217154, upload-time = "2025-08-04T00:33:49.299Z" }, - { url = "https://files.pythonhosted.org/packages/8d/04/9b7a741557f93c0ed791b854d27aa8d9fe0b0ce7bb7c52ca1b0f2619cb74/coverage-7.10.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:aca7b5645afa688de6d4f8e89d30c577f62956fefb1bad021490d63173874186", size = 215337, upload-time = "2025-08-04T00:33:50.61Z" }, - { url = "https://files.pythonhosted.org/packages/02/a4/8d1088cd644750c94bc305d3cf56082b4cdf7fb854a25abb23359e74892f/coverage-7.10.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:96e5921342574a14303dfdb73de0019e1ac041c863743c8fe1aa6c2b4a257226", size = 215596, upload-time = "2025-08-04T00:33:52.33Z" }, - { url = "https://files.pythonhosted.org/packages/01/2f/643a8d73343f70e162d8177a3972b76e306b96239026bc0c12cfde4f7c7a/coverage-7.10.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:11333094c1bff621aa811b67ed794865cbcaa99984dedea4bd9cf780ad64ecba", size = 246145, upload-time = "2025-08-04T00:33:53.641Z" }, - { url = "https://files.pythonhosted.org/packages/1f/4a/722098d1848db4072cda71b69ede1e55730d9063bf868375264d0d302bc9/coverage-7.10.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6eb586fa7d2aee8d65d5ae1dd71414020b2f447435c57ee8de8abea0a77d5074", size = 248492, upload-time = "2025-08-04T00:33:55.366Z" }, - { url = "https://files.pythonhosted.org/packages/3f/b0/8a6d7f326f6e3e6ed398cde27f9055e860a1e858317001835c521673fb60/coverage-7.10.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2d358f259d8019d4ef25d8c5b78aca4c7af25e28bd4231312911c22a0e824a57", size = 249927, upload-time = "2025-08-04T00:33:57.042Z" }, - { url = "https://files.pythonhosted.org/packages/bb/21/1aaadd3197b54d1e61794475379ecd0f68d8fc5c2ebd352964dc6f698a3d/coverage-7.10.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5250bda76e30382e0a2dcd68d961afcab92c3a7613606e6269855c6979a1b0bb", size = 248138, upload-time = "2025-08-04T00:33:58.329Z" }, - { url = "https://files.pythonhosted.org/packages/48/65/be75bafb2bdd22fd8bf9bf63cd5873b91bb26ec0d68f02d4b8b09c02decb/coverage-7.10.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a91e027d66eff214d88d9afbe528e21c9ef1ecdf4956c46e366c50f3094696d0", size = 246111, upload-time = "2025-08-04T00:33:59.899Z" }, - { url = "https://files.pythonhosted.org/packages/5e/30/a4f0c5e249c3cc60e6c6f30d8368e372f2d380eda40e0434c192ac27ccf5/coverage-7.10.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:228946da741558904e2c03ce870ba5efd9cd6e48cbc004d9a27abee08100a15a", size = 247493, upload-time = "2025-08-04T00:34:01.619Z" }, - { url = "https://files.pythonhosted.org/packages/85/99/f09b9493e44a75cf99ca834394c12f8cb70da6c1711ee296534f97b52729/coverage-7.10.2-cp313-cp313-win32.whl", hash = "sha256:95e23987b52d02e7c413bf2d6dc6288bd5721beb518052109a13bfdc62c8033b", size = 217756, upload-time = "2025-08-04T00:34:03.277Z" }, - { url = "https://files.pythonhosted.org/packages/2d/bb/cbcb09103be330c7d26ff0ab05c4a8861dd2e254656fdbd3eb7600af4336/coverage-7.10.2-cp313-cp313-win_amd64.whl", hash = "sha256:f35481d42c6d146d48ec92d4e239c23f97b53a3f1fbd2302e7c64336f28641fe", size = 218526, upload-time = "2025-08-04T00:34:04.635Z" }, - { url = "https://files.pythonhosted.org/packages/37/8f/8bfb4e0bca52c00ab680767c0dd8cfd928a2a72d69897d9b2d5d8b5f63f5/coverage-7.10.2-cp313-cp313-win_arm64.whl", hash = "sha256:65b451949cb789c346f9f9002441fc934d8ccedcc9ec09daabc2139ad13853f7", size = 217176, upload-time = "2025-08-04T00:34:05.973Z" }, - { url = "https://files.pythonhosted.org/packages/1e/25/d458ba0bf16a8204a88d74dbb7ec5520f29937ffcbbc12371f931c11efd2/coverage-7.10.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e8415918856a3e7d57a4e0ad94651b761317de459eb74d34cc1bb51aad80f07e", size = 216058, upload-time = "2025-08-04T00:34:07.368Z" }, - { url = "https://files.pythonhosted.org/packages/0b/1c/af4dfd2d7244dc7610fed6d59d57a23ea165681cd764445dc58d71ed01a6/coverage-7.10.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f287a25a8ca53901c613498e4a40885b19361a2fe8fbfdbb7f8ef2cad2a23f03", size = 216273, upload-time = "2025-08-04T00:34:09.073Z" }, - { url = "https://files.pythonhosted.org/packages/8e/67/ec5095d4035c6e16368226fa9cb15f77f891194c7e3725aeefd08e7a3e5a/coverage-7.10.2-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:75cc1a3f8c88c69bf16a871dab1fe5a7303fdb1e9f285f204b60f1ee539b8fc0", size = 257513, upload-time = "2025-08-04T00:34:10.403Z" }, - { url = "https://files.pythonhosted.org/packages/1c/47/be5550b57a3a8ba797de4236b0fd31031f88397b2afc84ab3c2d4cf265f6/coverage-7.10.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ca07fa78cc9d26bc8c4740de1abd3489cf9c47cc06d9a8ab3d552ff5101af4c0", size = 259377, upload-time = "2025-08-04T00:34:12.138Z" }, - { url = "https://files.pythonhosted.org/packages/37/50/b12a4da1382e672305c2d17cd3029dc16b8a0470de2191dbf26b91431378/coverage-7.10.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2e117e64c26300032755d4520cd769f2623cde1a1d1c3515b05a3b8add0ade1", size = 261516, upload-time = "2025-08-04T00:34:13.608Z" }, - { url = "https://files.pythonhosted.org/packages/db/41/4d3296dbd33dd8da178171540ca3391af7c0184c0870fd4d4574ac290290/coverage-7.10.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:daaf98009977f577b71f8800208f4d40d4dcf5c2db53d4d822787cdc198d76e1", size = 259110, upload-time = "2025-08-04T00:34:15.089Z" }, - { url = "https://files.pythonhosted.org/packages/ea/f1/b409959ecbc0cec0e61e65683b22bacaa4a3b11512f834e16dd8ffbc37db/coverage-7.10.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ea8d8fe546c528535c761ba424410bbeb36ba8a0f24be653e94b70c93fd8a8ca", size = 257248, upload-time = "2025-08-04T00:34:16.501Z" }, - { url = "https://files.pythonhosted.org/packages/48/ab/7076dc1c240412e9267d36ec93e9e299d7659f6a5c1e958f87e998b0fb6d/coverage-7.10.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:fe024d40ac31eb8d5aae70215b41dafa264676caa4404ae155f77d2fa95c37bb", size = 258063, upload-time = "2025-08-04T00:34:18.338Z" }, - { url = "https://files.pythonhosted.org/packages/1e/77/f6b51a0288f8f5f7dcc7c89abdd22cf514f3bc5151284f5cd628917f8e10/coverage-7.10.2-cp313-cp313t-win32.whl", hash = "sha256:8f34b09f68bdadec122ffad312154eda965ade433559cc1eadd96cca3de5c824", size = 218433, upload-time = "2025-08-04T00:34:19.71Z" }, - { url = "https://files.pythonhosted.org/packages/7b/6d/547a86493e25270ce8481543e77f3a0aa3aa872c1374246b7b76273d66eb/coverage-7.10.2-cp313-cp313t-win_amd64.whl", hash = "sha256:71d40b3ac0f26fa9ffa6ee16219a714fed5c6ec197cdcd2018904ab5e75bcfa3", size = 219523, upload-time = "2025-08-04T00:34:21.171Z" }, - { url = "https://files.pythonhosted.org/packages/ff/d5/3c711e38eaf9ab587edc9bed232c0298aed84e751a9f54aaa556ceaf7da6/coverage-7.10.2-cp313-cp313t-win_arm64.whl", hash = "sha256:abb57fdd38bf6f7dcc66b38dafb7af7c5fdc31ac6029ce373a6f7f5331d6f60f", size = 217739, upload-time = "2025-08-04T00:34:22.514Z" }, - { url = "https://files.pythonhosted.org/packages/71/53/83bafa669bb9d06d4c8c6a055d8d05677216f9480c4698fb183ba7ec5e47/coverage-7.10.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:a3e853cc04987c85ec410905667eed4bf08b1d84d80dfab2684bb250ac8da4f6", size = 215328, upload-time = "2025-08-04T00:34:23.991Z" }, - { url = "https://files.pythonhosted.org/packages/1d/6c/30827a9c5a48a813e865fbaf91e2db25cce990bd223a022650ef2293fe11/coverage-7.10.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0100b19f230df72c90fdb36db59d3f39232391e8d89616a7de30f677da4f532b", size = 215608, upload-time = "2025-08-04T00:34:25.437Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a0/c92d85948056ddc397b72a3d79d36d9579c53cb25393ed3c40db7d33b193/coverage-7.10.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9c1cd71483ea78331bdfadb8dcec4f4edfb73c7002c1206d8e0af6797853f5be", size = 246111, upload-time = "2025-08-04T00:34:26.857Z" }, - { url = "https://files.pythonhosted.org/packages/c2/cf/d695cf86b2559aadd072c91720a7844be4fb82cb4a3b642a2c6ce075692d/coverage-7.10.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9f75dbf4899e29a37d74f48342f29279391668ef625fdac6d2f67363518056a1", size = 248419, upload-time = "2025-08-04T00:34:28.726Z" }, - { url = "https://files.pythonhosted.org/packages/ce/0a/03206aec4a05986e039418c038470d874045f6e00426b0c3879adc1f9251/coverage-7.10.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a7df481e7508de1c38b9b8043da48d94931aefa3e32b47dd20277e4978ed5b95", size = 250038, upload-time = "2025-08-04T00:34:30.061Z" }, - { url = "https://files.pythonhosted.org/packages/ab/9b/b3bd6bd52118c12bc4cf319f5baba65009c9beea84e665b6b9f03fa3f180/coverage-7.10.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:835f39e618099325e7612b3406f57af30ab0a0af350490eff6421e2e5f608e46", size = 248066, upload-time = "2025-08-04T00:34:31.53Z" }, - { url = "https://files.pythonhosted.org/packages/80/cc/bfa92e261d3e055c851a073e87ba6a3bff12a1f7134233e48a8f7d855875/coverage-7.10.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:12e52b5aa00aa720097d6947d2eb9e404e7c1101ad775f9661ba165ed0a28303", size = 245909, upload-time = "2025-08-04T00:34:32.943Z" }, - { url = "https://files.pythonhosted.org/packages/12/80/c8df15db4847710c72084164f615ae900af1ec380dce7f74a5678ccdf5e1/coverage-7.10.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:718044729bf1fe3e9eb9f31b52e44ddae07e434ec050c8c628bf5adc56fe4bdd", size = 247329, upload-time = "2025-08-04T00:34:34.388Z" }, - { url = "https://files.pythonhosted.org/packages/04/6f/cb66e1f7124d5dd9ced69f889f02931419cb448125e44a89a13f4e036124/coverage-7.10.2-cp314-cp314-win32.whl", hash = "sha256:f256173b48cc68486299d510a3e729a96e62c889703807482dbf56946befb5c8", size = 218007, upload-time = "2025-08-04T00:34:35.846Z" }, - { url = "https://files.pythonhosted.org/packages/8c/e1/3d4be307278ce32c1b9d95cc02ee60d54ddab784036101d053ec9e4fe7f5/coverage-7.10.2-cp314-cp314-win_amd64.whl", hash = "sha256:2e980e4179f33d9b65ac4acb86c9c0dde904098853f27f289766657ed16e07b3", size = 218802, upload-time = "2025-08-04T00:34:37.35Z" }, - { url = "https://files.pythonhosted.org/packages/ec/66/1e43bbeb66c55a5a5efec70f1c153cf90cfc7f1662ab4ebe2d844de9122c/coverage-7.10.2-cp314-cp314-win_arm64.whl", hash = "sha256:14fb5b6641ab5b3c4161572579f0f2ea8834f9d3af2f7dd8fbaecd58ef9175cc", size = 217397, upload-time = "2025-08-04T00:34:39.15Z" }, - { url = "https://files.pythonhosted.org/packages/81/01/ae29c129217f6110dc694a217475b8aecbb1b075d8073401f868c825fa99/coverage-7.10.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:e96649ac34a3d0e6491e82a2af71098e43be2874b619547c3282fc11d3840a4b", size = 216068, upload-time = "2025-08-04T00:34:40.648Z" }, - { url = "https://files.pythonhosted.org/packages/a2/50/6e9221d4139f357258f36dfa1d8cac4ec56d9d5acf5fdcc909bb016954d7/coverage-7.10.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1a2e934e9da26341d342d30bfe91422bbfdb3f1f069ec87f19b2909d10d8dcc4", size = 216285, upload-time = "2025-08-04T00:34:42.441Z" }, - { url = "https://files.pythonhosted.org/packages/eb/ec/89d1d0c0ece0d296b4588e0ef4df185200456d42a47f1141335f482c2fc5/coverage-7.10.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:651015dcd5fd9b5a51ca79ece60d353cacc5beaf304db750407b29c89f72fe2b", size = 257603, upload-time = "2025-08-04T00:34:43.899Z" }, - { url = "https://files.pythonhosted.org/packages/82/06/c830af66734671c778fc49d35b58339e8f0687fbd2ae285c3f96c94da092/coverage-7.10.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81bf6a32212f9f66da03d63ecb9cd9bd48e662050a937db7199dbf47d19831de", size = 259568, upload-time = "2025-08-04T00:34:45.519Z" }, - { url = "https://files.pythonhosted.org/packages/60/57/f280dd6f1c556ecc744fbf39e835c33d3ae987d040d64d61c6f821e87829/coverage-7.10.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d800705f6951f75a905ea6feb03fff8f3ea3468b81e7563373ddc29aa3e5d1ca", size = 261691, upload-time = "2025-08-04T00:34:47.019Z" }, - { url = "https://files.pythonhosted.org/packages/54/2b/c63a0acbd19d99ec32326164c23df3a4e18984fb86e902afdd66ff7b3d83/coverage-7.10.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:248b5394718e10d067354448dc406d651709c6765669679311170da18e0e9af8", size = 259166, upload-time = "2025-08-04T00:34:48.792Z" }, - { url = "https://files.pythonhosted.org/packages/fd/c5/cd2997dcfcbf0683634da9df52d3967bc1f1741c1475dd0e4722012ba9ef/coverage-7.10.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:5c61675a922b569137cf943770d7ad3edd0202d992ce53ac328c5ff68213ccf4", size = 257241, upload-time = "2025-08-04T00:34:51.038Z" }, - { url = "https://files.pythonhosted.org/packages/16/26/c9e30f82fdad8d47aee90af4978b18c88fa74369ae0f0ba0dbf08cee3a80/coverage-7.10.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:52d708b5fd65589461381fa442d9905f5903d76c086c6a4108e8e9efdca7a7ed", size = 258139, upload-time = "2025-08-04T00:34:52.533Z" }, - { url = "https://files.pythonhosted.org/packages/c9/99/bdb7bd00bebcd3dedfb895fa9af8e46b91422993e4a37ac634a5f1113790/coverage-7.10.2-cp314-cp314t-win32.whl", hash = "sha256:916369b3b914186b2c5e5ad2f7264b02cff5df96cdd7cdad65dccd39aa5fd9f0", size = 218809, upload-time = "2025-08-04T00:34:54.075Z" }, - { url = "https://files.pythonhosted.org/packages/eb/5e/56a7852e38a04d1520dda4dfbfbf74a3d6dec932c20526968f7444763567/coverage-7.10.2-cp314-cp314t-win_amd64.whl", hash = "sha256:5b9d538e8e04916a5df63052d698b30c74eb0174f2ca9cd942c981f274a18eaf", size = 219926, upload-time = "2025-08-04T00:34:55.643Z" }, - { url = "https://files.pythonhosted.org/packages/e0/12/7fbe6b9c52bb9d627e9556f9f2edfdbe88b315e084cdecc9afead0c3b36a/coverage-7.10.2-cp314-cp314t-win_arm64.whl", hash = "sha256:04c74f9ef1f925456a9fd23a7eef1103126186d0500ef9a0acb0bd2514bdc7cc", size = 217925, upload-time = "2025-08-04T00:34:57.564Z" }, - { url = "https://files.pythonhosted.org/packages/f5/c9/139fa9f64edfa5bae1492a4efecef7209f59ba5f9d862db594be7a85d7fb/coverage-7.10.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:765b13b164685a2f8b2abef867ad07aebedc0e090c757958a186f64e39d63dbd", size = 215003, upload-time = "2025-08-04T00:34:59.079Z" }, - { url = "https://files.pythonhosted.org/packages/fd/9f/8682ccdd223c2ab34de6575ef3c78fae9bdaece1710b4d95bb9b0abd4d2f/coverage-7.10.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a219b70100500d0c7fd3ebb824a3302efb6b1a122baa9d4eb3f43df8f0b3d899", size = 215382, upload-time = "2025-08-04T00:35:00.772Z" }, - { url = "https://files.pythonhosted.org/packages/ab/4e/45b9658499db7149e1ed5b46ccac6101dc5c0ddb786a0304f7bb0c0d90d4/coverage-7.10.2-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e33e79a219105aa315439ee051bd50b6caa705dc4164a5aba6932c8ac3ce2d98", size = 241457, upload-time = "2025-08-04T00:35:02.696Z" }, - { url = "https://files.pythonhosted.org/packages/dd/66/aaf159bfe94ee3996b8786034a8e713bc68cd650aa7c1a41b612846cdc41/coverage-7.10.2-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bc3945b7bad33957a9eca16e9e5eae4b17cb03173ef594fdaad228f4fc7da53b", size = 243354, upload-time = "2025-08-04T00:35:04.238Z" }, - { url = "https://files.pythonhosted.org/packages/21/31/8fd2f67d8580380e7b19b23838e308b6757197e94a1b3b87e0ad483f70c8/coverage-7.10.2-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9bdff88e858ee608a924acfad32a180d2bf6e13e059d6a7174abbae075f30436", size = 244923, upload-time = "2025-08-04T00:35:06.159Z" }, - { url = "https://files.pythonhosted.org/packages/55/90/67b129b08200e08962961f56604083923bc8484bc641c92ee6801c1ae822/coverage-7.10.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:44329cbed24966c0b49acb386352c9722219af1f0c80db7f218af7793d251902", size = 242856, upload-time = "2025-08-04T00:35:07.735Z" }, - { url = "https://files.pythonhosted.org/packages/4d/8f/3f428363f713ab3432e602665cdefe436fd427263471644dd3742b6eebd8/coverage-7.10.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:be127f292496d0fbe20d8025f73221b36117b3587f890346e80a13b310712982", size = 241092, upload-time = "2025-08-04T00:35:09.381Z" }, - { url = "https://files.pythonhosted.org/packages/ac/4d/e8531ea19f047b8b1d1d1c85794e4b35ae762e570f072ca2afbce67be176/coverage-7.10.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6c031da749a05f7a01447dd7f47beedb498edd293e31e1878c0d52db18787df0", size = 242044, upload-time = "2025-08-04T00:35:10.929Z" }, - { url = "https://files.pythonhosted.org/packages/62/6b/22cb6281b4d06b73edae2facc7935a15151ddb8e8d8928a184b7a3100289/coverage-7.10.2-cp39-cp39-win32.whl", hash = "sha256:22aca3e691c7709c5999ccf48b7a8ff5cf5a8bd6fe9b36efbd4993f5a36b2fcf", size = 217512, upload-time = "2025-08-04T00:35:12.801Z" }, - { url = "https://files.pythonhosted.org/packages/9e/83/bce22e6880837de640d6ff630c7493709a3511f93c5154a326b337f01a81/coverage-7.10.2-cp39-cp39-win_amd64.whl", hash = "sha256:c7195444b932356055a8e287fa910bf9753a84a1bc33aeb3770e8fca521e032e", size = 218406, upload-time = "2025-08-04T00:35:14.351Z" }, - { url = "https://files.pythonhosted.org/packages/18/d8/9b768ac73a8ac2d10c080af23937212434a958c8d2a1c84e89b450237942/coverage-7.10.2-py3-none-any.whl", hash = "sha256:95db3750dd2e6e93d99fa2498f3a1580581e49c494bddccc6f85c5c21604921f", size = 206973, upload-time = "2025-08-04T00:35:15.918Z" }, +version = "7.13.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/23/f9/e92df5e07f3fc8d4c7f9a0f146ef75446bf870351cd37b788cf5897f8079/coverage-7.13.1.tar.gz", hash = "sha256:b7593fe7eb5feaa3fbb461ac79aac9f9fc0387a5ca8080b0c6fe2ca27b091afd", size = 825862, upload-time = "2025-12-28T15:42:56.969Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/9a/3742e58fd04b233df95c012ee9f3dfe04708a5e1d32613bd2d47d4e1be0d/coverage-7.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e1fa280b3ad78eea5be86f94f461c04943d942697e0dac889fa18fff8f5f9147", size = 218633, upload-time = "2025-12-28T15:40:10.165Z" }, + { url = "https://files.pythonhosted.org/packages/7e/45/7e6bdc94d89cd7c8017ce735cf50478ddfe765d4fbf0c24d71d30ea33d7a/coverage-7.13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c3d8c679607220979434f494b139dfb00131ebf70bb406553d69c1ff01a5c33d", size = 219147, upload-time = "2025-12-28T15:40:12.069Z" }, + { url = "https://files.pythonhosted.org/packages/f7/38/0d6a258625fd7f10773fe94097dc16937a5f0e3e0cdf3adef67d3ac6baef/coverage-7.13.1-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:339dc63b3eba969067b00f41f15ad161bf2946613156fb131266d8debc8e44d0", size = 245894, upload-time = "2025-12-28T15:40:13.556Z" }, + { url = "https://files.pythonhosted.org/packages/27/58/409d15ea487986994cbd4d06376e9860e9b157cfbfd402b1236770ab8dd2/coverage-7.13.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:db622b999ffe49cb891f2fff3b340cdc2f9797d01a0a202a0973ba2562501d90", size = 247721, upload-time = "2025-12-28T15:40:15.37Z" }, + { url = "https://files.pythonhosted.org/packages/da/bf/6e8056a83fd7a96c93341f1ffe10df636dd89f26d5e7b9ca511ce3bcf0df/coverage-7.13.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1443ba9acbb593fa7c1c29e011d7c9761545fe35e7652e85ce7f51a16f7e08d", size = 249585, upload-time = "2025-12-28T15:40:17.226Z" }, + { url = "https://files.pythonhosted.org/packages/f4/15/e1daff723f9f5959acb63cbe35b11203a9df77ee4b95b45fffd38b318390/coverage-7.13.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c832ec92c4499ac463186af72f9ed4d8daec15499b16f0a879b0d1c8e5cf4a3b", size = 246597, upload-time = "2025-12-28T15:40:19.028Z" }, + { url = "https://files.pythonhosted.org/packages/74/a6/1efd31c5433743a6ddbc9d37ac30c196bb07c7eab3d74fbb99b924c93174/coverage-7.13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:562ec27dfa3f311e0db1ba243ec6e5f6ab96b1edfcfc6cf86f28038bc4961ce6", size = 247626, upload-time = "2025-12-28T15:40:20.846Z" }, + { url = "https://files.pythonhosted.org/packages/6d/9f/1609267dd3e749f57fdd66ca6752567d1c13b58a20a809dc409b263d0b5f/coverage-7.13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4de84e71173d4dada2897e5a0e1b7877e5eefbfe0d6a44edee6ce31d9b8ec09e", size = 245629, upload-time = "2025-12-28T15:40:22.397Z" }, + { url = "https://files.pythonhosted.org/packages/e2/f6/6815a220d5ec2466383d7cc36131b9fa6ecbe95c50ec52a631ba733f306a/coverage-7.13.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:a5a68357f686f8c4d527a2dc04f52e669c2fc1cbde38f6f7eb6a0e58cbd17cae", size = 245901, upload-time = "2025-12-28T15:40:23.836Z" }, + { url = "https://files.pythonhosted.org/packages/ac/58/40576554cd12e0872faf6d2c0eb3bc85f71d78427946ddd19ad65201e2c0/coverage-7.13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:77cc258aeb29a3417062758975521eae60af6f79e930d6993555eeac6a8eac29", size = 246505, upload-time = "2025-12-28T15:40:25.421Z" }, + { url = "https://files.pythonhosted.org/packages/3b/77/9233a90253fba576b0eee81707b5781d0e21d97478e5377b226c5b096c0f/coverage-7.13.1-cp310-cp310-win32.whl", hash = "sha256:bb4f8c3c9a9f34423dba193f241f617b08ffc63e27f67159f60ae6baf2dcfe0f", size = 221257, upload-time = "2025-12-28T15:40:27.217Z" }, + { url = "https://files.pythonhosted.org/packages/e0/43/e842ff30c1a0a623ec80db89befb84a3a7aad7bfe44a6ea77d5a3e61fedd/coverage-7.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:c8e2706ceb622bc63bac98ebb10ef5da80ed70fbd8a7999a5076de3afaef0fb1", size = 222191, upload-time = "2025-12-28T15:40:28.916Z" }, + { url = "https://files.pythonhosted.org/packages/b4/9b/77baf488516e9ced25fc215a6f75d803493fc3f6a1a1227ac35697910c2a/coverage-7.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a55d509a1dc5a5b708b5dad3b5334e07a16ad4c2185e27b40e4dba796ab7f88", size = 218755, upload-time = "2025-12-28T15:40:30.812Z" }, + { url = "https://files.pythonhosted.org/packages/d7/cd/7ab01154e6eb79ee2fab76bf4d89e94c6648116557307ee4ebbb85e5c1bf/coverage-7.13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d010d080c4888371033baab27e47c9df7d6fb28d0b7b7adf85a4a49be9298b3", size = 219257, upload-time = "2025-12-28T15:40:32.333Z" }, + { url = "https://files.pythonhosted.org/packages/01/d5/b11ef7863ffbbdb509da0023fad1e9eda1c0eaea61a6d2ea5b17d4ac706e/coverage-7.13.1-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d938b4a840fb1523b9dfbbb454f652967f18e197569c32266d4d13f37244c3d9", size = 249657, upload-time = "2025-12-28T15:40:34.1Z" }, + { url = "https://files.pythonhosted.org/packages/f7/7c/347280982982383621d29b8c544cf497ae07ac41e44b1ca4903024131f55/coverage-7.13.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bf100a3288f9bb7f919b87eb84f87101e197535b9bd0e2c2b5b3179633324fee", size = 251581, upload-time = "2025-12-28T15:40:36.131Z" }, + { url = "https://files.pythonhosted.org/packages/82/f6/ebcfed11036ade4c0d75fa4453a6282bdd225bc073862766eec184a4c643/coverage-7.13.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ef6688db9bf91ba111ae734ba6ef1a063304a881749726e0d3575f5c10a9facf", size = 253691, upload-time = "2025-12-28T15:40:37.626Z" }, + { url = "https://files.pythonhosted.org/packages/02/92/af8f5582787f5d1a8b130b2dcba785fa5e9a7a8e121a0bb2220a6fdbdb8a/coverage-7.13.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0b609fc9cdbd1f02e51f67f51e5aee60a841ef58a68d00d5ee2c0faf357481a3", size = 249799, upload-time = "2025-12-28T15:40:39.47Z" }, + { url = "https://files.pythonhosted.org/packages/24/aa/0e39a2a3b16eebf7f193863323edbff38b6daba711abaaf807d4290cf61a/coverage-7.13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c43257717611ff5e9a1d79dce8e47566235ebda63328718d9b65dd640bc832ef", size = 251389, upload-time = "2025-12-28T15:40:40.954Z" }, + { url = "https://files.pythonhosted.org/packages/73/46/7f0c13111154dc5b978900c0ccee2e2ca239b910890e674a77f1363d483e/coverage-7.13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e09fbecc007f7b6afdfb3b07ce5bd9f8494b6856dd4f577d26c66c391b829851", size = 249450, upload-time = "2025-12-28T15:40:42.489Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ca/e80da6769e8b669ec3695598c58eef7ad98b0e26e66333996aee6316db23/coverage-7.13.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:a03a4f3a19a189919c7055098790285cc5c5b0b3976f8d227aea39dbf9f8bfdb", size = 249170, upload-time = "2025-12-28T15:40:44.279Z" }, + { url = "https://files.pythonhosted.org/packages/af/18/9e29baabdec1a8644157f572541079b4658199cfd372a578f84228e860de/coverage-7.13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3820778ea1387c2b6a818caec01c63adc5b3750211af6447e8dcfb9b6f08dbba", size = 250081, upload-time = "2025-12-28T15:40:45.748Z" }, + { url = "https://files.pythonhosted.org/packages/00/f8/c3021625a71c3b2f516464d322e41636aea381018319050a8114105872ee/coverage-7.13.1-cp311-cp311-win32.whl", hash = "sha256:ff10896fa55167371960c5908150b434b71c876dfab97b69478f22c8b445ea19", size = 221281, upload-time = "2025-12-28T15:40:47.232Z" }, + { url = "https://files.pythonhosted.org/packages/27/56/c216625f453df6e0559ed666d246fcbaaa93f3aa99eaa5080cea1229aa3d/coverage-7.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:a998cc0aeeea4c6d5622a3754da5a493055d2d95186bad877b0a34ea6e6dbe0a", size = 222215, upload-time = "2025-12-28T15:40:49.19Z" }, + { url = "https://files.pythonhosted.org/packages/5c/9a/be342e76f6e531cae6406dc46af0d350586f24d9b67fdfa6daee02df71af/coverage-7.13.1-cp311-cp311-win_arm64.whl", hash = "sha256:fea07c1a39a22614acb762e3fbbb4011f65eedafcb2948feeef641ac78b4ee5c", size = 220886, upload-time = "2025-12-28T15:40:51.067Z" }, + { url = "https://files.pythonhosted.org/packages/ce/8a/87af46cccdfa78f53db747b09f5f9a21d5fc38d796834adac09b30a8ce74/coverage-7.13.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6f34591000f06e62085b1865c9bc5f7858df748834662a51edadfd2c3bfe0dd3", size = 218927, upload-time = "2025-12-28T15:40:52.814Z" }, + { url = "https://files.pythonhosted.org/packages/82/a8/6e22fdc67242a4a5a153f9438d05944553121c8f4ba70cb072af4c41362e/coverage-7.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b67e47c5595b9224599016e333f5ec25392597a89d5744658f837d204e16c63e", size = 219288, upload-time = "2025-12-28T15:40:54.262Z" }, + { url = "https://files.pythonhosted.org/packages/d0/0a/853a76e03b0f7c4375e2ca025df45c918beb367f3e20a0a8e91967f6e96c/coverage-7.13.1-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e7b8bd70c48ffb28461ebe092c2345536fb18bbbf19d287c8913699735f505c", size = 250786, upload-time = "2025-12-28T15:40:56.059Z" }, + { url = "https://files.pythonhosted.org/packages/ea/b4/694159c15c52b9f7ec7adf49d50e5f8ee71d3e9ef38adb4445d13dd56c20/coverage-7.13.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c223d078112e90dc0e5c4e35b98b9584164bea9fbbd221c0b21c5241f6d51b62", size = 253543, upload-time = "2025-12-28T15:40:57.585Z" }, + { url = "https://files.pythonhosted.org/packages/96/b2/7f1f0437a5c855f87e17cf5d0dc35920b6440ff2b58b1ba9788c059c26c8/coverage-7.13.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:794f7c05af0763b1bbd1b9e6eff0e52ad068be3b12cd96c87de037b01390c968", size = 254635, upload-time = "2025-12-28T15:40:59.443Z" }, + { url = "https://files.pythonhosted.org/packages/e9/d1/73c3fdb8d7d3bddd9473c9c6a2e0682f09fc3dfbcb9c3f36412a7368bcab/coverage-7.13.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0642eae483cc8c2902e4af7298bf886d605e80f26382124cddc3967c2a3df09e", size = 251202, upload-time = "2025-12-28T15:41:01.328Z" }, + { url = "https://files.pythonhosted.org/packages/66/3c/f0edf75dcc152f145d5598329e864bbbe04ab78660fe3e8e395f9fff010f/coverage-7.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9f5e772ed5fef25b3de9f2008fe67b92d46831bd2bc5bdc5dd6bfd06b83b316f", size = 252566, upload-time = "2025-12-28T15:41:03.319Z" }, + { url = "https://files.pythonhosted.org/packages/17/b3/e64206d3c5f7dcbceafd14941345a754d3dbc78a823a6ed526e23b9cdaab/coverage-7.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:45980ea19277dc0a579e432aef6a504fe098ef3a9032ead15e446eb0f1191aee", size = 250711, upload-time = "2025-12-28T15:41:06.411Z" }, + { url = "https://files.pythonhosted.org/packages/dc/ad/28a3eb970a8ef5b479ee7f0c484a19c34e277479a5b70269dc652b730733/coverage-7.13.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:e4f18eca6028ffa62adbd185a8f1e1dd242f2e68164dba5c2b74a5204850b4cf", size = 250278, upload-time = "2025-12-28T15:41:08.285Z" }, + { url = "https://files.pythonhosted.org/packages/54/e3/c8f0f1a93133e3e1291ca76cbb63565bd4b5c5df63b141f539d747fff348/coverage-7.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f8dca5590fec7a89ed6826fce625595279e586ead52e9e958d3237821fbc750c", size = 252154, upload-time = "2025-12-28T15:41:09.969Z" }, + { url = "https://files.pythonhosted.org/packages/d0/bf/9939c5d6859c380e405b19e736321f1c7d402728792f4c752ad1adcce005/coverage-7.13.1-cp312-cp312-win32.whl", hash = "sha256:ff86d4e85188bba72cfb876df3e11fa243439882c55957184af44a35bd5880b7", size = 221487, upload-time = "2025-12-28T15:41:11.468Z" }, + { url = "https://files.pythonhosted.org/packages/fa/dc/7282856a407c621c2aad74021680a01b23010bb8ebf427cf5eacda2e876f/coverage-7.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:16cc1da46c04fb0fb128b4dc430b78fa2aba8a6c0c9f8eb391fd5103409a6ac6", size = 222299, upload-time = "2025-12-28T15:41:13.386Z" }, + { url = "https://files.pythonhosted.org/packages/10/79/176a11203412c350b3e9578620013af35bcdb79b651eb976f4a4b32044fa/coverage-7.13.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d9bc218650022a768f3775dd7fdac1886437325d8d295d923ebcfef4892ad5c", size = 220941, upload-time = "2025-12-28T15:41:14.975Z" }, + { url = "https://files.pythonhosted.org/packages/a3/a4/e98e689347a1ff1a7f67932ab535cef82eb5e78f32a9e4132e114bbb3a0a/coverage-7.13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb237bfd0ef4d5eb6a19e29f9e528ac67ac3be932ea6b44fb6cc09b9f3ecff78", size = 218951, upload-time = "2025-12-28T15:41:16.653Z" }, + { url = "https://files.pythonhosted.org/packages/32/33/7cbfe2bdc6e2f03d6b240d23dc45fdaf3fd270aaf2d640be77b7f16989ab/coverage-7.13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1dcb645d7e34dcbcc96cd7c132b1fc55c39263ca62eb961c064eb3928997363b", size = 219325, upload-time = "2025-12-28T15:41:18.609Z" }, + { url = "https://files.pythonhosted.org/packages/59/f6/efdabdb4929487baeb7cb2a9f7dac457d9356f6ad1b255be283d58b16316/coverage-7.13.1-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3d42df8201e00384736f0df9be2ced39324c3907607d17d50d50116c989d84cd", size = 250309, upload-time = "2025-12-28T15:41:20.629Z" }, + { url = "https://files.pythonhosted.org/packages/12/da/91a52516e9d5aea87d32d1523f9cdcf7a35a3b298e6be05d6509ba3cfab2/coverage-7.13.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa3edde1aa8807de1d05934982416cb3ec46d1d4d91e280bcce7cca01c507992", size = 252907, upload-time = "2025-12-28T15:41:22.257Z" }, + { url = "https://files.pythonhosted.org/packages/75/38/f1ea837e3dc1231e086db1638947e00d264e7e8c41aa8ecacf6e1e0c05f4/coverage-7.13.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9edd0e01a343766add6817bc448408858ba6b489039eaaa2018474e4001651a4", size = 254148, upload-time = "2025-12-28T15:41:23.87Z" }, + { url = "https://files.pythonhosted.org/packages/7f/43/f4f16b881aaa34954ba446318dea6b9ed5405dd725dd8daac2358eda869a/coverage-7.13.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:985b7836931d033570b94c94713c6dba5f9d3ff26045f72c3e5dbc5fe3361e5a", size = 250515, upload-time = "2025-12-28T15:41:25.437Z" }, + { url = "https://files.pythonhosted.org/packages/84/34/8cba7f00078bd468ea914134e0144263194ce849ec3baad187ffb6203d1c/coverage-7.13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ffed1e4980889765c84a5d1a566159e363b71d6b6fbaf0bebc9d3c30bc016766", size = 252292, upload-time = "2025-12-28T15:41:28.459Z" }, + { url = "https://files.pythonhosted.org/packages/8c/a4/cffac66c7652d84ee4ac52d3ccb94c015687d3b513f9db04bfcac2ac800d/coverage-7.13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8842af7f175078456b8b17f1b73a0d16a65dcbdc653ecefeb00a56b3c8c298c4", size = 250242, upload-time = "2025-12-28T15:41:30.02Z" }, + { url = "https://files.pythonhosted.org/packages/f4/78/9a64d462263dde416f3c0067efade7b52b52796f489b1037a95b0dc389c9/coverage-7.13.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:ccd7a6fca48ca9c131d9b0a2972a581e28b13416fc313fb98b6d24a03ce9a398", size = 250068, upload-time = "2025-12-28T15:41:32.007Z" }, + { url = "https://files.pythonhosted.org/packages/69/c8/a8994f5fece06db7c4a97c8fc1973684e178599b42e66280dded0524ef00/coverage-7.13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0403f647055de2609be776965108447deb8e384fe4a553c119e3ff6bfbab4784", size = 251846, upload-time = "2025-12-28T15:41:33.946Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f7/91fa73c4b80305c86598a2d4e54ba22df6bf7d0d97500944af7ef155d9f7/coverage-7.13.1-cp313-cp313-win32.whl", hash = "sha256:549d195116a1ba1e1ae2f5ca143f9777800f6636eab917d4f02b5310d6d73461", size = 221512, upload-time = "2025-12-28T15:41:35.519Z" }, + { url = "https://files.pythonhosted.org/packages/45/0b/0768b4231d5a044da8f75e097a8714ae1041246bb765d6b5563bab456735/coverage-7.13.1-cp313-cp313-win_amd64.whl", hash = "sha256:5899d28b5276f536fcf840b18b61a9fce23cc3aec1d114c44c07fe94ebeaa500", size = 222321, upload-time = "2025-12-28T15:41:37.371Z" }, + { url = "https://files.pythonhosted.org/packages/9b/b8/bdcb7253b7e85157282450262008f1366aa04663f3e3e4c30436f596c3e2/coverage-7.13.1-cp313-cp313-win_arm64.whl", hash = "sha256:868a2fae76dfb06e87291bcbd4dcbcc778a8500510b618d50496e520bd94d9b9", size = 220949, upload-time = "2025-12-28T15:41:39.553Z" }, + { url = "https://files.pythonhosted.org/packages/70/52/f2be52cc445ff75ea8397948c96c1b4ee14f7f9086ea62fc929c5ae7b717/coverage-7.13.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:67170979de0dacac3f3097d02b0ad188d8edcea44ccc44aaa0550af49150c7dc", size = 219643, upload-time = "2025-12-28T15:41:41.567Z" }, + { url = "https://files.pythonhosted.org/packages/47/79/c85e378eaa239e2edec0c5523f71542c7793fe3340954eafb0bc3904d32d/coverage-7.13.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f80e2bb21bfab56ed7405c2d79d34b5dc0bc96c2c1d2a067b643a09fb756c43a", size = 219997, upload-time = "2025-12-28T15:41:43.418Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9b/b1ade8bfb653c0bbce2d6d6e90cc6c254cbb99b7248531cc76253cb4da6d/coverage-7.13.1-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f83351e0f7dcdb14d7326c3d8d8c4e915fa685cbfdc6281f9470d97a04e9dfe4", size = 261296, upload-time = "2025-12-28T15:41:45.207Z" }, + { url = "https://files.pythonhosted.org/packages/1f/af/ebf91e3e1a2473d523e87e87fd8581e0aa08741b96265730e2d79ce78d8d/coverage-7.13.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:bb3f6562e89bad0110afbe64e485aac2462efdce6232cdec7862a095dc3412f6", size = 263363, upload-time = "2025-12-28T15:41:47.163Z" }, + { url = "https://files.pythonhosted.org/packages/c4/8b/fb2423526d446596624ac7fde12ea4262e66f86f5120114c3cfd0bb2befa/coverage-7.13.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77545b5dcda13b70f872c3b5974ac64c21d05e65b1590b441c8560115dc3a0d1", size = 265783, upload-time = "2025-12-28T15:41:49.03Z" }, + { url = "https://files.pythonhosted.org/packages/9b/26/ef2adb1e22674913b89f0fe7490ecadcef4a71fa96f5ced90c60ec358789/coverage-7.13.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4d240d260a1aed814790bbe1f10a5ff31ce6c21bc78f0da4a1e8268d6c80dbd", size = 260508, upload-time = "2025-12-28T15:41:51.035Z" }, + { url = "https://files.pythonhosted.org/packages/ce/7d/f0f59b3404caf662e7b5346247883887687c074ce67ba453ea08c612b1d5/coverage-7.13.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d2287ac9360dec3837bfdad969963a5d073a09a85d898bd86bea82aa8876ef3c", size = 263357, upload-time = "2025-12-28T15:41:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b1/29896492b0b1a047604d35d6fa804f12818fa30cdad660763a5f3159e158/coverage-7.13.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:0d2c11f3ea4db66b5cbded23b20185c35066892c67d80ec4be4bab257b9ad1e0", size = 260978, upload-time = "2025-12-28T15:41:54.589Z" }, + { url = "https://files.pythonhosted.org/packages/48/f2/971de1238a62e6f0a4128d37adadc8bb882ee96afbe03ff1570291754629/coverage-7.13.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:3fc6a169517ca0d7ca6846c3c5392ef2b9e38896f61d615cb75b9e7134d4ee1e", size = 259877, upload-time = "2025-12-28T15:41:56.263Z" }, + { url = "https://files.pythonhosted.org/packages/6a/fc/0474efcbb590ff8628830e9aaec5f1831594874360e3251f1fdec31d07a3/coverage-7.13.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d10a2ed46386e850bb3de503a54f9fe8192e5917fcbb143bfef653a9355e9a53", size = 262069, upload-time = "2025-12-28T15:41:58.093Z" }, + { url = "https://files.pythonhosted.org/packages/88/4f/3c159b7953db37a7b44c0eab8a95c37d1aa4257c47b4602c04022d5cb975/coverage-7.13.1-cp313-cp313t-win32.whl", hash = "sha256:75a6f4aa904301dab8022397a22c0039edc1f51e90b83dbd4464b8a38dc87842", size = 222184, upload-time = "2025-12-28T15:41:59.763Z" }, + { url = "https://files.pythonhosted.org/packages/58/a5/6b57d28f81417f9335774f20679d9d13b9a8fb90cd6160957aa3b54a2379/coverage-7.13.1-cp313-cp313t-win_amd64.whl", hash = "sha256:309ef5706e95e62578cda256b97f5e097916a2c26247c287bbe74794e7150df2", size = 223250, upload-time = "2025-12-28T15:42:01.52Z" }, + { url = "https://files.pythonhosted.org/packages/81/7c/160796f3b035acfbb58be80e02e484548595aa67e16a6345e7910ace0a38/coverage-7.13.1-cp313-cp313t-win_arm64.whl", hash = "sha256:92f980729e79b5d16d221038dbf2e8f9a9136afa072f9d5d6ed4cb984b126a09", size = 221521, upload-time = "2025-12-28T15:42:03.275Z" }, + { url = "https://files.pythonhosted.org/packages/aa/8e/ba0e597560c6563fc0adb902fda6526df5d4aa73bb10adf0574d03bd2206/coverage-7.13.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:97ab3647280d458a1f9adb85244e81587505a43c0c7cff851f5116cd2814b894", size = 218996, upload-time = "2025-12-28T15:42:04.978Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8e/764c6e116f4221dc7aa26c4061181ff92edb9c799adae6433d18eeba7a14/coverage-7.13.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8f572d989142e0908e6acf57ad1b9b86989ff057c006d13b76c146ec6a20216a", size = 219326, upload-time = "2025-12-28T15:42:06.691Z" }, + { url = "https://files.pythonhosted.org/packages/4f/a6/6130dc6d8da28cdcbb0f2bf8865aeca9b157622f7c0031e48c6cf9a0e591/coverage-7.13.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d72140ccf8a147e94274024ff6fd8fb7811354cf7ef88b1f0a988ebaa5bc774f", size = 250374, upload-time = "2025-12-28T15:42:08.786Z" }, + { url = "https://files.pythonhosted.org/packages/82/2b/783ded568f7cd6b677762f780ad338bf4b4750205860c17c25f7c708995e/coverage-7.13.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3c9f051b028810f5a87c88e5d6e9af3c0ff32ef62763bf15d29f740453ca909", size = 252882, upload-time = "2025-12-28T15:42:10.515Z" }, + { url = "https://files.pythonhosted.org/packages/cd/b2/9808766d082e6a4d59eb0cc881a57fc1600eb2c5882813eefff8254f71b5/coverage-7.13.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f398ba4df52d30b1763f62eed9de5620dcde96e6f491f4c62686736b155aa6e4", size = 254218, upload-time = "2025-12-28T15:42:12.208Z" }, + { url = "https://files.pythonhosted.org/packages/44/ea/52a985bb447c871cb4d2e376e401116520991b597c85afdde1ea9ef54f2c/coverage-7.13.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:132718176cc723026d201e347f800cd1a9e4b62ccd3f82476950834dad501c75", size = 250391, upload-time = "2025-12-28T15:42:14.21Z" }, + { url = "https://files.pythonhosted.org/packages/7f/1d/125b36cc12310718873cfc8209ecfbc1008f14f4f5fa0662aa608e579353/coverage-7.13.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9e549d642426e3579b3f4b92d0431543b012dcb6e825c91619d4e93b7363c3f9", size = 252239, upload-time = "2025-12-28T15:42:16.292Z" }, + { url = "https://files.pythonhosted.org/packages/6a/16/10c1c164950cade470107f9f14bbac8485f8fb8515f515fca53d337e4a7f/coverage-7.13.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:90480b2134999301eea795b3a9dbf606c6fbab1b489150c501da84a959442465", size = 250196, upload-time = "2025-12-28T15:42:18.54Z" }, + { url = "https://files.pythonhosted.org/packages/2a/c6/cd860fac08780c6fd659732f6ced1b40b79c35977c1356344e44d72ba6c4/coverage-7.13.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e825dbb7f84dfa24663dd75835e7257f8882629fc11f03ecf77d84a75134b864", size = 250008, upload-time = "2025-12-28T15:42:20.365Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/a8c58d3d38f82a5711e1e0a67268362af48e1a03df27c03072ac30feefcf/coverage-7.13.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:623dcc6d7a7ba450bbdbeedbaa0c42b329bdae16491af2282f12a7e809be7eb9", size = 251671, upload-time = "2025-12-28T15:42:22.114Z" }, + { url = "https://files.pythonhosted.org/packages/f0/bc/fd4c1da651d037a1e3d53e8cb3f8182f4b53271ffa9a95a2e211bacc0349/coverage-7.13.1-cp314-cp314-win32.whl", hash = "sha256:6e73ebb44dca5f708dc871fe0b90cf4cff1a13f9956f747cc87b535a840386f5", size = 221777, upload-time = "2025-12-28T15:42:23.919Z" }, + { url = "https://files.pythonhosted.org/packages/4b/50/71acabdc8948464c17e90b5ffd92358579bd0910732c2a1c9537d7536aa6/coverage-7.13.1-cp314-cp314-win_amd64.whl", hash = "sha256:be753b225d159feb397bd0bf91ae86f689bad0da09d3b301478cd39b878ab31a", size = 222592, upload-time = "2025-12-28T15:42:25.619Z" }, + { url = "https://files.pythonhosted.org/packages/f7/c8/a6fb943081bb0cc926499c7907731a6dc9efc2cbdc76d738c0ab752f1a32/coverage-7.13.1-cp314-cp314-win_arm64.whl", hash = "sha256:228b90f613b25ba0019361e4ab81520b343b622fc657daf7e501c4ed6a2366c0", size = 221169, upload-time = "2025-12-28T15:42:27.629Z" }, + { url = "https://files.pythonhosted.org/packages/16/61/d5b7a0a0e0e40d62e59bc8c7aa1afbd86280d82728ba97f0673b746b78e2/coverage-7.13.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:60cfb538fe9ef86e5b2ab0ca8fc8d62524777f6c611dcaf76dc16fbe9b8e698a", size = 219730, upload-time = "2025-12-28T15:42:29.306Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2c/8881326445fd071bb49514d1ce97d18a46a980712b51fee84f9ab42845b4/coverage-7.13.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:57dfc8048c72ba48a8c45e188d811e5efd7e49b387effc8fb17e97936dde5bf6", size = 220001, upload-time = "2025-12-28T15:42:31.319Z" }, + { url = "https://files.pythonhosted.org/packages/b5/d7/50de63af51dfa3a7f91cc37ad8fcc1e244b734232fbc8b9ab0f3c834a5cd/coverage-7.13.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3f2f725aa3e909b3c5fdb8192490bdd8e1495e85906af74fe6e34a2a77ba0673", size = 261370, upload-time = "2025-12-28T15:42:32.992Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2c/d31722f0ec918fd7453b2758312729f645978d212b410cd0f7c2aed88a94/coverage-7.13.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ee68b21909686eeb21dfcba2c3b81fee70dcf38b140dcd5aa70680995fa3aa5", size = 263485, upload-time = "2025-12-28T15:42:34.759Z" }, + { url = "https://files.pythonhosted.org/packages/fa/7a/2c114fa5c5fc08ba0777e4aec4c97e0b4a1afcb69c75f1f54cff78b073ab/coverage-7.13.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:724b1b270cb13ea2e6503476e34541a0b1f62280bc997eab443f87790202033d", size = 265890, upload-time = "2025-12-28T15:42:36.517Z" }, + { url = "https://files.pythonhosted.org/packages/65/d9/f0794aa1c74ceabc780fe17f6c338456bbc4e96bd950f2e969f48ac6fb20/coverage-7.13.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:916abf1ac5cf7eb16bc540a5bf75c71c43a676f5c52fcb9fe75a2bd75fb944e8", size = 260445, upload-time = "2025-12-28T15:42:38.646Z" }, + { url = "https://files.pythonhosted.org/packages/49/23/184b22a00d9bb97488863ced9454068c79e413cb23f472da6cbddc6cfc52/coverage-7.13.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:776483fd35b58d8afe3acbd9988d5de592ab6da2d2a865edfdbc9fdb43e7c486", size = 263357, upload-time = "2025-12-28T15:42:40.788Z" }, + { url = "https://files.pythonhosted.org/packages/7d/bd/58af54c0c9199ea4190284f389005779d7daf7bf3ce40dcd2d2b2f96da69/coverage-7.13.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b6f3b96617e9852703f5b633ea01315ca45c77e879584f283c44127f0f1ec564", size = 260959, upload-time = "2025-12-28T15:42:42.808Z" }, + { url = "https://files.pythonhosted.org/packages/4b/2a/6839294e8f78a4891bf1df79d69c536880ba2f970d0ff09e7513d6e352e9/coverage-7.13.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:bd63e7b74661fed317212fab774e2a648bc4bb09b35f25474f8e3325d2945cd7", size = 259792, upload-time = "2025-12-28T15:42:44.818Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c3/528674d4623283310ad676c5af7414b9850ab6d55c2300e8aa4b945ec554/coverage-7.13.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:933082f161bbb3e9f90d00990dc956120f608cdbcaeea15c4d897f56ef4fe416", size = 262123, upload-time = "2025-12-28T15:42:47.108Z" }, + { url = "https://files.pythonhosted.org/packages/06/c5/8c0515692fb4c73ac379d8dc09b18eaf0214ecb76ea6e62467ba7a1556ff/coverage-7.13.1-cp314-cp314t-win32.whl", hash = "sha256:18be793c4c87de2965e1c0f060f03d9e5aff66cfeae8e1dbe6e5b88056ec153f", size = 222562, upload-time = "2025-12-28T15:42:49.144Z" }, + { url = "https://files.pythonhosted.org/packages/05/0e/c0a0c4678cb30dac735811db529b321d7e1c9120b79bd728d4f4d6b010e9/coverage-7.13.1-cp314-cp314t-win_amd64.whl", hash = "sha256:0e42e0ec0cd3e0d851cb3c91f770c9301f48647cb2877cb78f74bdaa07639a79", size = 223670, upload-time = "2025-12-28T15:42:51.218Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5f/b177aa0011f354abf03a8f30a85032686d290fdeed4222b27d36b4372a50/coverage-7.13.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eaecf47ef10c72ece9a2a92118257da87e460e113b83cc0d2905cbbe931792b4", size = 221707, upload-time = "2025-12-28T15:42:53.034Z" }, + { url = "https://files.pythonhosted.org/packages/cc/48/d9f421cb8da5afaa1a64570d9989e00fb7955e6acddc5a12979f7666ef60/coverage-7.13.1-py3-none-any.whl", hash = "sha256:2016745cb3ba554469d02819d78958b571792bb68e31302610e898f80dd3a573", size = 210722, upload-time = "2025-12-28T15:42:54.901Z" }, ] [package.optional-dependencies] @@ -361,14 +410,14 @@ toml = [ [[package]] name = "deprecated" -version = "1.2.18" +version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "wrapt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/98/97/06afe62762c9a8a86af0cfb7bfdab22a43ad17138b07af5b1a58442690a2/deprecated-1.2.18.tar.gz", hash = "sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d", size = 2928744, upload-time = "2025-01-27T10:46:25.7Z" } +sdist = { url = "https://files.pythonhosted.org/packages/49/85/12f0a49a7c4ffb70572b6c2ef13c90c88fd190debda93b23f026b25f9634/deprecated-1.3.1.tar.gz", hash = "sha256:b1b50e0ff0c1fddaa5708a2c6b0a6588bb09b892825ab2b214ac9ea9d92a5223", size = 2932523, upload-time = "2025-10-30T08:19:02.757Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6e/c6/ac0b6c1e2d138f1002bcf799d330bd6d85084fece321e662a14223794041/Deprecated-1.2.18-py2.py3-none-any.whl", hash = "sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec", size = 9998, upload-time = "2025-01-27T10:46:09.186Z" }, + { url = "https://files.pythonhosted.org/packages/84/d0/205d54408c08b13550c733c4b85429e7ead111c7f0014309637425520a9a/deprecated-1.3.1-py2.py3-none-any.whl", hash = "sha256:597bfef186b6f60181535a29fbe44865ce137a5079f295b479886c82729d5f3f", size = 11298, upload-time = "2025-10-30T08:19:00.758Z" }, ] [[package]] @@ -400,32 +449,32 @@ wheels = [ [[package]] name = "exceptiongroup" -version = "1.3.0" +version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, ] [[package]] name = "execnet" -version = "2.1.1" +version = "2.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bb/ff/b4c0dc78fbe20c3e59c0c7334de0c27eb4001a2b2017999af398bf730817/execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3", size = 166524, upload-time = "2024-04-08T09:04:19.245Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/89/780e11f9588d9e7128a3f87788354c7946a9cbb1401ad38a48c4db9a4f07/execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", size = 166622, upload-time = "2025-11-12T09:56:37.75Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612, upload-time = "2024-04-08T09:04:17.414Z" }, + { url = "https://files.pythonhosted.org/packages/ab/84/02fc1827e8cdded4aa65baef11296a9bbe595c474f0d6d758af082d849fd/execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec", size = 40708, upload-time = "2025-11-12T09:56:36.333Z" }, ] [[package]] name = "filelock" -version = "3.18.0" +version = "3.20.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/65/ce7f1b70157833bf3cb851b556a37d4547ceafc158aa9b34b36782f23696/filelock-3.20.3.tar.gz", hash = "sha256:18c57ee915c7ec61cff0ecf7f0f869936c7c30191bb0cf406f1341778d0834e1", size = 19485, upload-time = "2026-01-09T17:55:05.421Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, + { url = "https://files.pythonhosted.org/packages/b5/36/7fb70f04bf00bc646cd5bb45aa9eddb15e19437a28b8fb2b4a5249fac770/filelock-3.20.3-py3-none-any.whl", hash = "sha256:4b0dda527ee31078689fc205ec4f1c1bf7d56cf88b6dc9426c4f230e46c2dce1", size = 16701, upload-time = "2026-01-09T17:55:04.334Z" }, ] [[package]] @@ -442,15 +491,14 @@ wheels = [ [[package]] name = "gitpython" -version = "3.1.45" +version = "3.1.58" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "gitdb" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9a/c8/dd58967d119baab745caec2f9d853297cec1989ec1d63f677d3880632b88/gitpython-3.1.45.tar.gz", hash = "sha256:85b0ee964ceddf211c41b9f27a49086010a190fd8132a24e21f362a4b36a791c", size = 215076, upload-time = "2025-07-24T03:45:54.871Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/d6/5f358ff283325580c2003a6d953aea18cfe10ae87b46f5ebc80fa3a386dc/gitpython-3.1.58.tar.gz", hash = "sha256:621416df10ef3fd0e19fabf9172ddeed0fa704d353d04f194eec56a625a95b22", size = 228498, upload-time = "2026-08-04T15:05:49.47Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" }, + { url = "https://files.pythonhosted.org/packages/ec/0c/9d8752098bc442f0726e64aa6135940b3a96809915d1aa4206c1bb97881d/gitpython-3.1.58-py3-none-any.whl", hash = "sha256:d331e722577f0fd7fc1f857419b3ecc07af66282b933d2a4d95f84a042fdd50f", size = 220183, upload-time = "2026-08-04T15:05:48.025Z" }, ] [[package]] @@ -470,20 +518,20 @@ sdist = { url = "https://files.pythonhosted.org/packages/6e/19/850b7ed736319d0c4 [[package]] name = "identify" -version = "2.6.12" +version = "2.6.16" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/88/d193a27416618628a5eea64e3223acd800b40749a96ffb322a9b55a49ed1/identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6", size = 99254, upload-time = "2025-05-23T20:37:53.3Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/8d/e8b97e6bd3fb6fb271346f7981362f1e04d6a7463abd0de79e1fda17c067/identify-2.6.16.tar.gz", hash = "sha256:846857203b5511bbe94d5a352a48ef2359532bc8f6727b5544077a0dcfb24980", size = 99360, upload-time = "2026-01-12T18:58:58.201Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7a/cd/18f8da995b658420625f7ef13f037be53ae04ec5ad33f9b718240dcfd48c/identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2", size = 99145, upload-time = "2025-05-23T20:37:51.495Z" }, + { url = "https://files.pythonhosted.org/packages/b8/58/40fbbcefeda82364720eba5cf2270f98496bdfa19ea75b4cccae79c698e6/identify-2.6.16-py2.py3-none-any.whl", hash = "sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0", size = 99202, upload-time = "2026-01-12T18:58:56.627Z" }, ] [[package]] name = "idna" -version = "3.10" +version = "3.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, + { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, ] [[package]] @@ -495,25 +543,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, ] -[[package]] -name = "importlib-metadata" -version = "8.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "zipp", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, -] - [[package]] name = "importlib-resources" version = "6.5.2" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "zipp", marker = "python_full_version < '3.10'" }, -] sdist = { url = "https://files.pythonhosted.org/packages/cf/8c/f834fbf984f691b4f7ff60f50b514cc3de5cc08abfc3295564dd89c5e2e7/importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c", size = 44693, upload-time = "2025-01-03T18:51:56.698Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec", size = 37461, upload-time = "2025-01-03T18:51:54.306Z" }, @@ -521,11 +554,11 @@ wheels = [ [[package]] name = "iniconfig" -version = "2.1.0" +version = "2.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, ] [[package]] @@ -541,30 +574,98 @@ wheels = [ ] [[package]] -name = "markdown-it-py" -version = "3.0.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "mdurl", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, +name = "librt" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/2f/3908645ddddab7120b46295e541ead308109fa48dbec7d67d7a778870d60/librt-0.13.0.tar.gz", hash = "sha256:1d2a610c14ac0d0750ee0a3ab8548e83155258387891caaca04def4bf7289781", size = 211402, upload-time = "2026-07-08T12:26:29.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/2f/ec5241c38e7fa0fe6c26bfc450e78b9489a6c3c08b394b85d2c10e506975/librt-0.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:34e47058fcc69a313293d6dee94216a4f30c929ae6f2476e58c5ba635aa639d5", size = 148654, upload-time = "2026-07-08T12:24:30.622Z" }, + { url = "https://files.pythonhosted.org/packages/a5/1a/d651e18d3ee7aa2879322368c4f278bb7ecaa6b90caadfdec4ebfa8389f3/librt-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dbdd5b6509d0c2a8fe72cf494c299a61dbd58142a90a4190664ae159e4a7b547", size = 153537, upload-time = "2026-07-08T12:24:31.773Z" }, + { url = "https://files.pythonhosted.org/packages/45/18/10bff2122577246009d9619b6569596daf69b7648812f997ca9ca0426f60/librt-0.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e56ea4ee4df77585a6b5c138f6538680886024fa559f5b55bd14b12e98e67b2", size = 494336, upload-time = "2026-07-08T12:24:33.079Z" }, + { url = "https://files.pythonhosted.org/packages/67/69/87dfee871b852970f137fdeae8e2ca356c5ab38e6f21d2a3299535fc3159/librt-0.13.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f1f9cc4d09a46d9cb3c2063ae100629d3f52a6517c3c08c2f4c9828261883929", size = 485393, upload-time = "2026-07-08T12:24:34.324Z" }, + { url = "https://files.pythonhosted.org/packages/e9/d5/625447a8c0441ff5f15f4ac5e1d323fb9d4d256ebfde7a3c8e003f646057/librt-0.13.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f125f5d46b20f89dc5587a55cc416b4ba2a5b2ffda36d048ee120e17598a653a", size = 515382, upload-time = "2026-07-08T12:24:35.575Z" }, + { url = "https://files.pythonhosted.org/packages/8d/d8/1c8c49ea04235960426444deece9092a6b3a9587a850a81bae2335317411/librt-0.13.0-cp310-cp310-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2608d3b39f9e0b4a66a130d9150c615cba40a5090d25eeeaa225e0e46de8c0ac", size = 509483, upload-time = "2026-07-08T12:24:36.923Z" }, + { url = "https://files.pythonhosted.org/packages/6f/65/f1760fc48050e215201a03506c32b7270159088d01f64557b53e39e74a45/librt-0.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9fd35e95ab5e45c3901d37110263c7db85a961110f5460588fe37f8c131f88a7", size = 532503, upload-time = "2026-07-08T12:24:38.203Z" }, + { url = "https://files.pythonhosted.org/packages/18/1b/793e281dcf494879eff99f642b63ebc9c7c58694a1c2d1e93362a22c7041/librt-0.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5f31b0aa13c9b04370d4da6be1ab7779776b3a075cceb6747a39a4be85fe1e40", size = 537027, upload-time = "2026-07-08T12:24:39.34Z" }, + { url = "https://files.pythonhosted.org/packages/69/45/0801bbb40c9eea795d3dd3ce91c4c5f3fe7d42d23ec4be3e8cb283bcc754/librt-0.13.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:0b795f5fc70fbbb787ceaf79bb3a0d627bcc33c53de51741755263ec406b775a", size = 517100, upload-time = "2026-07-08T12:24:40.907Z" }, + { url = "https://files.pythonhosted.org/packages/a1/6c/eb5f514f8e29d4924bc0ff4601dd7b4175557e182e7c0721e84cffa39b8a/librt-0.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:36b306a623aaad96fe4b378692b54f9c0789fccd833b9851753d5fbf6138cfde", size = 558653, upload-time = "2026-07-08T12:24:42.359Z" }, + { url = "https://files.pythonhosted.org/packages/b4/bf/f140100d1b59fe87ff40b5ecbb4e27924335b189a784e230ee465452f6c2/librt-0.13.0-cp310-cp310-win32.whl", hash = "sha256:a3762e75fcac8c9e4dacaaf438bffd9003e2ca2c531b756f3c0035deefa674c8", size = 104402, upload-time = "2026-07-08T12:24:43.668Z" }, + { url = "https://files.pythonhosted.org/packages/22/7c/57e40fef7cfb61869341cb28bdcefe8a950bebcbecca74a397bae14dce4a/librt-0.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:d63bae12a8aeb51380be3438e4dc4bd27354d0f8e19166b2f44e3e94d6f552dc", size = 125002, upload-time = "2026-07-08T12:24:44.793Z" }, + { url = "https://files.pythonhosted.org/packages/89/25/a6498964cfeec270c468cffdc118f69c29b412593610d55fa1327ca51ff4/librt-0.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1b5a7bbff495baedbd9b916c367d66854008f8f3b575908ded477c499dc60082", size = 148029, upload-time = "2026-07-08T12:24:45.961Z" }, + { url = "https://files.pythonhosted.org/packages/78/59/dc86d1bffd8e0c2818bace29d9f7783cfbb8e0673bf3673b5bbd5bbe0420/librt-0.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34bc7938b9fdf14fe32a406c19c71faf894c5cee7e7474bd0be2f17200b82d14", size = 153036, upload-time = "2026-07-08T12:24:47.257Z" }, + { url = "https://files.pythonhosted.org/packages/29/3f/b923826660f02f286186cd9303d52bb05ced0a13708edc104dc8480920e3/librt-0.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f40e56b61b41be5f7dec938cfeffd660668cf4b5e72c78e7bd671d66b7bc2c79", size = 493062, upload-time = "2026-07-08T12:24:48.483Z" }, + { url = "https://files.pythonhosted.org/packages/88/87/6c0980a9c9b1302cb68d108906697b89eceb55889bb1dcf77c109aa56ca5/librt-0.13.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:9c5d02b89de5acd0379a51ec44a89476fb03df6145442e1c8ecd6bee2f91b176", size = 485510, upload-time = "2026-07-08T12:24:49.727Z" }, + { url = "https://files.pythonhosted.org/packages/32/81/795ae3b9df5dd94079fb807e38191855e023e8c6249014ae6bc3f0d9a490/librt-0.13.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7db9a3ff32ef5f7d1703d93831a3316cdf0b537de6a1cc03cc8fdd09b9194e89", size = 515909, upload-time = "2026-07-08T12:24:51.135Z" }, + { url = "https://files.pythonhosted.org/packages/20/e5/182de15abce8907108a6fdb41487de65beb5099b74dc5841b19b099168db/librt-0.13.0-cp311-cp311-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3dbb2a31882456cadc7053378e81ad7ed7693db4ac9f98ab5f81ef034aa8ec9f", size = 508620, upload-time = "2026-07-08T12:24:52.358Z" }, + { url = "https://files.pythonhosted.org/packages/32/03/33978d32db76e1f66377e8f78e42a2ca3c162143331677d1f50bbad36cfb/librt-0.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c6014e3c80f9c1fe268ef8b0e0ef113bac672cc032f2f93866e7ddad4f3e663d", size = 530363, upload-time = "2026-07-08T12:24:53.503Z" }, + { url = "https://files.pythonhosted.org/packages/e6/f5/b291fbd2d00f7d8287bcbf67b5aa0c6afed4bc26cef23e079629c47a2c04/librt-0.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:091b60a4d2174fc1ec5c34cdc0b72efb6224753d76b7da61ebeab7a191aec8bd", size = 534209, upload-time = "2026-07-08T12:24:55.138Z" }, + { url = "https://files.pythonhosted.org/packages/3e/03/6f41f17939d191bc21609f220da8509316bc62797f078545fe83be522e78/librt-0.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:66cb1138f384a191a6d75f986064841fcfdc0cea98f7bd9c9ab9b38049917588", size = 514254, upload-time = "2026-07-08T12:24:56.276Z" }, + { url = "https://files.pythonhosted.org/packages/af/c2/2e4befa5410a7443019c14abccc94ff619797171f6b72013635fb87f31d7/librt-0.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:17221a7569f8f292aa0014226e48aa25b8c2b08da18088cd230953d0ea0f9cd1", size = 557611, upload-time = "2026-07-08T12:24:57.561Z" }, + { url = "https://files.pythonhosted.org/packages/ab/54/8b69f81448417adbc040a2185f4e2eece1e1994b7dcfaeed4662b30f98a5/librt-0.13.0-cp311-cp311-win32.whl", hash = "sha256:fc67741da44c6eaa90e01eafb586bbba9b51eb5b6ed381ee6f5ae72eb3316d21", size = 104906, upload-time = "2026-07-08T12:24:58.806Z" }, + { url = "https://files.pythonhosted.org/packages/76/5a/f4aaf37b50f2fde12c8c663b83fdd499cdc24f957f19543d7414bfcc9e25/librt-0.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:cc99dfb62b23c9207c33d0be8a2e2af7a42e21e6ea388b380a0c948c7b88953b", size = 125852, upload-time = "2026-07-08T12:25:00.065Z" }, + { url = "https://files.pythonhosted.org/packages/f2/99/bf1820e6feeabc2f218c24450ec0c995d6a91e8ba0fd3caf042c9e8adb2a/librt-0.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:40ccd13c252d3fe473ffc8a57be7565abc8b64cf1b108344c859d5164f7f3e0c", size = 111832, upload-time = "2026-07-08T12:25:01.148Z" }, + { url = "https://files.pythonhosted.org/packages/f0/f4/b2933ddae222dac338476abb872641169a5cfed2c2bb5444a5b07b32b0c3/librt-0.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30536798f4504c0fad0885b1d371b0539abb081e4570c9d7c641cb51141b49f0", size = 150990, upload-time = "2026-07-08T12:25:02.42Z" }, + { url = "https://files.pythonhosted.org/packages/90/ef/db98f744ca50e6efc9c95c70ee49b77aefac31f6a3fc7c83754a42d6a74f/librt-0.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93d24ebb82aa4420b1409c389e7857bc35bd0b668007ac8172427d5c73cc8cc5", size = 155238, upload-time = "2026-07-08T12:25:03.681Z" }, + { url = "https://files.pythonhosted.org/packages/03/e7/a197e7bc72baf2c61ce7fdc6906a5054dc05bd8da0819aa894e4857bf87e/librt-0.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb8a1adce42d8b75485a5d56a9623a50bcab995b6079f1dac59fc44034dd93d9", size = 503073, upload-time = "2026-07-08T12:25:05.049Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e7/7887712e27da7c1ab80fcabb1de6eb24243964f6557cae530d4b70706dbd/librt-0.13.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:0763ca2ab66058174f9dee426dc64f5e0a89c24a7df8d3fe3f1836c04e25de4b", size = 496528, upload-time = "2026-07-08T12:25:06.26Z" }, + { url = "https://files.pythonhosted.org/packages/94/f0/f2283385bb6b950b26a1410f4ce51ec27231e0b3a4b925c46366d218b198/librt-0.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b222493da6e7b6199db9bd79502436cf5a27da3c1f7fa83c7e285444fc93fd03", size = 531786, upload-time = "2026-07-08T12:25:07.658Z" }, + { url = "https://files.pythonhosted.org/packages/36/11/69ac3b54766ffba5fd7e5acebfb048d66dbe1f9f2d14516c2b3edc59cf87/librt-0.13.0-cp312-cp312-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fadc63331f4388c3dc90090448f682a7e9feafc11481391c1e94f2f907a3976e", size = 524393, upload-time = "2026-07-08T12:25:09.121Z" }, + { url = "https://files.pythonhosted.org/packages/61/5f/d72f95fd444a926a3c14b4e24979474116988dd57a45be242077c45d3c22/librt-0.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:70d9c62a4cffd9f23396cd5ef93fc5d11b31596b9b7d6306074abe3d5fcf09bd", size = 543026, upload-time = "2026-07-08T12:25:10.459Z" }, + { url = "https://files.pythonhosted.org/packages/c4/08/dcd9993ad192737a004ba263d549f8ea605b326b952e7d6205c7d4170b76/librt-0.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66c0e7e6b02a155576df2c77ec933a70b72da726e248c494abf690923e624348", size = 546829, upload-time = "2026-07-08T12:25:11.716Z" }, + { url = "https://files.pythonhosted.org/packages/96/d5/6d9bb2f54e4109a956b7128836529653eb9d740f784bc47ed10a02c1000e/librt-0.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ac04bcd3328eb91d99dfedf6a60d9c1f15d3434e6f6daf922f0420f7d90b85c7", size = 535700, upload-time = "2026-07-08T12:25:13.144Z" }, + { url = "https://files.pythonhosted.org/packages/8c/f2/10946922503858a359492fa27f13e86228bde702116a740ac7b3cd185f24/librt-0.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:db327e7271e653c32040b85ae6188059c924b57d7e1e29f935523fa017cd4e82", size = 573566, upload-time = "2026-07-08T12:25:14.336Z" }, + { url = "https://files.pythonhosted.org/packages/48/a8/94f00e3c99479a18088af3685ea016c42f3c7d5d1964d8dbb40c08d7f1aa/librt-0.13.0-cp312-cp312-win32.whl", hash = "sha256:860bd1d8ba48456ce08feaf8d343a8aaeb2fa086f2bcaa2a923fa3f7a3ff9aa3", size = 106099, upload-time = "2026-07-08T12:25:16.159Z" }, + { url = "https://files.pythonhosted.org/packages/c9/7b/2da9c74c1ed25a89cc4e1c8e007ea2eb4a0f1fafa3e70d757fe3242c5c5c/librt-0.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:e54a315caf843c8d77e388cadc56ea9ded569935ee2d2347d7ea94992e5aa6fa", size = 126934, upload-time = "2026-07-08T12:25:17.275Z" }, + { url = "https://files.pythonhosted.org/packages/d0/65/aead61bbf3b5358593f9d4779d2a0e88eaf6ec191a6342dde36dd1df6371/librt-0.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:c718e99a0992127af84385378460db624103b559ab260435abcfe77a4e4ed1c1", size = 112236, upload-time = "2026-07-08T12:25:18.425Z" }, + { url = "https://files.pythonhosted.org/packages/67/3b/18e7b63255297a2bdc9c25c8d6d4ca8eca9f63aceb1252c0f7427ac7099e/librt-0.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a468951af16155824e88bdd8326ebe5bdb371f3ec0ac04642994b98201d914f3", size = 151027, upload-time = "2026-07-08T12:25:19.638Z" }, + { url = "https://files.pythonhosted.org/packages/4d/68/e2248452c00d1a03b45fee1752cdc8f790a476efd2402b75181da88a9e61/librt-0.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ae01d8512cc17079e53425635327dbf3f7ff57a42c00dec348bf79791c56444c", size = 155152, upload-time = "2026-07-08T12:25:20.851Z" }, + { url = "https://files.pythonhosted.org/packages/0e/16/52b1c99bf19057a062aac39c900cbb81499f6f75d6c537c14463d247ba78/librt-0.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:32c26893cd085c1efe83219e78d866da23fb20a066101b8f68210004361d224c", size = 502499, upload-time = "2026-07-08T12:25:22.055Z" }, + { url = "https://files.pythonhosted.org/packages/9f/54/b811151805c795f55e0dedee6ec687b75f9982a8105d240ea3910737a77b/librt-0.13.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:5929da1981a46bcf4b28b1b9499905f0ff58e2419da402a048234e9783acbc4b", size = 496108, upload-time = "2026-07-08T12:25:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/8f/f8/094d6b2bd93f3fdaa54db54cc788c4a365333bddad65ab02e04da0b1d004/librt-0.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:94b85d664d777bab6c0d709416cb42938251fda9e221b79e3a2215d85df5f4f9", size = 531576, upload-time = "2026-07-08T12:25:24.648Z" }, + { url = "https://files.pythonhosted.org/packages/2e/40/541733d5755824f968f7ec39d78ffbd75d145964157ae5e69a09ec6d7326/librt-0.13.0-cp313-cp313-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:531b2df3e9fe96b1fcf73a6d165921e4656be5f58d631d384ebce344298368db", size = 524390, upload-time = "2026-07-08T12:25:25.898Z" }, + { url = "https://files.pythonhosted.org/packages/c6/b5/255673cfdbf5ba663339d36cd863c897289ab4337577e19f9405ce059f36/librt-0.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:109b84a9edf69ad89dc1f66358659e14a031baca95e3e5b0060bd903ede8efd6", size = 543053, upload-time = "2026-07-08T12:25:27.436Z" }, + { url = "https://files.pythonhosted.org/packages/9e/11/ab5005e9c9850710f21e354201bf090646349d3fabf5f951eaf70235729e/librt-0.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1304368a3e7ffc3e9db986796cc5326fdb5943a3567ecc137cff318e4240c0e7", size = 546387, upload-time = "2026-07-08T12:25:28.65Z" }, + { url = "https://files.pythonhosted.org/packages/a2/04/a5d7ce1d1df1afd15ca283dcdf7530ac073e12d69ae8c40879dda96f7868/librt-0.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e4f9b472e7d308d94b62c801982065661158c6ed02790d6c7ddb4337cea0f9c1", size = 535970, upload-time = "2026-07-08T12:25:30.171Z" }, + { url = "https://files.pythonhosted.org/packages/5a/76/927e267a6daa290174ac281b23c9804c8829b042ade9c6f24a065f540958/librt-0.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f836c37478f167a81200d8c8b2c920a22224564bed2c23d7aeec760965c367a", size = 573582, upload-time = "2026-07-08T12:25:31.507Z" }, + { url = "https://files.pythonhosted.org/packages/10/24/b6c5213efe39c19f9e13605644d0cf063b4ddaa33ac2e45b088e23a70e2e/librt-0.13.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl", hash = "sha256:4000d961ff9598ac6ea603c6c836a5ed49bc205ade5fc378b998dfe1e2c36628", size = 82189, upload-time = "2026-07-08T12:25:32.675Z" }, + { url = "https://files.pythonhosted.org/packages/4c/00/d29736be177a906ac0b84a5b04b4fbfa22c776dc2f366de4172b0f968c08/librt-0.13.0-cp313-cp313-win32.whl", hash = "sha256:79e44cff71750d299d61a678e49995b0d5935a9cda238c2574daeca3ba536927", size = 106193, upload-time = "2026-07-08T12:25:33.692Z" }, + { url = "https://files.pythonhosted.org/packages/c8/ac/aff6fb45393cb8912f39dfb156ef6b2d1cadb207ff465fc8f66141054be8/librt-0.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:54dab44a847d5ad1acd05c8a83fe518ae685516ecf4d3f7cc6e3df2a66767650", size = 126962, upload-time = "2026-07-08T12:25:34.769Z" }, + { url = "https://files.pythonhosted.org/packages/d9/3a/d68cb2b334d53fd30fac81d3a489ce4ba0d9506f4df43fcf676b68352b19/librt-0.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:d4cb6fbfdf874340ab5e51450753c0f817b6958a3621125ee695bbc3de866566", size = 112127, upload-time = "2026-07-08T12:25:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/7b/66/f49ae0d592bd45b6941e9a8bafcb6a87cddcd501ee7874707e767f01b585/librt-0.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:25218d94b1d2cbc0ba1d8a3f9dc9af578d9646e5ed16443a70cde1dfdcce6d71", size = 149818, upload-time = "2026-07-08T12:25:37.203Z" }, + { url = "https://files.pythonhosted.org/packages/3d/50/51c76d74014d04fb95b6506d286808984b78a2f7a41039094e6b2194ac48/librt-0.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f26629539d4893c2957a16c41bb058e1e135c1f150f6a2e25ed047f64cf3f5c6", size = 154071, upload-time = "2026-07-08T12:25:39.399Z" }, + { url = "https://files.pythonhosted.org/packages/b8/fe/f19b0f5f82d5a1f2da736586bc840abd00ce07d6388136ae80b7333883fc/librt-0.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a4517d47b2b8af26975a406fba7d314de9696d864252e0257c6ea90238cfe27f", size = 494168, upload-time = "2026-07-08T12:25:40.641Z" }, + { url = "https://files.pythonhosted.org/packages/94/bc/b8550c75775127fd31a5f20e8775997f7b527ad661fc8ddccd7497c064f7/librt-0.13.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:f19e181de5b3a1148bb3420b8c4b0b0ea0fce6950099724ad151d6cea5acc180", size = 491054, upload-time = "2026-07-08T12:25:41.905Z" }, + { url = "https://files.pythonhosted.org/packages/30/14/4d0204867623df3f33f86efd3d3692ba5e01321443f4d6eab35a22697618/librt-0.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22034924f5b42d5a56371cf271771bfeaabf235a7a8b6264bef2d20013f786c6", size = 523006, upload-time = "2026-07-08T12:25:43.327Z" }, + { url = "https://files.pythonhosted.org/packages/19/0a/c45fc9a260934696bace1ac5df1e148ac92bd71767aee3bf7cd7a4534f4c/librt-0.13.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c7897db4e95e22468bdda33d8e012ceacd0182abf001e6389d763f0def6286b9", size = 515058, upload-time = "2026-07-08T12:25:44.541Z" }, + { url = "https://files.pythonhosted.org/packages/13/0a/50c5ce45b326854ef8fa6ae4c36cf5142e5c55315eaf9e51d0ae73ac4da3/librt-0.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1ce61b3746545029d4f5c17d6bd74b676254ad98433086c846ffb5e8fa73f007", size = 534025, upload-time = "2026-07-08T12:25:45.825Z" }, + { url = "https://files.pythonhosted.org/packages/89/2d/08c413c8f93fc13b8103624fce38e5caa86cd08cbbc8465870ab287af54b/librt-0.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:46c330e82565962c761dbce7941be2cff7db674ee807455a8d0cadc5f9b759b0", size = 540557, upload-time = "2026-07-08T12:25:47.059Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c1/93af71fb4a364952210051811dd4e40174e79656b050c89cacac18af3330/librt-0.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:375f5af8f99cbaa99dd293af986e3d57caabc9ba81a5d3f021603764854197a1", size = 523201, upload-time = "2026-07-08T12:25:48.392Z" }, + { url = "https://files.pythonhosted.org/packages/c1/6e/9766f07b676a4889d9f8bc2864e9ba5fff165653143ef4dda7df6aa34d16/librt-0.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9320d34c3376ae204b2cd176e8d4883a013934e0aef822f1aed9c536490c275d", size = 565740, upload-time = "2026-07-08T12:25:49.678Z" }, + { url = "https://files.pythonhosted.org/packages/a2/1e/664e3472ce2b6e10e9b83f29d4a36eb982ff6b5a169ae7567bba3a4c4ff5/librt-0.13.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:9af313c66157a69dc69ea0059a66961692250e0dc95af9c385a48ffb770a0d16", size = 81611, upload-time = "2026-07-08T12:25:50.857Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d4/8582a4d65e2234673685e07309d02c230b28a85724eb0acbf13f019b7f6e/librt-0.13.0-cp314-cp314-win32.whl", hash = "sha256:f2a7253458e34f33543551394ae4fe104b497ec2a65ac266074de64c1df82e37", size = 100106, upload-time = "2026-07-08T12:25:52.03Z" }, + { url = "https://files.pythonhosted.org/packages/63/ce/0cb99efe6086b46cd985dc26672166fae312a239690e75871f7fafbd3fc5/librt-0.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:a3dfe4edf10e8ed7e55b026a8bfc2c2a8704218b659cd4bffdf604fab966dc39", size = 121209, upload-time = "2026-07-08T12:25:53.166Z" }, + { url = "https://files.pythonhosted.org/packages/26/85/4f3ccb083a3c9b0d42e223acdb3c3f507953324a59cdcab4826e8e2e3b89/librt-0.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:68a5faee4bba381cb93b5961f684a514cf0053cb92308ff9c792c2fea0b174c6", size = 106404, upload-time = "2026-07-08T12:25:54.253Z" }, + { url = "https://files.pythonhosted.org/packages/b2/77/333191499538c8e8189de7a4cba8e6f49ee949fd6d6e6324b21fd1522466/librt-0.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a38fb81d8376dfa2f8963b265fec07637802b0d01e2a127c19c66cb070fb24f5", size = 159231, upload-time = "2026-07-08T12:25:55.432Z" }, + { url = "https://files.pythonhosted.org/packages/7a/9e/2aa83758f22c278b837a1d8025898434ce2b8bff36678d5330ecaef56dff/librt-0.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d4c8d9bd5abce34b2e75edb3bf37ab0f34e49b1f915a40ae8468eb7c85bc5b46", size = 161300, upload-time = "2026-07-08T12:25:56.585Z" }, + { url = "https://files.pythonhosted.org/packages/bb/c0/86791e936553ca763d6b3c2fb4d31d596cd00e14fa631c283a40ba01559a/librt-0.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:387e2f1d27e89bffe0d3f520f0da0662c973fd607ca16c1808f8a5085419485e", size = 582056, upload-time = "2026-07-08T12:25:58.144Z" }, + { url = "https://files.pythonhosted.org/packages/a8/d3/a9ec15984a185e000c4d2a16ba28bd623124ad4c38a10974c7ff78e3a893/librt-0.13.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:4f6db193d2e5e0ed60359b9a5a682cd67205d0d3b1e459a867dd4b5c4e7eaa7a", size = 562758, upload-time = "2026-07-08T12:25:59.544Z" }, + { url = "https://files.pythonhosted.org/packages/3c/af/dbe36b78b19c06a55097f99305e4ea9458e2273e6ae16a3cbecaad7ee978/librt-0.13.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d38604854e8d22faadf683ec6c02bb0f886e2ba56ef981a1c36ee275f21ea22", size = 602095, upload-time = "2026-07-08T12:26:00.991Z" }, + { url = "https://files.pythonhosted.org/packages/2a/a8/2966891b4dd2830f5203fbee92ac2c4947653a2390ba73dfa44244fad025/librt-0.13.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:371f7ce73026815dafd51c50ce38416e91428b28c4b2ec97cd39271164b0045c", size = 593452, upload-time = "2026-07-08T12:26:02.352Z" }, + { url = "https://files.pythonhosted.org/packages/61/f5/4df8bfc8405ecf8c0d525b4d69636f694bdd8620b313ec8b76e54a5926cc/librt-0.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3aaedf52171bee90860704c560bc798fe83b76247df47568e0197e9b13c735a0", size = 623729, upload-time = "2026-07-08T12:26:04.294Z" }, + { url = "https://files.pythonhosted.org/packages/d6/13/9ac202dffc8db06f75d06c08c2f9f6ff054be67d21272dcc078fa1cc0c57/librt-0.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:96bad8725a4f196a798366c25ce075d1f7543a4ec045ffc13e6a7ec095cdab04", size = 617077, upload-time = "2026-07-08T12:26:05.845Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f0/ebe38610716aee5cb28efd95089bb90192096179802779381e1c5dcf239c/librt-0.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:6bf6a559ffe4a93bbea6cf31ddf01a7fd9ba342ef51f27beb178e318b74acd61", size = 599561, upload-time = "2026-07-08T12:26:07.21Z" }, + { url = "https://files.pythonhosted.org/packages/4f/5c/c2e72e236fff7abc716d5b1753b8b8cd3ea85ac46fe17d2e7c51d4e1c723/librt-0.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:301067672387902c55f94b51d5022304b36c966ea9fe1f21caab99a9bef487c9", size = 645511, upload-time = "2026-07-08T12:26:08.562Z" }, + { url = "https://files.pythonhosted.org/packages/0c/99/6203ce619dee940d6bfbe099ec3fe4be00a68e9d60f70abf906cf124fe66/librt-0.13.0-cp314-cp314t-win32.whl", hash = "sha256:5fdcf34f86de8fb66d7dc7589f96ba91c4aa46671200d400e6fd6f109a483f18", size = 104357, upload-time = "2026-07-08T12:26:09.828Z" }, + { url = "https://files.pythonhosted.org/packages/52/dd/843b6314087c41657c7036d7914d8f294bdf9b580aa8513ea0588c8e9a3d/librt-0.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:260c33e92263fa629b4f6d3c51967a1c2158fe6c33237aaa3ebeac586b085259", size = 126998, upload-time = "2026-07-08T12:26:10.975Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5d/3dcec2884ba1b0806d1408612555c38dd5d68e90156b59f75f6e36435c3a/librt-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2f281549a4c52ac7bb97997f14353f8bd0e53a34ca0dad1c905cfd0b4a58ae99", size = 110771, upload-time = "2026-07-08T12:26:12.303Z" }, ] [[package]] name = "markdown-it-py" version = "4.0.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.11'", - "python_full_version == '3.10.*'", -] dependencies = [ - { name = "mdurl", marker = "python_full_version >= '3.10'" }, + { name = "mdurl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } wheels = [ @@ -573,70 +674,87 @@ wheels = [ [[package]] name = "markupsafe" -version = "3.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357, upload-time = "2024-10-18T15:20:51.44Z" }, - { url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", size = 12393, upload-time = "2024-10-18T15:20:52.426Z" }, - { url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", size = 21732, upload-time = "2024-10-18T15:20:53.578Z" }, - { url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", size = 20866, upload-time = "2024-10-18T15:20:55.06Z" }, - { url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", size = 20964, upload-time = "2024-10-18T15:20:55.906Z" }, - { url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", size = 21977, upload-time = "2024-10-18T15:20:57.189Z" }, - { url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", size = 21366, upload-time = "2024-10-18T15:20:58.235Z" }, - { url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", size = 21091, upload-time = "2024-10-18T15:20:59.235Z" }, - { url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50", size = 15065, upload-time = "2024-10-18T15:21:00.307Z" }, - { url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", size = 15514, upload-time = "2024-10-18T15:21:01.122Z" }, - { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353, upload-time = "2024-10-18T15:21:02.187Z" }, - { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392, upload-time = "2024-10-18T15:21:02.941Z" }, - { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984, upload-time = "2024-10-18T15:21:03.953Z" }, - { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120, upload-time = "2024-10-18T15:21:06.495Z" }, - { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032, upload-time = "2024-10-18T15:21:07.295Z" }, - { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057, upload-time = "2024-10-18T15:21:08.073Z" }, - { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359, upload-time = "2024-10-18T15:21:09.318Z" }, - { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306, upload-time = "2024-10-18T15:21:10.185Z" }, - { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094, upload-time = "2024-10-18T15:21:11.005Z" }, - { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521, upload-time = "2024-10-18T15:21:12.911Z" }, - { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, - { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, - { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, - { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, - { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, - { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, - { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, - { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, - { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, - { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, - { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, - { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, - { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, - { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, - { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, - { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, - { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, - { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, - { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, - { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, - { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, - { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, - { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, - { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, - { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, - { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, - { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, - { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, - { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, - { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, - { url = "https://files.pythonhosted.org/packages/a7/ea/9b1530c3fdeeca613faeb0fb5cbcf2389d816072fab72a71b45749ef6062/MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", size = 14344, upload-time = "2024-10-18T15:21:43.721Z" }, - { url = "https://files.pythonhosted.org/packages/4b/c2/fbdbfe48848e7112ab05e627e718e854d20192b674952d9042ebd8c9e5de/MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", size = 12389, upload-time = "2024-10-18T15:21:44.666Z" }, - { url = "https://files.pythonhosted.org/packages/f0/25/7a7c6e4dbd4f867d95d94ca15449e91e52856f6ed1905d58ef1de5e211d0/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", size = 21607, upload-time = "2024-10-18T15:21:45.452Z" }, - { url = "https://files.pythonhosted.org/packages/53/8f/f339c98a178f3c1e545622206b40986a4c3307fe39f70ccd3d9df9a9e425/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", size = 20728, upload-time = "2024-10-18T15:21:46.295Z" }, - { url = "https://files.pythonhosted.org/packages/1a/03/8496a1a78308456dbd50b23a385c69b41f2e9661c67ea1329849a598a8f9/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", size = 20826, upload-time = "2024-10-18T15:21:47.134Z" }, - { url = "https://files.pythonhosted.org/packages/e6/cf/0a490a4bd363048c3022f2f475c8c05582179bb179defcee4766fb3dcc18/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", size = 21843, upload-time = "2024-10-18T15:21:48.334Z" }, - { url = "https://files.pythonhosted.org/packages/19/a3/34187a78613920dfd3cdf68ef6ce5e99c4f3417f035694074beb8848cd77/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", size = 21219, upload-time = "2024-10-18T15:21:49.587Z" }, - { url = "https://files.pythonhosted.org/packages/17/d8/5811082f85bb88410ad7e452263af048d685669bbbfb7b595e8689152498/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", size = 20946, upload-time = "2024-10-18T15:21:50.441Z" }, - { url = "https://files.pythonhosted.org/packages/7c/31/bd635fb5989440d9365c5e3c47556cfea121c7803f5034ac843e8f37c2f2/MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", size = 15063, upload-time = "2024-10-18T15:21:51.385Z" }, - { url = "https://files.pythonhosted.org/packages/b3/73/085399401383ce949f727afec55ec3abd76648d04b9f22e1c0e99cb4bec3/MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", size = 15506, upload-time = "2024-10-18T15:21:52.974Z" }, +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" }, + { url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" }, + { url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" }, + { url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" }, + { url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" }, + { url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" }, + { url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" }, + { url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" }, + { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, + { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, + { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, ] [[package]] @@ -659,53 +777,62 @@ wheels = [ [[package]] name = "mypy" -version = "1.17.1" +version = "2.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "ast-serialize" }, + { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, { name = "mypy-extensions" }, { name = "pathspec" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8e/22/ea637422dedf0bf36f3ef238eab4e455e2a0dcc3082b5cc067615347ab8e/mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01", size = 3352570, upload-time = "2025-07-31T07:54:19.204Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/77/a9/3d7aa83955617cdf02f94e50aab5c830d205cfa4320cf124ff64acce3a8e/mypy-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3fbe6d5555bf608c47203baa3e72dbc6ec9965b3d7c318aa9a4ca76f465bd972", size = 11003299, upload-time = "2025-07-31T07:54:06.425Z" }, - { url = "https://files.pythonhosted.org/packages/83/e8/72e62ff837dd5caaac2b4a5c07ce769c8e808a00a65e5d8f94ea9c6f20ab/mypy-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:80ef5c058b7bce08c83cac668158cb7edea692e458d21098c7d3bce35a5d43e7", size = 10125451, upload-time = "2025-07-31T07:53:52.974Z" }, - { url = "https://files.pythonhosted.org/packages/7d/10/f3f3543f6448db11881776f26a0ed079865926b0c841818ee22de2c6bbab/mypy-1.17.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4a580f8a70c69e4a75587bd925d298434057fe2a428faaf927ffe6e4b9a98df", size = 11916211, upload-time = "2025-07-31T07:53:18.879Z" }, - { url = "https://files.pythonhosted.org/packages/06/bf/63e83ed551282d67bb3f7fea2cd5561b08d2bb6eb287c096539feb5ddbc5/mypy-1.17.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd86bb649299f09d987a2eebb4d52d10603224500792e1bee18303bbcc1ce390", size = 12652687, upload-time = "2025-07-31T07:53:30.544Z" }, - { url = "https://files.pythonhosted.org/packages/69/66/68f2eeef11facf597143e85b694a161868b3b006a5fbad50e09ea117ef24/mypy-1.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a76906f26bd8d51ea9504966a9c25419f2e668f012e0bdf3da4ea1526c534d94", size = 12896322, upload-time = "2025-07-31T07:53:50.74Z" }, - { url = "https://files.pythonhosted.org/packages/a3/87/8e3e9c2c8bd0d7e071a89c71be28ad088aaecbadf0454f46a540bda7bca6/mypy-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:e79311f2d904ccb59787477b7bd5d26f3347789c06fcd7656fa500875290264b", size = 9507962, upload-time = "2025-07-31T07:53:08.431Z" }, - { url = "https://files.pythonhosted.org/packages/46/cf/eadc80c4e0a70db1c08921dcc220357ba8ab2faecb4392e3cebeb10edbfa/mypy-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad37544be07c5d7fba814eb370e006df58fed8ad1ef33ed1649cb1889ba6ff58", size = 10921009, upload-time = "2025-07-31T07:53:23.037Z" }, - { url = "https://files.pythonhosted.org/packages/5d/c1/c869d8c067829ad30d9bdae051046561552516cfb3a14f7f0347b7d973ee/mypy-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:064e2ff508e5464b4bd807a7c1625bc5047c5022b85c70f030680e18f37273a5", size = 10047482, upload-time = "2025-07-31T07:53:26.151Z" }, - { url = "https://files.pythonhosted.org/packages/98/b9/803672bab3fe03cee2e14786ca056efda4bb511ea02dadcedde6176d06d0/mypy-1.17.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70401bbabd2fa1aa7c43bb358f54037baf0586f41e83b0ae67dd0534fc64edfd", size = 11832883, upload-time = "2025-07-31T07:53:47.948Z" }, - { url = "https://files.pythonhosted.org/packages/88/fb/fcdac695beca66800918c18697b48833a9a6701de288452b6715a98cfee1/mypy-1.17.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e92bdc656b7757c438660f775f872a669b8ff374edc4d18277d86b63edba6b8b", size = 12566215, upload-time = "2025-07-31T07:54:04.031Z" }, - { url = "https://files.pythonhosted.org/packages/7f/37/a932da3d3dace99ee8eb2043b6ab03b6768c36eb29a02f98f46c18c0da0e/mypy-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c1fdf4abb29ed1cb091cf432979e162c208a5ac676ce35010373ff29247bcad5", size = 12751956, upload-time = "2025-07-31T07:53:36.263Z" }, - { url = "https://files.pythonhosted.org/packages/8c/cf/6438a429e0f2f5cab8bc83e53dbebfa666476f40ee322e13cac5e64b79e7/mypy-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:ff2933428516ab63f961644bc49bc4cbe42bbffb2cd3b71cc7277c07d16b1a8b", size = 9507307, upload-time = "2025-07-31T07:53:59.734Z" }, - { url = "https://files.pythonhosted.org/packages/17/a2/7034d0d61af8098ec47902108553122baa0f438df8a713be860f7407c9e6/mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb", size = 11086295, upload-time = "2025-07-31T07:53:28.124Z" }, - { url = "https://files.pythonhosted.org/packages/14/1f/19e7e44b594d4b12f6ba8064dbe136505cec813549ca3e5191e40b1d3cc2/mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403", size = 10112355, upload-time = "2025-07-31T07:53:21.121Z" }, - { url = "https://files.pythonhosted.org/packages/5b/69/baa33927e29e6b4c55d798a9d44db5d394072eef2bdc18c3e2048c9ed1e9/mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056", size = 11875285, upload-time = "2025-07-31T07:53:55.293Z" }, - { url = "https://files.pythonhosted.org/packages/90/13/f3a89c76b0a41e19490b01e7069713a30949d9a6c147289ee1521bcea245/mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341", size = 12737895, upload-time = "2025-07-31T07:53:43.623Z" }, - { url = "https://files.pythonhosted.org/packages/23/a1/c4ee79ac484241301564072e6476c5a5be2590bc2e7bfd28220033d2ef8f/mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb", size = 12931025, upload-time = "2025-07-31T07:54:17.125Z" }, - { url = "https://files.pythonhosted.org/packages/89/b8/7409477be7919a0608900e6320b155c72caab4fef46427c5cc75f85edadd/mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19", size = 9584664, upload-time = "2025-07-31T07:54:12.842Z" }, - { url = "https://files.pythonhosted.org/packages/5b/82/aec2fc9b9b149f372850291827537a508d6c4d3664b1750a324b91f71355/mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7", size = 11075338, upload-time = "2025-07-31T07:53:38.873Z" }, - { url = "https://files.pythonhosted.org/packages/07/ac/ee93fbde9d2242657128af8c86f5d917cd2887584cf948a8e3663d0cd737/mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81", size = 10113066, upload-time = "2025-07-31T07:54:14.707Z" }, - { url = "https://files.pythonhosted.org/packages/5a/68/946a1e0be93f17f7caa56c45844ec691ca153ee8b62f21eddda336a2d203/mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6", size = 11875473, upload-time = "2025-07-31T07:53:14.504Z" }, - { url = "https://files.pythonhosted.org/packages/9f/0f/478b4dce1cb4f43cf0f0d00fba3030b21ca04a01b74d1cd272a528cf446f/mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849", size = 12744296, upload-time = "2025-07-31T07:53:03.896Z" }, - { url = "https://files.pythonhosted.org/packages/ca/70/afa5850176379d1b303f992a828de95fc14487429a7139a4e0bdd17a8279/mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14", size = 12914657, upload-time = "2025-07-31T07:54:08.576Z" }, - { url = "https://files.pythonhosted.org/packages/53/f9/4a83e1c856a3d9c8f6edaa4749a4864ee98486e9b9dbfbc93842891029c2/mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a", size = 9593320, upload-time = "2025-07-31T07:53:01.341Z" }, - { url = "https://files.pythonhosted.org/packages/38/56/79c2fac86da57c7d8c48622a05873eaab40b905096c33597462713f5af90/mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733", size = 11040037, upload-time = "2025-07-31T07:54:10.942Z" }, - { url = "https://files.pythonhosted.org/packages/4d/c3/adabe6ff53638e3cad19e3547268482408323b1e68bf082c9119000cd049/mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd", size = 10131550, upload-time = "2025-07-31T07:53:41.307Z" }, - { url = "https://files.pythonhosted.org/packages/b8/c5/2e234c22c3bdeb23a7817af57a58865a39753bde52c74e2c661ee0cfc640/mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0", size = 11872963, upload-time = "2025-07-31T07:53:16.878Z" }, - { url = "https://files.pythonhosted.org/packages/ab/26/c13c130f35ca8caa5f2ceab68a247775648fdcd6c9a18f158825f2bc2410/mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a", size = 12710189, upload-time = "2025-07-31T07:54:01.962Z" }, - { url = "https://files.pythonhosted.org/packages/82/df/c7d79d09f6de8383fe800521d066d877e54d30b4fb94281c262be2df84ef/mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91", size = 12900322, upload-time = "2025-07-31T07:53:10.551Z" }, - { url = "https://files.pythonhosted.org/packages/b8/98/3d5a48978b4f708c55ae832619addc66d677f6dc59f3ebad71bae8285ca6/mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed", size = 9751879, upload-time = "2025-07-31T07:52:56.683Z" }, - { url = "https://files.pythonhosted.org/packages/29/cb/673e3d34e5d8de60b3a61f44f80150a738bff568cd6b7efb55742a605e98/mypy-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5d1092694f166a7e56c805caaf794e0585cabdbf1df36911c414e4e9abb62ae9", size = 10992466, upload-time = "2025-07-31T07:53:57.574Z" }, - { url = "https://files.pythonhosted.org/packages/0c/d0/fe1895836eea3a33ab801561987a10569df92f2d3d4715abf2cfeaa29cb2/mypy-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79d44f9bfb004941ebb0abe8eff6504223a9c1ac51ef967d1263c6572bbebc99", size = 10117638, upload-time = "2025-07-31T07:53:34.256Z" }, - { url = "https://files.pythonhosted.org/packages/97/f3/514aa5532303aafb95b9ca400a31054a2bd9489de166558c2baaeea9c522/mypy-1.17.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b01586eed696ec905e61bd2568f48740f7ac4a45b3a468e6423a03d3788a51a8", size = 11915673, upload-time = "2025-07-31T07:52:59.361Z" }, - { url = "https://files.pythonhosted.org/packages/ab/c3/c0805f0edec96fe8e2c048b03769a6291523d509be8ee7f56ae922fa3882/mypy-1.17.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43808d9476c36b927fbcd0b0255ce75efe1b68a080154a38ae68a7e62de8f0f8", size = 12649022, upload-time = "2025-07-31T07:53:45.92Z" }, - { url = "https://files.pythonhosted.org/packages/45/3e/d646b5a298ada21a8512fa7e5531f664535a495efa672601702398cea2b4/mypy-1.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:feb8cc32d319edd5859da2cc084493b3e2ce5e49a946377663cc90f6c15fb259", size = 12895536, upload-time = "2025-07-31T07:53:06.17Z" }, - { url = "https://files.pythonhosted.org/packages/14/55/e13d0dcd276975927d1f4e9e2ec4fd409e199f01bdc671717e673cc63a22/mypy-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d7598cf74c3e16539d4e2f0b8d8c318e00041553d83d4861f87c7a72e95ac24d", size = 9512564, upload-time = "2025-07-31T07:53:12.346Z" }, - { url = "https://files.pythonhosted.org/packages/1d/f3/8fcd2af0f5b806f6cf463efaffd3c9548a28f84220493ecd38d127b6b66d/mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9", size = 2283411, upload-time = "2025-07-31T07:53:24.664Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/12/af/4e516a05d3ca2eb9283e9ec45b2c02225c1514dd6da49fd3c9eaa6639370/mypy-2.3.0.tar.gz", hash = "sha256:465965d41cd9a2726694e983e8ce7113259327bec798115d1e1dfa2a52fb666e", size = 3988104, upload-time = "2026-07-13T11:34:53.387Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/09/f2f5f45dae0c9a0891e4751a73312730e009395102e5d72a22a976cca41f/mypy-2.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1fa8d916ac3b705af733c4c1e6c9ebe38fd0d52beb15b105c3e8355b55e6ecdc", size = 14927774, upload-time = "2026-07-13T11:28:38.224Z" }, + { url = "https://files.pythonhosted.org/packages/56/b9/345367effd3a6877275a94d481614bfca983f45e028c6290e2cc54603811/mypy-2.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:28e1e2af8cd8fff551fd30f2fe4b03fb76764ac8b1ba6c6a1bd00ad32b412db3", size = 14000127, upload-time = "2026-07-13T11:30:19.57Z" }, + { url = "https://files.pythonhosted.org/packages/99/6c/a10b7a7b9f0a755fb94e27ae834d4cea9ad6c5221f9325eef8f182641feb/mypy-2.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3e77244df3843048c3f927182916730e40c124cbaa43905c1fb86cb382aa0805", size = 14229437, upload-time = "2026-07-13T11:28:17.765Z" }, + { url = "https://files.pythonhosted.org/packages/d9/bd/a26a602acb1bbf849fa4bdac4bc657ee2f11c0c2a764a2cc87a5304e865c/mypy-2.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9559ab18a9c9957dfa3004ab57cd4bac5f26a724329a9584e583367f0c2e1117", size = 15171457, upload-time = "2026-07-13T11:29:01.834Z" }, + { url = "https://files.pythonhosted.org/packages/7f/14/124f462bef69bcbc90b9358088460b6091954a3e004852fcd9948db617a5/mypy-2.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:09abd66d8685e73f8f7d17b847c3e104d9a7b164a8706ea87d6c96a3d45816d5", size = 15478281, upload-time = "2026-07-13T11:32:23.413Z" }, + { url = "https://files.pythonhosted.org/packages/db/a4/8bdca6a8ac8d856d82ed049144af2721245a135c2e8001d3890c93975852/mypy-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e91adad1ca81742ac7ef9893959911df867752206b37135185e88dfb3c89494", size = 11148008, upload-time = "2026-07-13T11:34:17.332Z" }, + { url = "https://files.pythonhosted.org/packages/83/41/490eea348e60ba50decec20bc750605444149a5d7a8cc560042f90ba2c75/mypy-2.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:6f99ec626e3c3a2f7c0b22c5b90ddb5dabb1c18729c971e9bdaca1f1766d2cee", size = 10142329, upload-time = "2026-07-13T11:32:52.116Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b9/d75b3082b05f1b3028828aeb18e74ae5ab0a0936051bbf1f32f59f654747/mypy-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3419d00717afbc5265b50dd14b1278f29ea4884dd398ab67873489ac093fd329", size = 14838725, upload-time = "2026-07-13T11:32:44.655Z" }, + { url = "https://files.pythonhosted.org/packages/a9/50/79a65c6ea6e115bc73296038a4543b2d5c91f07912b918a2c616a2514bba/mypy-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cfca8ee88544090f86b6dcce05ec55d66eb48a762412ac2507810ba4bd793b6f", size = 13911128, upload-time = "2026-07-13T11:32:02.021Z" }, + { url = "https://files.pythonhosted.org/packages/90/48/e11ed7716c26953ca321f726e452e374dbf81a6f2b8b212ec02af29b6b8f/mypy-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75cbb4b9ef04a0c84a957f07abc4504fbf64b8dcc145675101f2d3a78a4b1d6a", size = 14146742, upload-time = "2026-07-13T11:33:03.313Z" }, + { url = "https://files.pythonhosted.org/packages/06/72/6807565b1c4861ef66f7fdd98b51c61556356eab80235717b46c53bb8627/mypy-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:982e3d53dd23d0a4cef67dd66791fdbede0cf38f9eb617bf47663554c51e1e36", size = 15081418, upload-time = "2026-07-13T11:31:13.899Z" }, + { url = "https://files.pythonhosted.org/packages/00/80/1ea14c5d80e589e415973db3e47c78c2219a305b808b2b506395342c1d79/mypy-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:85c5385b93012ffa3b31479ab579aef5415f4f3a32c6cf1ae07a984d2a0ff461", size = 15328164, upload-time = "2026-07-13T11:31:35.723Z" }, + { url = "https://files.pythonhosted.org/packages/37/28/8223157404a3d51920078459c37f80fbdc590e1d8ea049dc5ce48643022a/mypy-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:13b1b16e2fa39f3b2e33fb1c468abc7a69369fa2e886b4b87b5afc81472325cd", size = 11136472, upload-time = "2026-07-13T11:27:37.018Z" }, + { url = "https://files.pythonhosted.org/packages/6f/cc/ea27e5959c5f258585a756b252031f3b313583d81b5064b2bebc41d3706b/mypy-2.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:b5cd2f027a972a4a5f2278a11fac9747f5f81a53a30b714d74950b6807e55568", size = 10135800, upload-time = "2026-07-13T11:30:08.92Z" }, + { url = "https://files.pythonhosted.org/packages/dc/94/0e7e592619e2133596a47cdd642534b0456545c218430bd3b9d8fefdd1b1/mypy-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2d53fc67b9d28a43c6199077f49fea0f05839e36cf6158500331c9549225e5a5", size = 15026523, upload-time = "2026-07-13T11:34:49.206Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/1e1731df090a857df2807177a4626863e5ac0f0256513c35780efe53986f/mypy-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fbc00cee7bdbb9291979ddc9d08034a29dfcda4932628c9bbc28c1edd589df0c", size = 14032189, upload-time = "2026-07-13T11:33:57.168Z" }, + { url = "https://files.pythonhosted.org/packages/44/95/cab921f4a806e171f34113e6181dd23c55358ccf6a80741269ef594a410e/mypy-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:04e617030eca5221909c8b7d8d7fd1c637948199aa2100b2ad9813feb07e1491", size = 14198696, upload-time = "2026-07-13T11:32:12.767Z" }, + { url = "https://files.pythonhosted.org/packages/66/80/e6d008bb19fe446e3662d85e0e2717bf9f2d611a2164fb29d6e067dbf46c/mypy-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56c184d2c20ca6b6378d58d1960270a767f41f5e44acbbd27f05effef4f4e1d7", size = 15286904, upload-time = "2026-07-13T11:34:27.594Z" }, + { url = "https://files.pythonhosted.org/packages/db/83/94397c9293608a364aa03e8084fb34ede4ae976a260384b9b52929308135/mypy-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3961a4a34b05f7c74b0f05aa51fbfe99a2d1e126038df40318d15c8f558b7ef3", size = 15528342, upload-time = "2026-07-13T11:34:07.819Z" }, + { url = "https://files.pythonhosted.org/packages/cf/96/d8b37d819adec6cfccfb1fd3afc1735d94717ddeafb45536db9c6943e09b/mypy-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:b1942b9314d4c784b8ea1dbab4972603290e5dd5630f06675f13aec97526bc4c", size = 11218346, upload-time = "2026-07-13T11:28:27.745Z" }, + { url = "https://files.pythonhosted.org/packages/2b/cd/cd9f725b19b19e5b530a154cf9bcf9e94279c5d55b3c34fb42b3aa48ea1b/mypy-2.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:be51653d7669d7d7955d613b8d0bb57d5b652eaf71a873ddf65ac87254dd2595", size = 10204525, upload-time = "2026-07-13T11:31:02.552Z" }, + { url = "https://files.pythonhosted.org/packages/6e/ae/f7d056eb0294586a572d0d0d89580ec633c064db520f11d37d5a2fb833bd/mypy-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:91ad22a52ae2c7e621c2f67c94d5a17f66b3209a4cff5cf8a573579835c69e97", size = 14947298, upload-time = "2026-07-13T11:27:47.734Z" }, + { url = "https://files.pythonhosted.org/packages/32/d5/db3e7af01e7844d21662c6ddc1f7825ec7cb4053f0391ac02faf3638396f/mypy-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:99ac767cc5d3b64c8d0ae226ead10c96694f94e4e7da1668642225dcd4e75aac", size = 13950768, upload-time = "2026-07-13T11:27:57.726Z" }, + { url = "https://files.pythonhosted.org/packages/d9/fb/43c031f0190513d1ec248ed037eceb742ddd2a4d74bbf406658a28173837/mypy-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6d2c484742a4d7b0ed6d07b143375624d3b899c5749c7b3c947f56261f48a6", size = 14151586, upload-time = "2026-07-13T11:29:18.615Z" }, + { url = "https://files.pythonhosted.org/packages/ec/c3/f8b2ffc60883084da91be51af58e88a7ffd4ff9795acb7d902ff88d31eb1/mypy-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7da939dd335cfd2ad788bdfd081c9f4e47634ab995e5a45eb15fd1e5bc052f8b", size = 15227411, upload-time = "2026-07-13T11:30:29.904Z" }, + { url = "https://files.pythonhosted.org/packages/83/2e/16b917fc7adcf03f1aadddfc93aab804ffb234b1ab09c0ffd6d92a5d34a2/mypy-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7247eb2824f996722a949530183394921ca71deb9680052a338cf53cff7925c2", size = 15478790, upload-time = "2026-07-13T11:33:14.686Z" }, + { url = "https://files.pythonhosted.org/packages/c0/88/aaa65a93c73d0cdae7e42f8adb302bf6885bb281302084f99d0290a35347/mypy-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:75b0984bb3cbd76bb5c9291a8671f7ae66ca3b51c7584c358fc2e923259f0757", size = 11234919, upload-time = "2026-07-13T11:33:39.28Z" }, + { url = "https://files.pythonhosted.org/packages/35/19/b40de63f1a80e63bc2d40f0679a6a8dbd34e95176c8122119bdf406aa552/mypy-2.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:d78fcf900b59cb7e82cb7e3a235e31b462d9333d92285bd1e4952d355b8ffba1", size = 10201510, upload-time = "2026-07-13T11:31:52.619Z" }, + { url = "https://files.pythonhosted.org/packages/a4/58/fa0ae047da911f540284009b4f44b96fe09d83c076d7c103e9d645f46303/mypy-2.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ea317b060ce83e26050f8f9e4d7d6bf44ed7597c8ff9990bccffbb9d1d8522db", size = 14941909, upload-time = "2026-07-13T11:32:34.332Z" }, + { url = "https://files.pythonhosted.org/packages/15/14/2ba1d61452d7c2a7fe12741e8d374e52b183476b07aa7f9e2a0d02b0720a/mypy-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:094af99f92638aa92852326188b85a89e50f4a472f44827c03362228482f0762", size = 13967581, upload-time = "2026-07-13T11:30:00.587Z" }, + { url = "https://files.pythonhosted.org/packages/ed/5a/483fb9e5ffbbb1a28dccc7b0a13d141b17ac769b6c9f488c0a0c63698962/mypy-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de121747278144fc9ae7caa2e978cf5df12aebc82933182f5b3b86081a30baef", size = 14168807, upload-time = "2026-07-13T11:28:48.6Z" }, + { url = "https://files.pythonhosted.org/packages/ae/77/70d7a10732063beb74ad713682cf871e88f5c5fa39bfc8beff8a524bf9cb/mypy-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:37fa4de896a84e2dc9200d91e614c22563b43d1a266789d4bbac7b22ebe6192b", size = 15200144, upload-time = "2026-07-13T11:31:25.283Z" }, + { url = "https://files.pythonhosted.org/packages/56/72/766218ac783be4fdfcd699b90037b63017348a3e86fb2c1fbfb18302637d/mypy-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f1b3a98dfd21058bc759bb3337d5d1f61d0fdf9f3cf9c00f4291790fb5427bff", size = 15460389, upload-time = "2026-07-13T11:29:29.077Z" }, + { url = "https://files.pythonhosted.org/packages/38/4e/8a9db7411ecb8ec0cb1fd05dba432f28bafffcd38b4e887714a4a0506689/mypy-2.3.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:944c665d984157cb96a679dfb7a4a81dd1d36b24b9c284b699514e6e626b82d4", size = 7753664, upload-time = "2026-07-13T11:29:08.147Z" }, + { url = "https://files.pythonhosted.org/packages/65/4c/c3f8bfd6ed0e5e38b5a244403b27f821d433443df5a15a278417c10a3a3c/mypy-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:4359424140d985192c778c1ce2c114a10c1ca58a381ed79cfa70d37df94b299f", size = 11417237, upload-time = "2026-07-13T11:33:47.467Z" }, + { url = "https://files.pythonhosted.org/packages/3c/00/89a32eaf5ccf174bc4f90db0eaea5d70636c01b8d49f384bdab2e8834390/mypy-2.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:3dd0bed92c4bdec57c42505b96416fb9e6a5aa7be84d2809bcd5f2ecec2860d7", size = 10389252, upload-time = "2026-07-13T11:31:43.81Z" }, + { url = "https://files.pythonhosted.org/packages/31/56/104f93d69aa9f339b6b9d3b0a7faa699b8b466c942cf3ae86cc2a2ec0915/mypy-2.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:691fdc37132b1ae628d834f672e74de83462d9fb4aff621835767fb43a8dd373", size = 16385495, upload-time = "2026-07-13T11:29:49.818Z" }, + { url = "https://files.pythonhosted.org/packages/d2/03/f1d2123313f55efafdd27706960f43a771c62f1b68426c76043f3ab9ebf3/mypy-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:aec15d465d477558fd842757b487849007311cf3897849cdda0e3162ac0ac556", size = 15098155, upload-time = "2026-07-13T11:30:40.301Z" }, + { url = "https://files.pythonhosted.org/packages/e5/5d/d5f9200399b445e81726c4f23becee33f233aee81c72680b1ef3a258b641/mypy-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b352b7e49f5e6576009e8df730e1ff4f915cb565b851b396d2ffe2f5a6f5da88", size = 15514155, upload-time = "2026-07-13T11:34:38.569Z" }, + { url = "https://files.pythonhosted.org/packages/cd/ce/69977c555f08faa3190cfde44189b89dbd56861b1ab97aa18fc5f3a2e4a3/mypy-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c6c6bf687b17f90dbfcad95b960d32eaa0154c00da45f03ab50bf8952e047fe", size = 16766351, upload-time = "2026-07-13T11:33:29.195Z" }, + { url = "https://files.pythonhosted.org/packages/bc/92/6648b6caa3ab9e00f9ac0c2a78307805f873dd48139b24a6f6f7c3667bbf/mypy-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f4ed18f111bfe2d599bca7468e7f9251042c1c2118f762c8de2766a56d773c60", size = 17043490, upload-time = "2026-07-13T11:30:53.927Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ab/0dc91d80f3f016634c68d451f294a97320fe903a9b6f90b9e57b3f7f1717/mypy-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0b025a93cffb9781d231f232be07a17912f35f10a313c24f301c81e842870654", size = 12146869, upload-time = "2026-07-13T11:29:38.874Z" }, + { url = "https://files.pythonhosted.org/packages/85/b5/4c964d02634ba81f4d1c84838e5c5b18ab06d13ed568960f5d6318495ccc/mypy-2.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:adebc76aab4f3495a88b41d48aa4aff0c03f2822501da76625afcca5975f19e5", size = 10965113, upload-time = "2026-07-13T11:28:07.056Z" }, + { url = "https://files.pythonhosted.org/packages/2c/fa/fdc54fe583ba3cafbcedfb70eeeaf03849f75b1827a07096c7bd996f582d/mypy-2.3.0-py3-none-any.whl", hash = "sha256:6b1cdb579446b60432432b2b2403a6201b4b475a004d7f488511c9ba177c9e88", size = 2753292, upload-time = "2026-07-13T11:33:18.48Z" }, ] [[package]] @@ -719,11 +846,11 @@ wheels = [ [[package]] name = "nodeenv" -version = "1.9.1" +version = "1.10.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, ] [[package]] @@ -740,41 +867,41 @@ wheels = [ [[package]] name = "packaging" -version = "25.0" +version = "26.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, ] [[package]] name = "pathspec" -version = "0.12.1" +version = "1.0.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/b2/bb8e495d5262bfec41ab5cb18f522f1012933347fb5d9e62452d446baca2/pathspec-1.0.3.tar.gz", hash = "sha256:bac5cf97ae2c2876e2d25ebb15078eb04d76e4b98921ee31c6f85ade8b59444d", size = 130841, upload-time = "2026-01-09T15:46:46.009Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, + { url = "https://files.pythonhosted.org/packages/32/2b/121e912bd60eebd623f873fd090de0e84f322972ab25a7f9044c056804ed/pathspec-1.0.3-py3-none-any.whl", hash = "sha256:e80767021c1cc524aa3fb14bedda9c34406591343cc42797b386ce7b9354fb6c", size = 55021, upload-time = "2026-01-09T15:46:44.652Z" }, ] [[package]] name = "pbr" -version = "6.1.1" +version = "7.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "setuptools" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/01/d2/510cc0d218e753ba62a1bc1434651db3cd797a9716a0a66cc714cb4f0935/pbr-6.1.1.tar.gz", hash = "sha256:93ea72ce6989eb2eed99d0f75721474f69ad88128afdef5ac377eb797c4bf76b", size = 125702, upload-time = "2025-02-04T14:28:06.514Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/ab/1de9a4f730edde1bdbbc2b8d19f8fa326f036b4f18b2f72cfbea7dc53c26/pbr-7.0.3.tar.gz", hash = "sha256:b46004ec30a5324672683ec848aed9e8fc500b0d261d40a3229c2d2bbfcedc29", size = 135625, upload-time = "2025-11-03T17:04:56.274Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/47/ac/684d71315abc7b1214d59304e23a982472967f6bf4bde5a98f1503f648dc/pbr-6.1.1-py2.py3-none-any.whl", hash = "sha256:38d4daea5d9fa63b3f626131b9d34947fd0c8be9b05a29276870580050a25a76", size = 108997, upload-time = "2025-02-04T14:28:03.168Z" }, + { url = "https://files.pythonhosted.org/packages/c0/db/61efa0d08a99f897ef98256b03e563092d36cc38dc4ebe4a85020fe40b31/pbr-7.0.3-py2.py3-none-any.whl", hash = "sha256:ff223894eb1cd271a98076b13d3badff3bb36c424074d26334cd25aebeecea6b", size = 131898, upload-time = "2025-11-03T17:04:54.875Z" }, ] [[package]] name = "platformdirs" -version = "4.3.8" +version = "4.5.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, + { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, ] [[package]] @@ -788,7 +915,7 @@ wheels = [ [[package]] name = "pre-commit" -version = "4.2.0" +version = "4.6.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, @@ -797,23 +924,23 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } +sdist = { url = "https://files.pythonhosted.org/packages/74/89/1f3e8e1fc3e97de0fa963495832f581f025f29471602a309e48808244292/pre_commit-4.6.2.tar.gz", hash = "sha256:8f5d7bfb021ecdbcd9d49d89847082dd24172ccde534390081a679ad046e2441", size = 198670, upload-time = "2026-08-10T22:07:18.421Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, + { url = "https://files.pythonhosted.org/packages/45/e2/bbb7129c9e7999a6b8ee9cca3b66486c25c423ab5a75f34071798b74ce94/pre_commit-4.6.2-py2.py3-none-any.whl", hash = "sha256:e2dde9a75d3bce11bd3831c26d134df00a2803c1d818be6a0383c3dcda25dc4e", size = 226202, upload-time = "2026-08-10T22:07:16.942Z" }, ] [[package]] name = "pycparser" -version = "2.22" +version = "3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, ] [[package]] name = "pydantic" -version = "2.11.7" +version = "2.12.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -821,127 +948,136 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } +sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, + { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, ] [[package]] name = "pydantic-core" -version = "2.33.2" +version = "2.41.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", size = 2028817, upload-time = "2025-04-23T18:30:43.919Z" }, - { url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", size = 1861357, upload-time = "2025-04-23T18:30:46.372Z" }, - { url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", size = 1898011, upload-time = "2025-04-23T18:30:47.591Z" }, - { url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", size = 1982730, upload-time = "2025-04-23T18:30:49.328Z" }, - { url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", size = 2136178, upload-time = "2025-04-23T18:30:50.907Z" }, - { url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", size = 2736462, upload-time = "2025-04-23T18:30:52.083Z" }, - { url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", size = 2005652, upload-time = "2025-04-23T18:30:53.389Z" }, - { url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", size = 2113306, upload-time = "2025-04-23T18:30:54.661Z" }, - { url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", size = 2073720, upload-time = "2025-04-23T18:30:56.11Z" }, - { url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", size = 2244915, upload-time = "2025-04-23T18:30:57.501Z" }, - { url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", size = 2241884, upload-time = "2025-04-23T18:30:58.867Z" }, - { url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", size = 1910496, upload-time = "2025-04-23T18:31:00.078Z" }, - { url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", size = 1955019, upload-time = "2025-04-23T18:31:01.335Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" }, - { url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" }, - { url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" }, - { url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" }, - { url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" }, - { url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" }, - { url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" }, - { url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" }, - { url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" }, - { url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" }, - { url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" }, - { url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" }, - { url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" }, - { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, - { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, - { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, - { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, - { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, - { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, - { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, - { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, - { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, - { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, - { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, - { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, - { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, - { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, - { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, - { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, - { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, - { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, - { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, - { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, - { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, - { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, - { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, - { url = "https://files.pythonhosted.org/packages/53/ea/bbe9095cdd771987d13c82d104a9c8559ae9aec1e29f139e286fd2e9256e/pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d", size = 2028677, upload-time = "2025-04-23T18:32:27.227Z" }, - { url = "https://files.pythonhosted.org/packages/49/1d/4ac5ed228078737d457a609013e8f7edc64adc37b91d619ea965758369e5/pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954", size = 1864735, upload-time = "2025-04-23T18:32:29.019Z" }, - { url = "https://files.pythonhosted.org/packages/23/9a/2e70d6388d7cda488ae38f57bc2f7b03ee442fbcf0d75d848304ac7e405b/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb", size = 1898467, upload-time = "2025-04-23T18:32:31.119Z" }, - { url = "https://files.pythonhosted.org/packages/ff/2e/1568934feb43370c1ffb78a77f0baaa5a8b6897513e7a91051af707ffdc4/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7", size = 1983041, upload-time = "2025-04-23T18:32:33.655Z" }, - { url = "https://files.pythonhosted.org/packages/01/1a/1a1118f38ab64eac2f6269eb8c120ab915be30e387bb561e3af904b12499/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4", size = 2136503, upload-time = "2025-04-23T18:32:35.519Z" }, - { url = "https://files.pythonhosted.org/packages/5c/da/44754d1d7ae0f22d6d3ce6c6b1486fc07ac2c524ed8f6eca636e2e1ee49b/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b", size = 2736079, upload-time = "2025-04-23T18:32:37.659Z" }, - { url = "https://files.pythonhosted.org/packages/4d/98/f43cd89172220ec5aa86654967b22d862146bc4d736b1350b4c41e7c9c03/pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3", size = 2006508, upload-time = "2025-04-23T18:32:39.637Z" }, - { url = "https://files.pythonhosted.org/packages/2b/cc/f77e8e242171d2158309f830f7d5d07e0531b756106f36bc18712dc439df/pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a", size = 2113693, upload-time = "2025-04-23T18:32:41.818Z" }, - { url = "https://files.pythonhosted.org/packages/54/7a/7be6a7bd43e0a47c147ba7fbf124fe8aaf1200bc587da925509641113b2d/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782", size = 2074224, upload-time = "2025-04-23T18:32:44.033Z" }, - { url = "https://files.pythonhosted.org/packages/2a/07/31cf8fadffbb03be1cb520850e00a8490c0927ec456e8293cafda0726184/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9", size = 2245403, upload-time = "2025-04-23T18:32:45.836Z" }, - { url = "https://files.pythonhosted.org/packages/b6/8d/bbaf4c6721b668d44f01861f297eb01c9b35f612f6b8e14173cb204e6240/pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e", size = 2242331, upload-time = "2025-04-23T18:32:47.618Z" }, - { url = "https://files.pythonhosted.org/packages/bb/93/3cc157026bca8f5006250e74515119fcaa6d6858aceee8f67ab6dc548c16/pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9", size = 1910571, upload-time = "2025-04-23T18:32:49.401Z" }, - { url = "https://files.pythonhosted.org/packages/5b/90/7edc3b2a0d9f0dda8806c04e511a67b0b7a41d2187e2003673a996fb4310/pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3", size = 1956504, upload-time = "2025-04-23T18:32:51.287Z" }, - { url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", size = 2023982, upload-time = "2025-04-23T18:32:53.14Z" }, - { url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", size = 1858412, upload-time = "2025-04-23T18:32:55.52Z" }, - { url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", size = 1892749, upload-time = "2025-04-23T18:32:57.546Z" }, - { url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", size = 2067527, upload-time = "2025-04-23T18:32:59.771Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", size = 2108225, upload-time = "2025-04-23T18:33:04.51Z" }, - { url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", size = 2069490, upload-time = "2025-04-23T18:33:06.391Z" }, - { url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", size = 2237525, upload-time = "2025-04-23T18:33:08.44Z" }, - { url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", size = 2238446, upload-time = "2025-04-23T18:33:10.313Z" }, - { url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", size = 2066678, upload-time = "2025-04-23T18:33:12.224Z" }, - { url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" }, - { url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" }, - { url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" }, - { url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" }, - { url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" }, - { url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" }, - { url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" }, - { url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" }, - { url = "https://files.pythonhosted.org/packages/08/98/dbf3fdfabaf81cda5622154fda78ea9965ac467e3239078e0dcd6df159e7/pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101", size = 2024034, upload-time = "2025-04-23T18:33:32.843Z" }, - { url = "https://files.pythonhosted.org/packages/8d/99/7810aa9256e7f2ccd492590f86b79d370df1e9292f1f80b000b6a75bd2fb/pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64", size = 1858578, upload-time = "2025-04-23T18:33:34.912Z" }, - { url = "https://files.pythonhosted.org/packages/d8/60/bc06fa9027c7006cc6dd21e48dbf39076dc39d9abbaf718a1604973a9670/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d", size = 1892858, upload-time = "2025-04-23T18:33:36.933Z" }, - { url = "https://files.pythonhosted.org/packages/f2/40/9d03997d9518816c68b4dfccb88969756b9146031b61cd37f781c74c9b6a/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535", size = 2068498, upload-time = "2025-04-23T18:33:38.997Z" }, - { url = "https://files.pythonhosted.org/packages/d8/62/d490198d05d2d86672dc269f52579cad7261ced64c2df213d5c16e0aecb1/pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d", size = 2108428, upload-time = "2025-04-23T18:33:41.18Z" }, - { url = "https://files.pythonhosted.org/packages/9a/ec/4cd215534fd10b8549015f12ea650a1a973da20ce46430b68fc3185573e8/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6", size = 2069854, upload-time = "2025-04-23T18:33:43.446Z" }, - { url = "https://files.pythonhosted.org/packages/1a/1a/abbd63d47e1d9b0d632fee6bb15785d0889c8a6e0a6c3b5a8e28ac1ec5d2/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca", size = 2237859, upload-time = "2025-04-23T18:33:45.56Z" }, - { url = "https://files.pythonhosted.org/packages/80/1c/fa883643429908b1c90598fd2642af8839efd1d835b65af1f75fba4d94fe/pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039", size = 2239059, upload-time = "2025-04-23T18:33:47.735Z" }, - { url = "https://files.pythonhosted.org/packages/d4/29/3cade8a924a61f60ccfa10842f75eb12787e1440e2b8660ceffeb26685e7/pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", size = 2066661, upload-time = "2025-04-23T18:33:49.995Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", size = 2107298, upload-time = "2025-11-04T13:39:04.116Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", size = 1901475, upload-time = "2025-11-04T13:39:06.055Z" }, + { url = "https://files.pythonhosted.org/packages/5d/b6/338abf60225acc18cdc08b4faef592d0310923d19a87fba1faf05af5346e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", size = 1918815, upload-time = "2025-11-04T13:39:10.41Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1c/2ed0433e682983d8e8cba9c8d8ef274d4791ec6a6f24c58935b90e780e0a/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", size = 2065567, upload-time = "2025-11-04T13:39:12.244Z" }, + { url = "https://files.pythonhosted.org/packages/b3/24/cf84974ee7d6eae06b9e63289b7b8f6549d416b5c199ca2d7ce13bbcf619/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52", size = 2230442, upload-time = "2025-11-04T13:39:13.962Z" }, + { url = "https://files.pythonhosted.org/packages/fd/21/4e287865504b3edc0136c89c9c09431be326168b1eb7841911cbc877a995/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", size = 2350956, upload-time = "2025-11-04T13:39:15.889Z" }, + { url = "https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", size = 2068253, upload-time = "2025-11-04T13:39:17.403Z" }, + { url = "https://files.pythonhosted.org/packages/d5/8c/a4abfc79604bcb4c748e18975c44f94f756f08fb04218d5cb87eb0d3a63e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", size = 2177050, upload-time = "2025-11-04T13:39:19.351Z" }, + { url = "https://files.pythonhosted.org/packages/67/b1/de2e9a9a79b480f9cb0b6e8b6ba4c50b18d4e89852426364c66aa82bb7b3/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", size = 2147178, upload-time = "2025-11-04T13:39:21Z" }, + { url = "https://files.pythonhosted.org/packages/16/c1/dfb33f837a47b20417500efaa0378adc6635b3c79e8369ff7a03c494b4ac/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", size = 2341833, upload-time = "2025-11-04T13:39:22.606Z" }, + { url = "https://files.pythonhosted.org/packages/47/36/00f398642a0f4b815a9a558c4f1dca1b4020a7d49562807d7bc9ff279a6c/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", size = 2321156, upload-time = "2025-11-04T13:39:25.843Z" }, + { url = "https://files.pythonhosted.org/packages/7e/70/cad3acd89fde2010807354d978725ae111ddf6d0ea46d1ea1775b5c1bd0c/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", size = 1989378, upload-time = "2025-11-04T13:39:27.92Z" }, + { url = "https://files.pythonhosted.org/packages/76/92/d338652464c6c367e5608e4488201702cd1cbb0f33f7b6a85a60fe5f3720/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", size = 2013622, upload-time = "2025-11-04T13:39:29.848Z" }, + { url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, + { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, + { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, + { url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" }, + { url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" }, + { url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" }, + { url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" }, + { url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" }, + { url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" }, + { url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" }, + { url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" }, + { url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, + { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, + { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, + { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, + { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, + { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, + { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, + { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, + { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, + { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, + { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, + { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, + { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, + { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, + { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, + { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, + { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, + { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, + { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, + { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, + { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, + { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, + { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, + { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, + { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, + { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, + { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, + { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, + { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, + { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, + { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, + { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, + { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, + { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, + { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, + { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, + { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" }, + { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, + { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, + { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351, upload-time = "2025-11-04T13:43:02.058Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363, upload-time = "2025-11-04T13:43:05.159Z" }, + { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615, upload-time = "2025-11-04T13:43:08.116Z" }, + { url = "https://files.pythonhosted.org/packages/99/0a/99a53d06dd0348b2008f2f30884b34719c323f16c3be4e6cc1203b74a91d/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", size = 2175369, upload-time = "2025-11-04T13:43:12.49Z" }, + { url = "https://files.pythonhosted.org/packages/6d/94/30ca3b73c6d485b9bb0bc66e611cff4a7138ff9736b7e66bcf0852151636/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", size = 2144218, upload-time = "2025-11-04T13:43:15.431Z" }, + { url = "https://files.pythonhosted.org/packages/87/57/31b4f8e12680b739a91f472b5671294236b82586889ef764b5fbc6669238/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", size = 2329951, upload-time = "2025-11-04T13:43:18.062Z" }, + { url = "https://files.pythonhosted.org/packages/7d/73/3c2c8edef77b8f7310e6fb012dbc4b8551386ed575b9eb6fb2506e28a7eb/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", size = 2318428, upload-time = "2025-11-04T13:43:20.679Z" }, + { url = "https://files.pythonhosted.org/packages/2f/02/8559b1f26ee0d502c74f9cca5c0d2fd97e967e083e006bbbb4e97f3a043a/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", size = 2147009, upload-time = "2025-11-04T13:43:23.286Z" }, + { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, + { url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" }, + { url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" }, + { url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" }, + { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, ] [[package]] name = "pygments" -version = "2.19.2" +version = "2.20.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, ] [[package]] @@ -955,7 +1091,7 @@ wheels = [ [[package]] name = "pytest" -version = "8.4.1" +version = "9.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -966,23 +1102,23 @@ dependencies = [ { name = "pygments" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, + { url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" }, ] [[package]] name = "pytest-cov" -version = "6.2.1" +version = "7.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pluggy" }, { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/99/668cade231f434aaa59bbfbf49469068d2ddd945000621d3d165d2e7dd7b/pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", size = 69432, upload-time = "2025-06-12T10:47:47.684Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/51/a849f96e117386044471c8ec2bd6cfebacda285da9525c9106aeb28da671/pytest_cov-7.1.0.tar.gz", hash = "sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2", size = 55592, upload-time = "2026-03-21T20:11:16.284Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/16/4ea354101abb1287856baa4af2732be351c7bee728065aed451b678153fd/pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5", size = 24644, upload-time = "2025-06-12T10:47:45.932Z" }, + { url = "https://files.pythonhosted.org/packages/9d/7a/d968e294073affff457b041c2be9868a40c1c71f4a35fcc1e45e5493067b/pytest_cov-7.1.0-py3-none-any.whl", hash = "sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678", size = 22876, upload-time = "2026-03-21T20:11:14.438Z" }, ] [[package]] @@ -1012,20 +1148,20 @@ wheels = [ [[package]] name = "python-gitlab" -version = "6.2.0" +version = "6.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "requests" }, { name = "requests-toolbelt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/30/32/8b1f293d106ec69033eb29dc998ff8a86fdbce5eebc1f6af8835b2faef61/python_gitlab-6.2.0.tar.gz", hash = "sha256:b88c79cea65dd2425922c829730ea95827ed7132d869b8532b90a8c7199cc1a6", size = 397611, upload-time = "2025-07-28T01:25:56.294Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/bd/b30f1d3b303cb5d3c72e2d57a847d699e8573cbdfd67ece5f1795e49da1c/python_gitlab-6.5.0.tar.gz", hash = "sha256:97553652d94b02de343e9ca92782239aa2b5f6594c5482331a9490d9d5e8737d", size = 400591, upload-time = "2025-10-17T21:40:02.89Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/41/4b/aa99112a09c2898e17b88245a1d2e5bfcc71016f3cbdc24b6d870de38cf9/python_gitlab-6.2.0-py3-none-any.whl", hash = "sha256:8adf2bbf1ac8a5224ee04a456d318da0d15128606711e8c8e1a2ff050968432b", size = 144242, upload-time = "2025-07-28T01:25:54.408Z" }, + { url = "https://files.pythonhosted.org/packages/34/bd/b0d440685fbcafee462bed793a74aea88541887c4c30556a55ac64914b8d/python_gitlab-6.5.0-py3-none-any.whl", hash = "sha256:494e1e8e5edd15286eaf7c286f3a06652688f1ee20a49e2a0218ddc5cc475e32", size = 144419, upload-time = "2025-10-17T21:40:01.233Z" }, ] [[package]] name = "python-semantic-release" -version = "10.3.1" +version = "10.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, @@ -1042,67 +1178,78 @@ dependencies = [ { name = "shellingham" }, { name = "tomlkit" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/af/75/fb578d1805dc482f619c82431b398ab3c0489817a1cdbe2fa1be48d3d7d3/python_semantic_release-10.3.1.tar.gz", hash = "sha256:16003292315ee29b6ad424fad9745946422cf965e19649269c4e2fb8271cb267", size = 323536, upload-time = "2025-08-06T04:41:10.135Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/f6/06d5aa54b46bb192b00ef3e74234300ea5932dd310d142a3c8070e770e93/python_semantic_release-10.6.1.tar.gz", hash = "sha256:ee6369238f72e75a009b3724481232c8b813416191be099bc0266e375fd02b2b", size = 626453, upload-time = "2026-07-06T06:14:35.507Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/49/0a74aafd0da45a7ee2c38b82112d576ee48a6795d813c8025cdf9cbaf159/python_semantic_release-10.3.1-py3-none-any.whl", hash = "sha256:b2677018e761dfbfdf5758eeee6b09963e136d67c43059f12f9bc6c441fcbf13", size = 142065, upload-time = "2025-08-06T04:41:08.056Z" }, + { url = "https://files.pythonhosted.org/packages/18/97/be812cd1eb350551d2f3cc38426864cce493a03ed31f4749133bcff8d053/python_semantic_release-10.6.1-py3-none-any.whl", hash = "sha256:36f7319515f218719d0972bc9535813a930f04cd19556767599e9863242efcdc", size = 155674, upload-time = "2026-07-06T06:14:33.575Z" }, ] [[package]] name = "pyyaml" -version = "6.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199, upload-time = "2024-08-06T20:31:40.178Z" }, - { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758, upload-time = "2024-08-06T20:31:42.173Z" }, - { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463, upload-time = "2024-08-06T20:31:44.263Z" }, - { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280, upload-time = "2024-08-06T20:31:50.199Z" }, - { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239, upload-time = "2024-08-06T20:31:52.292Z" }, - { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802, upload-time = "2024-08-06T20:31:53.836Z" }, - { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527, upload-time = "2024-08-06T20:31:55.565Z" }, - { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052, upload-time = "2024-08-06T20:31:56.914Z" }, - { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774, upload-time = "2024-08-06T20:31:58.304Z" }, - { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" }, - { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" }, - { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" }, - { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" }, - { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" }, - { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" }, - { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" }, - { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" }, - { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" }, - { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, - { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, - { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, - { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, - { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, - { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, - { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, - { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, - { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, - { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, - { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, - { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, - { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, - { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, - { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, - { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, - { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, - { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, - { url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", size = 184777, upload-time = "2024-08-06T20:33:25.896Z" }, - { url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", size = 172318, upload-time = "2024-08-06T20:33:27.212Z" }, - { url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", size = 720891, upload-time = "2024-08-06T20:33:28.974Z" }, - { url = "https://files.pythonhosted.org/packages/e9/6c/6e1b7f40181bc4805e2e07f4abc10a88ce4648e7e95ff1abe4ae4014a9b2/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", size = 722614, upload-time = "2024-08-06T20:33:34.157Z" }, - { url = "https://files.pythonhosted.org/packages/3d/32/e7bd8535d22ea2874cef6a81021ba019474ace0d13a4819c2a4bce79bd6a/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", size = 737360, upload-time = "2024-08-06T20:33:35.84Z" }, - { url = "https://files.pythonhosted.org/packages/d7/12/7322c1e30b9be969670b672573d45479edef72c9a0deac3bb2868f5d7469/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", size = 699006, upload-time = "2024-08-06T20:33:37.501Z" }, - { url = "https://files.pythonhosted.org/packages/82/72/04fcad41ca56491995076630c3ec1e834be241664c0c09a64c9a2589b507/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", size = 723577, upload-time = "2024-08-06T20:33:39.389Z" }, - { url = "https://files.pythonhosted.org/packages/ed/5e/46168b1f2757f1fcd442bc3029cd8767d88a98c9c05770d8b420948743bb/PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", size = 144593, upload-time = "2024-08-06T20:33:46.63Z" }, - { url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", size = 162312, upload-time = "2024-08-06T20:33:49.073Z" }, +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, ] [[package]] name = "requests" -version = "2.32.4" +version = "2.33.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -1110,9 +1257,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } +sdist = { url = "https://files.pythonhosted.org/packages/34/64/8860370b167a9721e8956ae116825caff829224fbca0ca6e7bf8ddef8430/requests-2.33.0.tar.gz", hash = "sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652", size = 134232, upload-time = "2026-03-25T15:10:41.586Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, + { url = "https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl", hash = "sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b", size = 65017, upload-time = "2026-03-25T15:10:40.382Z" }, ] [[package]] @@ -1129,55 +1276,66 @@ wheels = [ [[package]] name = "rich" -version = "14.1.0" +version = "14.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "markdown-it-py" }, { name = "pygments" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fe/75/af448d8e52bf1d8fa6a9d089ca6c07ff4453d86c65c145d0a300bb073b9b/rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8", size = 224441, upload-time = "2025-07-25T07:32:58.125Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" }, +] + +[[package]] +name = "roman-numerals" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/f9/41dc953bbeb056c17d5f7a519f50fdf010bd0553be2d630bc69d1e022703/roman_numerals-4.1.0.tar.gz", hash = "sha256:1af8b147eb1405d5839e78aeb93131690495fe9da5c91856cb33ad55a7f1e5b2", size = 9077, upload-time = "2025-12-17T18:25:34.381Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" }, + { url = "https://files.pythonhosted.org/packages/04/54/6f679c435d28e0a568d8e8a7c0a93a09010818634c3c3907fc98d8983770/roman_numerals-4.1.0-py3-none-any.whl", hash = "sha256:647ba99caddc2cc1e55a51e4360689115551bf4476d90e8162cf8c345fe233c7", size = 7676, upload-time = "2025-12-17T18:25:33.098Z" }, ] [[package]] name = "roman-numerals-py" -version = "3.1.0" +version = "4.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/76/48fd56d17c5bdbdf65609abbc67288728a98ed4c02919428d4f52d23b24b/roman_numerals_py-3.1.0.tar.gz", hash = "sha256:be4bf804f083a4ce001b5eb7e3c0862479d10f94c936f6c4e5f250aa5ff5bd2d", size = 9017, upload-time = "2025-02-22T07:34:54.333Z" } +dependencies = [ + { name = "roman-numerals" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/b5/de96fca640f4f656eb79bbee0e79aeec52e3e0e359f8a3e6a0d366378b64/roman_numerals_py-4.1.0.tar.gz", hash = "sha256:f5d7b2b4ca52dd855ef7ab8eb3590f428c0b1ea480736ce32b01fef2a5f8daf9", size = 4274, upload-time = "2025-12-17T18:25:41.153Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/53/97/d2cbbaa10c9b826af0e10fdf836e1bf344d9f0abb873ebc34d1f49642d3f/roman_numerals_py-3.1.0-py3-none-any.whl", hash = "sha256:9da2ad2fb670bcf24e81070ceb3be72f6c11c440d73bd579fbeca1e9f330954c", size = 7742, upload-time = "2025-02-22T07:34:52.422Z" }, + { url = "https://files.pythonhosted.org/packages/27/2c/daca29684cbe9fd4bc711f8246da3c10adca1ccc4d24436b17572eb2590e/roman_numerals_py-4.1.0-py3-none-any.whl", hash = "sha256:553114c1167141c1283a51743759723ecd05604a1b6b507225e91dc1a6df0780", size = 4547, upload-time = "2025-12-17T18:25:40.136Z" }, ] [[package]] name = "ruff" -version = "0.12.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/81/0bd3594fa0f690466e41bd033bdcdf86cba8288345ac77ad4afbe5ec743a/ruff-0.12.7.tar.gz", hash = "sha256:1fc3193f238bc2d7968772c82831a4ff69252f673be371fb49663f0068b7ec71", size = 5197814, upload-time = "2025-07-29T22:32:35.877Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/d2/6cb35e9c85e7a91e8d22ab32ae07ac39cc34a71f1009a6f9e4a2a019e602/ruff-0.12.7-py3-none-linux_armv6l.whl", hash = "sha256:76e4f31529899b8c434c3c1dede98c4483b89590e15fb49f2d46183801565303", size = 11852189, upload-time = "2025-07-29T22:31:41.281Z" }, - { url = "https://files.pythonhosted.org/packages/63/5b/a4136b9921aa84638f1a6be7fb086f8cad0fde538ba76bda3682f2599a2f/ruff-0.12.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:789b7a03e72507c54fb3ba6209e4bb36517b90f1a3569ea17084e3fd295500fb", size = 12519389, upload-time = "2025-07-29T22:31:54.265Z" }, - { url = "https://files.pythonhosted.org/packages/a8/c9/3e24a8472484269b6b1821794141f879c54645a111ded4b6f58f9ab0705f/ruff-0.12.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e1c2a3b8626339bb6369116e7030a4cf194ea48f49b64bb505732a7fce4f4e3", size = 11743384, upload-time = "2025-07-29T22:31:59.575Z" }, - { url = "https://files.pythonhosted.org/packages/26/7c/458dd25deeb3452c43eaee853c0b17a1e84169f8021a26d500ead77964fd/ruff-0.12.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32dec41817623d388e645612ec70d5757a6d9c035f3744a52c7b195a57e03860", size = 11943759, upload-time = "2025-07-29T22:32:01.95Z" }, - { url = "https://files.pythonhosted.org/packages/7f/8b/658798472ef260ca050e400ab96ef7e85c366c39cf3dfbef4d0a46a528b6/ruff-0.12.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47ef751f722053a5df5fa48d412dbb54d41ab9b17875c6840a58ec63ff0c247c", size = 11654028, upload-time = "2025-07-29T22:32:04.367Z" }, - { url = "https://files.pythonhosted.org/packages/a8/86/9c2336f13b2a3326d06d39178fd3448dcc7025f82514d1b15816fe42bfe8/ruff-0.12.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a828a5fc25a3efd3e1ff7b241fd392686c9386f20e5ac90aa9234a5faa12c423", size = 13225209, upload-time = "2025-07-29T22:32:06.952Z" }, - { url = "https://files.pythonhosted.org/packages/76/69/df73f65f53d6c463b19b6b312fd2391dc36425d926ec237a7ed028a90fc1/ruff-0.12.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5726f59b171111fa6a69d82aef48f00b56598b03a22f0f4170664ff4d8298efb", size = 14182353, upload-time = "2025-07-29T22:32:10.053Z" }, - { url = "https://files.pythonhosted.org/packages/58/1e/de6cda406d99fea84b66811c189b5ea139814b98125b052424b55d28a41c/ruff-0.12.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74e6f5c04c4dd4aba223f4fe6e7104f79e0eebf7d307e4f9b18c18362124bccd", size = 13631555, upload-time = "2025-07-29T22:32:12.644Z" }, - { url = "https://files.pythonhosted.org/packages/6f/ae/625d46d5164a6cc9261945a5e89df24457dc8262539ace3ac36c40f0b51e/ruff-0.12.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0bfe4e77fba61bf2ccadf8cf005d6133e3ce08793bbe870dd1c734f2699a3e", size = 12667556, upload-time = "2025-07-29T22:32:15.312Z" }, - { url = "https://files.pythonhosted.org/packages/55/bf/9cb1ea5e3066779e42ade8d0cd3d3b0582a5720a814ae1586f85014656b6/ruff-0.12.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606", size = 12939784, upload-time = "2025-07-29T22:32:17.69Z" }, - { url = "https://files.pythonhosted.org/packages/55/7f/7ead2663be5627c04be83754c4f3096603bf5e99ed856c7cd29618c691bd/ruff-0.12.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e41df94a957d50083fd09b916d6e89e497246698c3f3d5c681c8b3e7b9bb4ac8", size = 11771356, upload-time = "2025-07-29T22:32:20.134Z" }, - { url = "https://files.pythonhosted.org/packages/17/40/a95352ea16edf78cd3a938085dccc55df692a4d8ba1b3af7accbe2c806b0/ruff-0.12.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4000623300563c709458d0ce170c3d0d788c23a058912f28bbadc6f905d67afa", size = 11612124, upload-time = "2025-07-29T22:32:22.645Z" }, - { url = "https://files.pythonhosted.org/packages/4d/74/633b04871c669e23b8917877e812376827c06df866e1677f15abfadc95cb/ruff-0.12.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:69ffe0e5f9b2cf2b8e289a3f8945b402a1b19eff24ec389f45f23c42a3dd6fb5", size = 12479945, upload-time = "2025-07-29T22:32:24.765Z" }, - { url = "https://files.pythonhosted.org/packages/be/34/c3ef2d7799c9778b835a76189c6f53c179d3bdebc8c65288c29032e03613/ruff-0.12.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a07a5c8ffa2611a52732bdc67bf88e243abd84fe2d7f6daef3826b59abbfeda4", size = 12998677, upload-time = "2025-07-29T22:32:27.022Z" }, - { url = "https://files.pythonhosted.org/packages/77/ab/aca2e756ad7b09b3d662a41773f3edcbd262872a4fc81f920dc1ffa44541/ruff-0.12.7-py3-none-win32.whl", hash = "sha256:c928f1b2ec59fb77dfdf70e0419408898b63998789cc98197e15f560b9e77f77", size = 11756687, upload-time = "2025-07-29T22:32:29.381Z" }, - { url = "https://files.pythonhosted.org/packages/b4/71/26d45a5042bc71db22ddd8252ca9d01e9ca454f230e2996bb04f16d72799/ruff-0.12.7-py3-none-win_amd64.whl", hash = "sha256:9c18f3d707ee9edf89da76131956aba1270c6348bfee8f6c647de841eac7194f", size = 12912365, upload-time = "2025-07-29T22:32:31.517Z" }, - { url = "https://files.pythonhosted.org/packages/4c/9b/0b8aa09817b63e78d94b4977f18b1fcaead3165a5ee49251c5d5c245bb2d/ruff-0.12.7-py3-none-win_arm64.whl", hash = "sha256:dfce05101dbd11833a0776716d5d1578641b7fddb537fe7fa956ab85d1769b69", size = 11982083, upload-time = "2025-07-29T22:32:33.881Z" }, +version = "0.16.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/61/b3/3213589383f8f1b3938781bd1278713f6d18621a14992b3e81fefb8a5ef9/ruff-0.16.3.tar.gz", hash = "sha256:e76d33a347661a84b5be6d043d0347fdc745dfdcf825a8f4fed64b5e26eebdf2", size = 4891904, upload-time = "2026-08-13T15:17:13.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/96/493770daebd68c0a67f1549fdf519f53be51fc435186c0585bcc272fd76c/ruff-0.16.3-py3-none-linux_armv6l.whl", hash = "sha256:0c5710e247a58a4521e66e124ba9a74655b414f61ba3a2e9e3811e11098f48f7", size = 10902799, upload-time = "2026-08-13T15:16:27.382Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e6/2becf3942fddc29a29b8df47691d456fb1085391a694f74d84513251418c/ruff-0.16.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fe155130631a2471fd2e14a7a664a4dfbd7194b8229c3d7b2a40b21178639081", size = 11135539, upload-time = "2026-08-13T15:16:30.87Z" }, + { url = "https://files.pythonhosted.org/packages/3e/1e/4b8b72f0d006dbf19326aa99f9ca0ee2ff374187c4d301cf529a51aa06fe/ruff-0.16.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e2ed719e14aa64d895c2ee922594a90a43c861a93f0575a95ff8c47cdbd13eb9", size = 10475095, upload-time = "2026-08-13T15:16:33.259Z" }, + { url = "https://files.pythonhosted.org/packages/92/32/2201fa49ba1f6c101ee321e83f051ac7a4b8d07b0ef6b4d3f2772b302275/ruff-0.16.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e0b1da805eb043654645d74d5de1e5ce2edc686e40790d2b86f56d71cc06a84", size = 10668771, upload-time = "2026-08-13T15:16:35.65Z" }, + { url = "https://files.pythonhosted.org/packages/c3/66/4afc5c8363bd04d45effce1b7c8713ca037d7a6740b7451a2403a6e3a972/ruff-0.16.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a37bdea0bbe21780f590bf437d6412c8c4e1b6cd010f91a65c2c40c5e5f5f870", size = 10699568, upload-time = "2026-08-13T15:16:38.195Z" }, + { url = "https://files.pythonhosted.org/packages/53/fd/c67d246bf36bf1698551c56de39e95cd07f70e64433e0098e6267d77061b/ruff-0.16.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09571e6d1288ed9be475207a3ac04ada404f1cd898104be0f6ab8d7df438575b", size = 11499365, upload-time = "2026-08-13T15:16:40.623Z" }, + { url = "https://files.pythonhosted.org/packages/67/0b/00ecbceb99a263af7b12f6f05ac3c92bc47b905e91adc3f207a836e3bc01/ruff-0.16.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c18c5a101eb540010638cc1ff3c84944d3adb3df62b8d98ca8f22ba484d3413", size = 12311728, upload-time = "2026-08-13T15:16:43.564Z" }, + { url = "https://files.pythonhosted.org/packages/54/b2/b7b3bb54f4d3f7db504e476ad4ab8de530dceebe2c061384b2757ee419e8/ruff-0.16.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8457c44f15033c85ddbb77b15d451df9e24e4bd03b628396dd3610cedc3b8f82", size = 11699896, upload-time = "2026-08-13T15:16:46.209Z" }, + { url = "https://files.pythonhosted.org/packages/c7/30/4c468429ac195addc5ee1b717b6ab1b66632786737ca3b2ed3443fb0c26a/ruff-0.16.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:294b95c4ae0cda9388525c2047778aa758d6b8d4bb876fd4e9eaa3ebc92343eb", size = 11058736, upload-time = "2026-08-13T15:16:48.823Z" }, + { url = "https://files.pythonhosted.org/packages/43/67/7a113cdaddf24b64d7f75b1242a99d04c82fcef4f6921fdbb832beaffb5f/ruff-0.16.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3d0c7c40c87c2a820509c31ba007968da6e1306468c067b2d82fbfdbcd0e8474", size = 11586911, upload-time = "2026-08-13T15:16:51.913Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c1/2e66f24c0f3ead25a5e660111778685e505e5da353c82802bf49f0cbe7b9/ruff-0.16.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9f738c0fdfa8eed0b2ce7fb27ee7258208a92a68d7949e62aa15164bc7b389da", size = 10954265, upload-time = "2026-08-13T15:16:54.763Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ba/4cee23bf52cba9a058d3726de623624daf50ef9638868edd86f4126157f6/ruff-0.16.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fb785f0be25abe69d320415cd4f833b59e17ba7613d9ba6a958023b6bceb0a50", size = 10709886, upload-time = "2026-08-13T15:16:57.339Z" }, + { url = "https://files.pythonhosted.org/packages/82/df/7da7194fa5d9dc0a285f7e6fa5a4722e7c63faac0b45b614ded9314363a1/ruff-0.16.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c5536e3acfbf9563085aa2be7b13c629c3077e902afc5b941ac44024dbb9f506", size = 11210392, upload-time = "2026-08-13T15:17:00.171Z" }, + { url = "https://files.pythonhosted.org/packages/35/85/7795f6e817af050e7517bf3e7aa9b061cce70ef33d280aad902c956c1ecf/ruff-0.16.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a2d85c02f9b8e165d85e6779184d38c4132de12603dab59c51c28e22584f9e4d", size = 11626910, upload-time = "2026-08-13T15:17:03.299Z" }, + { url = "https://files.pythonhosted.org/packages/78/9b/475b927cf27a5cbbda3c7bafb69ed6ff77e1d7923d5d85f17c2749d7ae32/ruff-0.16.3-py3-none-win32.whl", hash = "sha256:388cdf2166642bd9b13d52b5932d3170f34f8abed7e8d9a855f1d84b83645a0a", size = 10931415, upload-time = "2026-08-13T15:17:05.726Z" }, + { url = "https://files.pythonhosted.org/packages/b2/99/e2a2bfc4fbf0a1e8a916bc9ebe6fe6c58cc34c28e0ffc6ce281d572d1c2e/ruff-0.16.3-py3-none-win_amd64.whl", hash = "sha256:e80a7d69ca2a6d1c4d352ec91458cdca6e56c83cdbcabd93e4abe1e53591d948", size = 11445993, upload-time = "2026-08-13T15:17:08.353Z" }, + { url = "https://files.pythonhosted.org/packages/69/3e/4132e539aed78c148854d4997a2685b0ed4dc4e87110b59ce528564e184e/ruff-0.16.3-py3-none-win_arm64.whl", hash = "sha256:b8ca152da82c1acc1fa8d5874b15951935f0eef46f10e6954c83859011b6178a", size = 11399302, upload-time = "2026-08-13T15:17:10.908Z" }, ] [[package]] name = "selenium" -version = "4.33.0" +version = "4.46.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -1187,18 +1345,18 @@ dependencies = [ { name = "urllib3", extra = ["socks"] }, { name = "websocket-client" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5f/7e/4145666dd275760b56d0123a9439915af167932dd6caa19b5f8b281ae297/selenium-4.33.0.tar.gz", hash = "sha256:d90974db95d2cdeb34d2fb1b13f03dc904f53e6c5d228745b0635ada10cd625d", size = 882387, upload-time = "2025-05-23T17:45:22.046Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a0/53/053df98ef0c38535a74ea732217eb2dbfddc7ff5442a47a4b315ba577f85/selenium-4.46.0.tar.gz", hash = "sha256:54f7e1a4df5f7508ac8c38ce2ea584db1b27083dd79962b22524219219df5cbe", size = 1006000, upload-time = "2026-07-11T00:38:41.11Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/c0/092fde36918574e144613de73ba43c36ab8d31e7d36bb44c35261909452d/selenium-4.33.0-py3-none-any.whl", hash = "sha256:af9ea757813918bddfe05cc677bf63c8a0cd277ebf8474b3dd79caa5727fca85", size = 9370835, upload-time = "2025-05-23T17:45:19.448Z" }, + { url = "https://files.pythonhosted.org/packages/30/f4/365c723a37c7e9ba6a6a19bf0c9e407137703f56a72c6201d0e4cb1432cb/selenium-4.46.0-py3-none-any.whl", hash = "sha256:f03e864770a21ab32009961c9d015cb2c6275eba45c926c272e02d90af423aad", size = 9428587, upload-time = "2026-07-11T00:38:38.84Z" }, ] [[package]] name = "setuptools" -version = "80.9.0" +version = "83.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/34/26/f5d29e25ffdb535afef2d35cdb55b325298f96debd670da4c325e08d70f4/setuptools-83.0.0.tar.gz", hash = "sha256:025bccbbf0fa05b6192bc64ae1e7b16e001fd6d6d4d5de03c97b1c1ade523bef", size = 1154254, upload-time = "2026-07-04T15:31:22.699Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, + { url = "https://files.pythonhosted.org/packages/5d/40/e1e72872c6354b306daef1703549e8e83b4d43cfea356311bf722a043752/setuptools-83.0.0-py3-none-any.whl", hash = "sha256:29b23c360f22f414dc7336bb39178cc7bcbf6021ed2733cde173f09dba19abb3", size = 1008090, upload-time = "2026-07-04T15:31:20.885Z" }, ] [[package]] @@ -1255,63 +1413,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, ] -[[package]] -name = "sphinx" -version = "7.4.7" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.10'", -] -dependencies = [ - { name = "alabaster", version = "0.7.16", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "babel", marker = "python_full_version < '3.10'" }, - { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, - { name = "docutils", marker = "python_full_version < '3.10'" }, - { name = "imagesize", marker = "python_full_version < '3.10'" }, - { name = "importlib-metadata", marker = "python_full_version < '3.10'" }, - { name = "jinja2", marker = "python_full_version < '3.10'" }, - { name = "packaging", marker = "python_full_version < '3.10'" }, - { name = "pygments", marker = "python_full_version < '3.10'" }, - { name = "requests", marker = "python_full_version < '3.10'" }, - { name = "snowballstemmer", marker = "python_full_version < '3.10'" }, - { name = "sphinxcontrib-applehelp", marker = "python_full_version < '3.10'" }, - { name = "sphinxcontrib-devhelp", marker = "python_full_version < '3.10'" }, - { name = "sphinxcontrib-htmlhelp", marker = "python_full_version < '3.10'" }, - { name = "sphinxcontrib-jsmath", marker = "python_full_version < '3.10'" }, - { name = "sphinxcontrib-qthelp", marker = "python_full_version < '3.10'" }, - { name = "sphinxcontrib-serializinghtml", marker = "python_full_version < '3.10'" }, - { name = "tomli", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5b/be/50e50cb4f2eff47df05673d361095cafd95521d2a22521b920c67a372dcb/sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe", size = 8067911, upload-time = "2024-07-20T14:46:56.059Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/ef/153f6803c5d5f8917dbb7f7fcf6d34a871ede3296fa89c2c703f5f8a6c8e/sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239", size = 3401624, upload-time = "2024-07-20T14:46:52.142Z" }, -] - [[package]] name = "sphinx" version = "8.1.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version == '3.10.*'", + "python_full_version < '3.11'", ] dependencies = [ - { name = "alabaster", version = "1.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, - { name = "babel", marker = "python_full_version == '3.10.*'" }, - { name = "colorama", marker = "python_full_version == '3.10.*' and sys_platform == 'win32'" }, - { name = "docutils", marker = "python_full_version == '3.10.*'" }, - { name = "imagesize", marker = "python_full_version == '3.10.*'" }, - { name = "jinja2", marker = "python_full_version == '3.10.*'" }, - { name = "packaging", marker = "python_full_version == '3.10.*'" }, - { name = "pygments", marker = "python_full_version == '3.10.*'" }, - { name = "requests", marker = "python_full_version == '3.10.*'" }, - { name = "snowballstemmer", marker = "python_full_version == '3.10.*'" }, - { name = "sphinxcontrib-applehelp", marker = "python_full_version == '3.10.*'" }, - { name = "sphinxcontrib-devhelp", marker = "python_full_version == '3.10.*'" }, - { name = "sphinxcontrib-htmlhelp", marker = "python_full_version == '3.10.*'" }, - { name = "sphinxcontrib-jsmath", marker = "python_full_version == '3.10.*'" }, - { name = "sphinxcontrib-qthelp", marker = "python_full_version == '3.10.*'" }, - { name = "sphinxcontrib-serializinghtml", marker = "python_full_version == '3.10.*'" }, - { name = "tomli", marker = "python_full_version == '3.10.*'" }, + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, + { name = "tomli" }, ] sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611, upload-time = "2024-10-13T20:27:13.93Z" } wheels = [ @@ -1323,26 +1449,27 @@ name = "sphinx" version = "8.2.3" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version >= '3.11'", + "python_full_version >= '3.15'", + "python_full_version >= '3.11' and python_full_version < '3.15'", ] dependencies = [ - { name = "alabaster", version = "1.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, - { name = "babel", marker = "python_full_version >= '3.11'" }, - { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, - { name = "docutils", marker = "python_full_version >= '3.11'" }, - { name = "imagesize", marker = "python_full_version >= '3.11'" }, - { name = "jinja2", marker = "python_full_version >= '3.11'" }, - { name = "packaging", marker = "python_full_version >= '3.11'" }, - { name = "pygments", marker = "python_full_version >= '3.11'" }, - { name = "requests", marker = "python_full_version >= '3.11'" }, - { name = "roman-numerals-py", marker = "python_full_version >= '3.11'" }, - { name = "snowballstemmer", marker = "python_full_version >= '3.11'" }, - { name = "sphinxcontrib-applehelp", marker = "python_full_version >= '3.11'" }, - { name = "sphinxcontrib-devhelp", marker = "python_full_version >= '3.11'" }, - { name = "sphinxcontrib-htmlhelp", marker = "python_full_version >= '3.11'" }, - { name = "sphinxcontrib-jsmath", marker = "python_full_version >= '3.11'" }, - { name = "sphinxcontrib-qthelp", marker = "python_full_version >= '3.11'" }, - { name = "sphinxcontrib-serializinghtml", marker = "python_full_version >= '3.11'" }, + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "roman-numerals-py" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/38/ad/4360e50ed56cb483667b8e6dadf2d3fda62359593faabbe749a27c4eaca6/sphinx-8.2.3.tar.gz", hash = "sha256:398ad29dee7f63a75888314e9424d40f52ce5a6a87ae88e7071e80af296ec348", size = 8321876, upload-time = "2025-03-02T22:31:59.658Z" } wheels = [ @@ -1351,18 +1478,17 @@ wheels = [ [[package]] name = "sphinx-rtd-theme" -version = "3.0.2" +version = "3.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "docutils" }, - { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinxcontrib-jquery" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/91/44/c97faec644d29a5ceddd3020ae2edffa69e7d00054a8c7a6021e82f20335/sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85", size = 7620463, upload-time = "2024-11-13T11:06:04.545Z" } +sdist = { url = "https://files.pythonhosted.org/packages/84/68/a1bfbf38c0f7bccc9b10bbf76b94606f64acb1552ae394f0b8285bfaea25/sphinx_rtd_theme-3.1.0.tar.gz", hash = "sha256:b44276f2c276e909239a4f6c955aa667aaafeb78597923b1c60babc76db78e4c", size = 7620915, upload-time = "2026-01-12T16:03:31.17Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/77/46e3bac77b82b4df5bb5b61f2de98637724f246b4966cfc34bc5895d852a/sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13", size = 7655561, upload-time = "2024-11-13T11:06:02.094Z" }, + { url = "https://files.pythonhosted.org/packages/87/c7/b5c8015d823bfda1a346adb2c634a2101d50bb75d421eb6dcb31acd25ebc/sphinx_rtd_theme-3.1.0-py2.py3-none-any.whl", hash = "sha256:1785824ae8e6632060490f67cf3a72d404a85d2d9fc26bce3619944de5682b89", size = 7655617, upload-time = "2026-01-12T16:03:28.101Z" }, ] [[package]] @@ -1371,8 +1497,7 @@ version = "0.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pbr" }, - { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/8d/161842a1c199c1baed5f5bc0765a59a791324f962fea3b604f105c9493e7/sphinxcontrib_apidoc-0.6.0.tar.gz", hash = "sha256:329b9810d66988f48e127a6bd18cc8efbbd1cd20b8deb4691a35738af49ad88d", size = 16790, upload-time = "2025-05-08T12:55:44.463Z" } @@ -1412,8 +1537,7 @@ name = "sphinxcontrib-jquery" version = "4.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/de/f3/aa67467e051df70a6330fe7770894b3e4f09436dea6881ae0b4f3d87cad8/sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a", size = 122331, upload-time = "2023-03-14T15:01:01.944Z" } @@ -1450,41 +1574,56 @@ wheels = [ [[package]] name = "tomli" -version = "2.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, - { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, - { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, - { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, - { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, - { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, - { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, - { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, - { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, - { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, - { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, - { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, - { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, - { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, - { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, - { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, - { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, - { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, - { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, - { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, - { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, - { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, - { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, - { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, - { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, - { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, - { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", size = 153663, upload-time = "2026-01-11T11:21:45.27Z" }, + { url = "https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", size = 148469, upload-time = "2026-01-11T11:21:46.873Z" }, + { url = "https://files.pythonhosted.org/packages/d6/c2/506e44cce89a8b1b1e047d64bd495c22c9f71f21e05f380f1a950dd9c217/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", size = 236039, upload-time = "2026-01-11T11:21:48.503Z" }, + { url = "https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", size = 243007, upload-time = "2026-01-11T11:21:49.456Z" }, + { url = "https://files.pythonhosted.org/packages/9c/6f/6e39ce66b58a5b7ae572a0f4352ff40c71e8573633deda43f6a379d56b3e/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", size = 240875, upload-time = "2026-01-11T11:21:50.755Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ad/cb089cb190487caa80204d503c7fd0f4d443f90b95cf4ef5cf5aa0f439b0/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", size = 246271, upload-time = "2026-01-11T11:21:51.81Z" }, + { url = "https://files.pythonhosted.org/packages/0b/63/69125220e47fd7a3a27fd0de0c6398c89432fec41bc739823bcc66506af6/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", size = 96770, upload-time = "2026-01-11T11:21:52.647Z" }, + { url = "https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", size = 107626, upload-time = "2026-01-11T11:21:53.459Z" }, + { url = "https://files.pythonhosted.org/packages/2f/6d/77be674a3485e75cacbf2ddba2b146911477bd887dda9d8c9dfb2f15e871/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", size = 94842, upload-time = "2026-01-11T11:21:54.831Z" }, + { url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" }, + { url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" }, + { url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" }, + { url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" }, + { url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" }, + { url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" }, + { url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" }, + { url = "https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", size = 154915, upload-time = "2026-01-11T11:22:06.703Z" }, + { url = "https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", size = 149038, upload-time = "2026-01-11T11:22:07.56Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8a/6d38870bd3d52c8d1505ce054469a73f73a0fe62c0eaf5dddf61447e32fa/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", size = 242245, upload-time = "2026-01-11T11:22:08.344Z" }, + { url = "https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", size = 250335, upload-time = "2026-01-11T11:22:09.951Z" }, + { url = "https://files.pythonhosted.org/packages/a5/3d/4cdb6f791682b2ea916af2de96121b3cb1284d7c203d97d92d6003e91c8d/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", size = 245962, upload-time = "2026-01-11T11:22:11.27Z" }, + { url = "https://files.pythonhosted.org/packages/f2/4a/5f25789f9a460bd858ba9756ff52d0830d825b458e13f754952dd15fb7bb/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", size = 250396, upload-time = "2026-01-11T11:22:12.325Z" }, + { url = "https://files.pythonhosted.org/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", size = 97530, upload-time = "2026-01-11T11:22:13.865Z" }, + { url = "https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", size = 108227, upload-time = "2026-01-11T11:22:15.224Z" }, + { url = "https://files.pythonhosted.org/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", size = 94748, upload-time = "2026-01-11T11:22:16.009Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" }, + { url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" }, + { url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" }, + { url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" }, + { url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" }, + { url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" }, + { url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" }, + { url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" }, + { url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" }, + { url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" }, + { url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" }, + { url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" }, + { url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" }, + { url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" }, + { url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" }, + { url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" }, + { url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" }, ] [[package]] @@ -1498,7 +1637,7 @@ wheels = [ [[package]] name = "trio" -version = "0.30.0" +version = "0.32.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "attrs" }, @@ -1509,9 +1648,9 @@ dependencies = [ { name = "sniffio" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/01/c1/68d582b4d3a1c1f8118e18042464bb12a7c1b75d64d75111b297687041e3/trio-0.30.0.tar.gz", hash = "sha256:0781c857c0c81f8f51e0089929a26b5bb63d57f927728a5586f7e36171f064df", size = 593776, upload-time = "2025-04-21T00:48:19.507Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/ce/0041ddd9160aac0031bcf5ab786c7640d795c797e67c438e15cfedf815c8/trio-0.32.0.tar.gz", hash = "sha256:150f29ec923bcd51231e1d4c71c7006e65247d68759dd1c19af4ea815a25806b", size = 605323, upload-time = "2025-10-31T07:18:17.466Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/69/8e/3f6dfda475ecd940e786defe6df6c500734e686c9cd0a0f8ef6821e9b2f2/trio-0.30.0-py3-none-any.whl", hash = "sha256:3bf4f06b8decf8d3cf00af85f40a89824669e2d033bb32469d34840edcfc22a5", size = 499194, upload-time = "2025-04-21T00:48:17.167Z" }, + { url = "https://files.pythonhosted.org/packages/41/bf/945d527ff706233636c73880b22c7c953f3faeb9d6c7e2e85bfbfd0134a0/trio-0.32.0-py3-none-any.whl", hash = "sha256:4ab65984ef8370b79a76659ec87aa3a30c5c7c83ff250b4de88c29a8ab6123c5", size = 512030, upload-time = "2025-10-31T07:18:15.885Z" }, ] [[package]] @@ -1531,41 +1670,41 @@ wheels = [ [[package]] name = "types-python-dateutil" -version = "2.9.0.20250708" +version = "2.9.0.20260807" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c9/95/6bdde7607da2e1e99ec1c1672a759d42f26644bbacf939916e086db34870/types_python_dateutil-2.9.0.20250708.tar.gz", hash = "sha256:ccdbd75dab2d6c9696c350579f34cffe2c281e4c5f27a585b2a2438dd1d5c8ab", size = 15834, upload-time = "2025-07-08T03:14:03.382Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c8/4e/b3fa538f9cb38dfece0d6ccf6d3d0d925bdedb144fb9c8129dfc007cd003/types_python_dateutil-2.9.0.20260807.tar.gz", hash = "sha256:e0b8a90d464c8684c66b7b8e4556d9074afdddcc56ca45323f0987134f9e7034", size = 17618, upload-time = "2026-08-07T04:17:13.491Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/72/52/43e70a8e57fefb172c22a21000b03ebcc15e47e97f5cb8495b9c2832efb4/types_python_dateutil-2.9.0.20250708-py3-none-any.whl", hash = "sha256:4d6d0cc1cc4d24a2dc3816024e502564094497b713f7befda4d5bc7a8e3fd21f", size = 17724, upload-time = "2025-07-08T03:14:02.593Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5e/3715867caea2f4cea56ccb04c851cde23ed063449c3b004c7a047f20dd48/types_python_dateutil-2.9.0.20260807-py3-none-any.whl", hash = "sha256:54aa3707350ed7a9cc0776fd2f6739679d6967d11b40150985e81edcb86df4db", size = 18486, upload-time = "2026-08-07T04:17:12.504Z" }, ] [[package]] name = "typing-extensions" -version = "4.13.2" +version = "4.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] [[package]] name = "typing-inspection" -version = "0.4.1" +version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, ] [[package]] name = "urllib3" -version = "2.4.0" +version = "2.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, ] [package.optional-dependencies] @@ -1575,123 +1714,129 @@ socks = [ [[package]] name = "virtualenv" -version = "20.33.1" +version = "20.36.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/60/4f20960df6c7b363a18a55ab034c8f2bcd5d9770d1f94f9370ec104c1855/virtualenv-20.33.1.tar.gz", hash = "sha256:1b44478d9e261b3fb8baa5e74a0ca3bc0e05f21aa36167bf9cbf850e542765b8", size = 6082160, upload-time = "2025-08-05T16:10:55.605Z" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/a3/4d310fa5f00863544e1d0f4de93bddec248499ccf97d4791bc3122c9d4f3/virtualenv-20.36.1.tar.gz", hash = "sha256:8befb5c81842c641f8ee658481e42641c68b5eab3521d8e092d18320902466ba", size = 6032239, upload-time = "2026-01-09T18:21:01.296Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/ff/ded57ac5ff40a09e6e198550bab075d780941e0b0f83cbeabd087c59383a/virtualenv-20.33.1-py3-none-any.whl", hash = "sha256:07c19bc66c11acab6a5958b815cbcee30891cd1c2ccf53785a28651a0d8d8a67", size = 6060362, upload-time = "2025-08-05T16:10:52.81Z" }, + { url = "https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl", hash = "sha256:575a8d6b124ef88f6f51d56d656132389f961062a9177016a50e4f507bbcc19f", size = 6008258, upload-time = "2026-01-09T18:20:59.425Z" }, ] [[package]] name = "websocket-client" -version = "1.8.0" +version = "1.9.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e6/30/fba0d96b4b5fbf5948ed3f4681f7da2f9f64512e1d303f94b4cc174c24a5/websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da", size = 54648, upload-time = "2024-04-23T22:16:16.976Z" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826, upload-time = "2024-04-23T22:16:14.422Z" }, + { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, ] [[package]] name = "wrapt" -version = "1.17.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/8f/aeb76c5b46e273670962298c23e7ddde79916cb74db802131d49a85e4b7d/wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0", size = 55547, upload-time = "2025-08-12T05:53:21.714Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/23/bb82321b86411eb51e5a5db3fb8f8032fd30bd7c2d74bfe936136b2fa1d6/wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04", size = 53482, upload-time = "2025-08-12T05:51:44.467Z" }, - { url = "https://files.pythonhosted.org/packages/45/69/f3c47642b79485a30a59c63f6d739ed779fb4cc8323205d047d741d55220/wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2", size = 38676, upload-time = "2025-08-12T05:51:32.636Z" }, - { url = "https://files.pythonhosted.org/packages/d1/71/e7e7f5670c1eafd9e990438e69d8fb46fa91a50785332e06b560c869454f/wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c", size = 38957, upload-time = "2025-08-12T05:51:54.655Z" }, - { url = "https://files.pythonhosted.org/packages/de/17/9f8f86755c191d6779d7ddead1a53c7a8aa18bccb7cea8e7e72dfa6a8a09/wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775", size = 81975, upload-time = "2025-08-12T05:52:30.109Z" }, - { url = "https://files.pythonhosted.org/packages/f2/15/dd576273491f9f43dd09fce517f6c2ce6eb4fe21681726068db0d0467096/wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd", size = 83149, upload-time = "2025-08-12T05:52:09.316Z" }, - { url = "https://files.pythonhosted.org/packages/0c/c4/5eb4ce0d4814521fee7aa806264bf7a114e748ad05110441cd5b8a5c744b/wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05", size = 82209, upload-time = "2025-08-12T05:52:10.331Z" }, - { url = "https://files.pythonhosted.org/packages/31/4b/819e9e0eb5c8dc86f60dfc42aa4e2c0d6c3db8732bce93cc752e604bb5f5/wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418", size = 81551, upload-time = "2025-08-12T05:52:31.137Z" }, - { url = "https://files.pythonhosted.org/packages/f8/83/ed6baf89ba3a56694700139698cf703aac9f0f9eb03dab92f57551bd5385/wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390", size = 36464, upload-time = "2025-08-12T05:53:01.204Z" }, - { url = "https://files.pythonhosted.org/packages/2f/90/ee61d36862340ad7e9d15a02529df6b948676b9a5829fd5e16640156627d/wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6", size = 38748, upload-time = "2025-08-12T05:53:00.209Z" }, - { url = "https://files.pythonhosted.org/packages/bd/c3/cefe0bd330d389c9983ced15d326f45373f4073c9f4a8c2f99b50bfea329/wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18", size = 36810, upload-time = "2025-08-12T05:52:51.906Z" }, - { url = "https://files.pythonhosted.org/packages/52/db/00e2a219213856074a213503fdac0511203dceefff26e1daa15250cc01a0/wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7", size = 53482, upload-time = "2025-08-12T05:51:45.79Z" }, - { url = "https://files.pythonhosted.org/packages/5e/30/ca3c4a5eba478408572096fe9ce36e6e915994dd26a4e9e98b4f729c06d9/wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85", size = 38674, upload-time = "2025-08-12T05:51:34.629Z" }, - { url = "https://files.pythonhosted.org/packages/31/25/3e8cc2c46b5329c5957cec959cb76a10718e1a513309c31399a4dad07eb3/wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f", size = 38959, upload-time = "2025-08-12T05:51:56.074Z" }, - { url = "https://files.pythonhosted.org/packages/5d/8f/a32a99fc03e4b37e31b57cb9cefc65050ea08147a8ce12f288616b05ef54/wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311", size = 82376, upload-time = "2025-08-12T05:52:32.134Z" }, - { url = "https://files.pythonhosted.org/packages/31/57/4930cb8d9d70d59c27ee1332a318c20291749b4fba31f113c2f8ac49a72e/wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1", size = 83604, upload-time = "2025-08-12T05:52:11.663Z" }, - { url = "https://files.pythonhosted.org/packages/a8/f3/1afd48de81d63dd66e01b263a6fbb86e1b5053b419b9b33d13e1f6d0f7d0/wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5", size = 82782, upload-time = "2025-08-12T05:52:12.626Z" }, - { url = "https://files.pythonhosted.org/packages/1e/d7/4ad5327612173b144998232f98a85bb24b60c352afb73bc48e3e0d2bdc4e/wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2", size = 82076, upload-time = "2025-08-12T05:52:33.168Z" }, - { url = "https://files.pythonhosted.org/packages/bb/59/e0adfc831674a65694f18ea6dc821f9fcb9ec82c2ce7e3d73a88ba2e8718/wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89", size = 36457, upload-time = "2025-08-12T05:53:03.936Z" }, - { url = "https://files.pythonhosted.org/packages/83/88/16b7231ba49861b6f75fc309b11012ede4d6b0a9c90969d9e0db8d991aeb/wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77", size = 38745, upload-time = "2025-08-12T05:53:02.885Z" }, - { url = "https://files.pythonhosted.org/packages/9a/1e/c4d4f3398ec073012c51d1c8d87f715f56765444e1a4b11e5180577b7e6e/wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a", size = 36806, upload-time = "2025-08-12T05:52:53.368Z" }, - { url = "https://files.pythonhosted.org/packages/9f/41/cad1aba93e752f1f9268c77270da3c469883d56e2798e7df6240dcb2287b/wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0", size = 53998, upload-time = "2025-08-12T05:51:47.138Z" }, - { url = "https://files.pythonhosted.org/packages/60/f8/096a7cc13097a1869fe44efe68dace40d2a16ecb853141394047f0780b96/wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba", size = 39020, upload-time = "2025-08-12T05:51:35.906Z" }, - { url = "https://files.pythonhosted.org/packages/33/df/bdf864b8997aab4febb96a9ae5c124f700a5abd9b5e13d2a3214ec4be705/wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd", size = 39098, upload-time = "2025-08-12T05:51:57.474Z" }, - { url = "https://files.pythonhosted.org/packages/9f/81/5d931d78d0eb732b95dc3ddaeeb71c8bb572fb01356e9133916cd729ecdd/wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828", size = 88036, upload-time = "2025-08-12T05:52:34.784Z" }, - { url = "https://files.pythonhosted.org/packages/ca/38/2e1785df03b3d72d34fc6252d91d9d12dc27a5c89caef3335a1bbb8908ca/wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9", size = 88156, upload-time = "2025-08-12T05:52:13.599Z" }, - { url = "https://files.pythonhosted.org/packages/b3/8b/48cdb60fe0603e34e05cffda0b2a4adab81fd43718e11111a4b0100fd7c1/wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396", size = 87102, upload-time = "2025-08-12T05:52:14.56Z" }, - { url = "https://files.pythonhosted.org/packages/3c/51/d81abca783b58f40a154f1b2c56db1d2d9e0d04fa2d4224e357529f57a57/wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc", size = 87732, upload-time = "2025-08-12T05:52:36.165Z" }, - { url = "https://files.pythonhosted.org/packages/9e/b1/43b286ca1392a006d5336412d41663eeef1ad57485f3e52c767376ba7e5a/wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe", size = 36705, upload-time = "2025-08-12T05:53:07.123Z" }, - { url = "https://files.pythonhosted.org/packages/28/de/49493f962bd3c586ab4b88066e967aa2e0703d6ef2c43aa28cb83bf7b507/wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c", size = 38877, upload-time = "2025-08-12T05:53:05.436Z" }, - { url = "https://files.pythonhosted.org/packages/f1/48/0f7102fe9cb1e8a5a77f80d4f0956d62d97034bbe88d33e94699f99d181d/wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6", size = 36885, upload-time = "2025-08-12T05:52:54.367Z" }, - { url = "https://files.pythonhosted.org/packages/fc/f6/759ece88472157acb55fc195e5b116e06730f1b651b5b314c66291729193/wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0", size = 54003, upload-time = "2025-08-12T05:51:48.627Z" }, - { url = "https://files.pythonhosted.org/packages/4f/a9/49940b9dc6d47027dc850c116d79b4155f15c08547d04db0f07121499347/wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77", size = 39025, upload-time = "2025-08-12T05:51:37.156Z" }, - { url = "https://files.pythonhosted.org/packages/45/35/6a08de0f2c96dcdd7fe464d7420ddb9a7655a6561150e5fc4da9356aeaab/wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7", size = 39108, upload-time = "2025-08-12T05:51:58.425Z" }, - { url = "https://files.pythonhosted.org/packages/0c/37/6faf15cfa41bf1f3dba80cd3f5ccc6622dfccb660ab26ed79f0178c7497f/wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277", size = 88072, upload-time = "2025-08-12T05:52:37.53Z" }, - { url = "https://files.pythonhosted.org/packages/78/f2/efe19ada4a38e4e15b6dff39c3e3f3f73f5decf901f66e6f72fe79623a06/wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d", size = 88214, upload-time = "2025-08-12T05:52:15.886Z" }, - { url = "https://files.pythonhosted.org/packages/40/90/ca86701e9de1622b16e09689fc24b76f69b06bb0150990f6f4e8b0eeb576/wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa", size = 87105, upload-time = "2025-08-12T05:52:17.914Z" }, - { url = "https://files.pythonhosted.org/packages/fd/e0/d10bd257c9a3e15cbf5523025252cc14d77468e8ed644aafb2d6f54cb95d/wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050", size = 87766, upload-time = "2025-08-12T05:52:39.243Z" }, - { url = "https://files.pythonhosted.org/packages/e8/cf/7d848740203c7b4b27eb55dbfede11aca974a51c3d894f6cc4b865f42f58/wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8", size = 36711, upload-time = "2025-08-12T05:53:10.074Z" }, - { url = "https://files.pythonhosted.org/packages/57/54/35a84d0a4d23ea675994104e667ceff49227ce473ba6a59ba2c84f250b74/wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb", size = 38885, upload-time = "2025-08-12T05:53:08.695Z" }, - { url = "https://files.pythonhosted.org/packages/01/77/66e54407c59d7b02a3c4e0af3783168fff8e5d61def52cda8728439d86bc/wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16", size = 36896, upload-time = "2025-08-12T05:52:55.34Z" }, - { url = "https://files.pythonhosted.org/packages/02/a2/cd864b2a14f20d14f4c496fab97802001560f9f41554eef6df201cd7f76c/wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39", size = 54132, upload-time = "2025-08-12T05:51:49.864Z" }, - { url = "https://files.pythonhosted.org/packages/d5/46/d011725b0c89e853dc44cceb738a307cde5d240d023d6d40a82d1b4e1182/wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235", size = 39091, upload-time = "2025-08-12T05:51:38.935Z" }, - { url = "https://files.pythonhosted.org/packages/2e/9e/3ad852d77c35aae7ddebdbc3b6d35ec8013af7d7dddad0ad911f3d891dae/wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c", size = 39172, upload-time = "2025-08-12T05:51:59.365Z" }, - { url = "https://files.pythonhosted.org/packages/c3/f7/c983d2762bcce2326c317c26a6a1e7016f7eb039c27cdf5c4e30f4160f31/wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b", size = 87163, upload-time = "2025-08-12T05:52:40.965Z" }, - { url = "https://files.pythonhosted.org/packages/e4/0f/f673f75d489c7f22d17fe0193e84b41540d962f75fce579cf6873167c29b/wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa", size = 87963, upload-time = "2025-08-12T05:52:20.326Z" }, - { url = "https://files.pythonhosted.org/packages/df/61/515ad6caca68995da2fac7a6af97faab8f78ebe3bf4f761e1b77efbc47b5/wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7", size = 86945, upload-time = "2025-08-12T05:52:21.581Z" }, - { url = "https://files.pythonhosted.org/packages/d3/bd/4e70162ce398462a467bc09e768bee112f1412e563620adc353de9055d33/wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4", size = 86857, upload-time = "2025-08-12T05:52:43.043Z" }, - { url = "https://files.pythonhosted.org/packages/2b/b8/da8560695e9284810b8d3df8a19396a6e40e7518059584a1a394a2b35e0a/wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10", size = 37178, upload-time = "2025-08-12T05:53:12.605Z" }, - { url = "https://files.pythonhosted.org/packages/db/c8/b71eeb192c440d67a5a0449aaee2310a1a1e8eca41676046f99ed2487e9f/wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6", size = 39310, upload-time = "2025-08-12T05:53:11.106Z" }, - { url = "https://files.pythonhosted.org/packages/45/20/2cda20fd4865fa40f86f6c46ed37a2a8356a7a2fde0773269311f2af56c7/wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58", size = 37266, upload-time = "2025-08-12T05:52:56.531Z" }, - { url = "https://files.pythonhosted.org/packages/77/ed/dd5cf21aec36c80443c6f900449260b80e2a65cf963668eaef3b9accce36/wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a", size = 56544, upload-time = "2025-08-12T05:51:51.109Z" }, - { url = "https://files.pythonhosted.org/packages/8d/96/450c651cc753877ad100c7949ab4d2e2ecc4d97157e00fa8f45df682456a/wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067", size = 40283, upload-time = "2025-08-12T05:51:39.912Z" }, - { url = "https://files.pythonhosted.org/packages/d1/86/2fcad95994d9b572db57632acb6f900695a648c3e063f2cd344b3f5c5a37/wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454", size = 40366, upload-time = "2025-08-12T05:52:00.693Z" }, - { url = "https://files.pythonhosted.org/packages/64/0e/f4472f2fdde2d4617975144311f8800ef73677a159be7fe61fa50997d6c0/wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e", size = 108571, upload-time = "2025-08-12T05:52:44.521Z" }, - { url = "https://files.pythonhosted.org/packages/cc/01/9b85a99996b0a97c8a17484684f206cbb6ba73c1ce6890ac668bcf3838fb/wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f", size = 113094, upload-time = "2025-08-12T05:52:22.618Z" }, - { url = "https://files.pythonhosted.org/packages/25/02/78926c1efddcc7b3aa0bc3d6b33a822f7d898059f7cd9ace8c8318e559ef/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056", size = 110659, upload-time = "2025-08-12T05:52:24.057Z" }, - { url = "https://files.pythonhosted.org/packages/dc/ee/c414501ad518ac3e6fe184753632fe5e5ecacdcf0effc23f31c1e4f7bfcf/wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804", size = 106946, upload-time = "2025-08-12T05:52:45.976Z" }, - { url = "https://files.pythonhosted.org/packages/be/44/a1bd64b723d13bb151d6cc91b986146a1952385e0392a78567e12149c7b4/wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977", size = 38717, upload-time = "2025-08-12T05:53:15.214Z" }, - { url = "https://files.pythonhosted.org/packages/79/d9/7cfd5a312760ac4dd8bf0184a6ee9e43c33e47f3dadc303032ce012b8fa3/wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116", size = 41334, upload-time = "2025-08-12T05:53:14.178Z" }, - { url = "https://files.pythonhosted.org/packages/46/78/10ad9781128ed2f99dbc474f43283b13fea8ba58723e98844367531c18e9/wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6", size = 38471, upload-time = "2025-08-12T05:52:57.784Z" }, - { url = "https://files.pythonhosted.org/packages/41/be/be9b3b0a461ee3e30278706f3f3759b9b69afeedef7fe686036286c04ac6/wrapt-1.17.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc", size = 53485, upload-time = "2025-08-12T05:51:53.11Z" }, - { url = "https://files.pythonhosted.org/packages/b3/a8/8f61d6b8f526efc8c10e12bf80b4206099fea78ade70427846a37bc9cbea/wrapt-1.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9", size = 38675, upload-time = "2025-08-12T05:51:42.885Z" }, - { url = "https://files.pythonhosted.org/packages/48/f1/23950c29a25637b74b322f9e425a17cc01a478f6afb35138ecb697f9558d/wrapt-1.17.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d", size = 38956, upload-time = "2025-08-12T05:52:03.149Z" }, - { url = "https://files.pythonhosted.org/packages/43/46/dd0791943613885f62619f18ee6107e6133237a6b6ed8a9ecfac339d0b4f/wrapt-1.17.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a", size = 81745, upload-time = "2025-08-12T05:52:49.62Z" }, - { url = "https://files.pythonhosted.org/packages/dd/ec/bb2d19bd1a614cc4f438abac13ae26c57186197920432d2a915183b15a8b/wrapt-1.17.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139", size = 82833, upload-time = "2025-08-12T05:52:27.738Z" }, - { url = "https://files.pythonhosted.org/packages/8d/eb/66579aea6ad36f07617fedca8e282e49c7c9bab64c63b446cfe4f7f47a49/wrapt-1.17.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df", size = 81889, upload-time = "2025-08-12T05:52:29.023Z" }, - { url = "https://files.pythonhosted.org/packages/04/9c/a56b5ac0e2473bdc3fb11b22dd69ff423154d63861cf77911cdde5e38fd2/wrapt-1.17.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b", size = 81344, upload-time = "2025-08-12T05:52:50.869Z" }, - { url = "https://files.pythonhosted.org/packages/93/4c/9bd735c42641d81cb58d7bfb142c58f95c833962d15113026705add41a07/wrapt-1.17.3-cp39-cp39-win32.whl", hash = "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81", size = 36462, upload-time = "2025-08-12T05:53:19.623Z" }, - { url = "https://files.pythonhosted.org/packages/f0/ea/0b72f29cb5ebc16eb55c57dc0c98e5de76fc97f435fd407f7d409459c0a6/wrapt-1.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f", size = 38740, upload-time = "2025-08-12T05:53:18.271Z" }, - { url = "https://files.pythonhosted.org/packages/c3/8b/9eae65fb92321e38dbfec7719b87d840a4b92fde83fd1bbf238c5488d055/wrapt-1.17.3-cp39-cp39-win_arm64.whl", hash = "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f", size = 36806, upload-time = "2025-08-12T05:52:58.765Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f6/a933bd70f98e9cf3e08167fc5cd7aaaca49147e48411c0bd5ae701bb2194/wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22", size = 23591, upload-time = "2025-08-12T05:53:20.674Z" }, +version = "2.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/2a/6de8a50cb435b7f42c46126cf1a54b2aab81784e74c8595c8e025e8f36d3/wrapt-2.0.1.tar.gz", hash = "sha256:9c9c635e78497cacb81e84f8b11b23e0aacac7a136e73b8e5b2109a1d9fc468f", size = 82040, upload-time = "2025-11-07T00:45:33.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/0d/12d8c803ed2ce4e5e7d5b9f5f602721f9dfef82c95959f3ce97fa584bb5c/wrapt-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:64b103acdaa53b7caf409e8d45d39a8442fe6dcfec6ba3f3d141e0cc2b5b4dbd", size = 77481, upload-time = "2025-11-07T00:43:11.103Z" }, + { url = "https://files.pythonhosted.org/packages/05/3e/4364ebe221ebf2a44d9fc8695a19324692f7dd2795e64bd59090856ebf12/wrapt-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:91bcc576260a274b169c3098e9a3519fb01f2989f6d3d386ef9cbf8653de1374", size = 60692, upload-time = "2025-11-07T00:43:13.697Z" }, + { url = "https://files.pythonhosted.org/packages/1f/ff/ae2a210022b521f86a8ddcdd6058d137c051003812b0388a5e9a03d3fe10/wrapt-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab594f346517010050126fcd822697b25a7031d815bb4fbc238ccbe568216489", size = 61574, upload-time = "2025-11-07T00:43:14.967Z" }, + { url = "https://files.pythonhosted.org/packages/c6/93/5cf92edd99617095592af919cb81d4bff61c5dbbb70d3c92099425a8ec34/wrapt-2.0.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:36982b26f190f4d737f04a492a68accbfc6fa042c3f42326fdfbb6c5b7a20a31", size = 113688, upload-time = "2025-11-07T00:43:18.275Z" }, + { url = "https://files.pythonhosted.org/packages/a0/0a/e38fc0cee1f146c9fb266d8ef96ca39fb14a9eef165383004019aa53f88a/wrapt-2.0.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23097ed8bc4c93b7bf36fa2113c6c733c976316ce0ee2c816f64ca06102034ef", size = 115698, upload-time = "2025-11-07T00:43:19.407Z" }, + { url = "https://files.pythonhosted.org/packages/b0/85/bef44ea018b3925fb0bcbe9112715f665e4d5309bd945191da814c314fd1/wrapt-2.0.1-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8bacfe6e001749a3b64db47bcf0341da757c95959f592823a93931a422395013", size = 112096, upload-time = "2025-11-07T00:43:16.5Z" }, + { url = "https://files.pythonhosted.org/packages/7c/0b/733a2376e413117e497aa1a5b1b78e8f3a28c0e9537d26569f67d724c7c5/wrapt-2.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8ec3303e8a81932171f455f792f8df500fc1a09f20069e5c16bd7049ab4e8e38", size = 114878, upload-time = "2025-11-07T00:43:20.81Z" }, + { url = "https://files.pythonhosted.org/packages/da/03/d81dcb21bbf678fcda656495792b059f9d56677d119ca022169a12542bd0/wrapt-2.0.1-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:3f373a4ab5dbc528a94334f9fe444395b23c2f5332adab9ff4ea82f5a9e33bc1", size = 111298, upload-time = "2025-11-07T00:43:22.229Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d5/5e623040e8056e1108b787020d56b9be93dbbf083bf2324d42cde80f3a19/wrapt-2.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f49027b0b9503bf6c8cdc297ca55006b80c2f5dd36cecc72c6835ab6e10e8a25", size = 113361, upload-time = "2025-11-07T00:43:24.301Z" }, + { url = "https://files.pythonhosted.org/packages/a1/f3/de535ccecede6960e28c7b722e5744846258111d6c9f071aa7578ea37ad3/wrapt-2.0.1-cp310-cp310-win32.whl", hash = "sha256:8330b42d769965e96e01fa14034b28a2a7600fbf7e8f0cc90ebb36d492c993e4", size = 58035, upload-time = "2025-11-07T00:43:28.96Z" }, + { url = "https://files.pythonhosted.org/packages/21/15/39d3ca5428a70032c2ec8b1f1c9d24c32e497e7ed81aed887a4998905fcc/wrapt-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:1218573502a8235bb8a7ecaed12736213b22dcde9feab115fa2989d42b5ded45", size = 60383, upload-time = "2025-11-07T00:43:25.804Z" }, + { url = "https://files.pythonhosted.org/packages/43/c2/dfd23754b7f7a4dce07e08f4309c4e10a40046a83e9ae1800f2e6b18d7c1/wrapt-2.0.1-cp310-cp310-win_arm64.whl", hash = "sha256:eda8e4ecd662d48c28bb86be9e837c13e45c58b8300e43ba3c9b4fa9900302f7", size = 58894, upload-time = "2025-11-07T00:43:27.074Z" }, + { url = "https://files.pythonhosted.org/packages/98/60/553997acf3939079dab022e37b67b1904b5b0cc235503226898ba573b10c/wrapt-2.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0e17283f533a0d24d6e5429a7d11f250a58d28b4ae5186f8f47853e3e70d2590", size = 77480, upload-time = "2025-11-07T00:43:30.573Z" }, + { url = "https://files.pythonhosted.org/packages/2d/50/e5b3d30895d77c52105c6d5cbf94d5b38e2a3dd4a53d22d246670da98f7c/wrapt-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85df8d92158cb8f3965aecc27cf821461bb5f40b450b03facc5d9f0d4d6ddec6", size = 60690, upload-time = "2025-11-07T00:43:31.594Z" }, + { url = "https://files.pythonhosted.org/packages/f0/40/660b2898703e5cbbb43db10cdefcc294274458c3ca4c68637c2b99371507/wrapt-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c1be685ac7700c966b8610ccc63c3187a72e33cab53526a27b2a285a662cd4f7", size = 61578, upload-time = "2025-11-07T00:43:32.918Z" }, + { url = "https://files.pythonhosted.org/packages/5b/36/825b44c8a10556957bc0c1d84c7b29a40e05fcf1873b6c40aa9dbe0bd972/wrapt-2.0.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:df0b6d3b95932809c5b3fecc18fda0f1e07452d05e2662a0b35548985f256e28", size = 114115, upload-time = "2025-11-07T00:43:35.605Z" }, + { url = "https://files.pythonhosted.org/packages/83/73/0a5d14bb1599677304d3c613a55457d34c344e9b60eda8a737c2ead7619e/wrapt-2.0.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4da7384b0e5d4cae05c97cd6f94faaf78cc8b0f791fc63af43436d98c4ab37bb", size = 116157, upload-time = "2025-11-07T00:43:37.058Z" }, + { url = "https://files.pythonhosted.org/packages/01/22/1c158fe763dbf0a119f985d945711d288994fe5514c0646ebe0eb18b016d/wrapt-2.0.1-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ec65a78fbd9d6f083a15d7613b2800d5663dbb6bb96003899c834beaa68b242c", size = 112535, upload-time = "2025-11-07T00:43:34.138Z" }, + { url = "https://files.pythonhosted.org/packages/5c/28/4f16861af67d6de4eae9927799b559c20ebdd4fe432e89ea7fe6fcd9d709/wrapt-2.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7de3cc939be0e1174969f943f3b44e0d79b6f9a82198133a5b7fc6cc92882f16", size = 115404, upload-time = "2025-11-07T00:43:39.214Z" }, + { url = "https://files.pythonhosted.org/packages/a0/8b/7960122e625fad908f189b59c4aae2d50916eb4098b0fb2819c5a177414f/wrapt-2.0.1-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:fb1a5b72cbd751813adc02ef01ada0b0d05d3dcbc32976ce189a1279d80ad4a2", size = 111802, upload-time = "2025-11-07T00:43:40.476Z" }, + { url = "https://files.pythonhosted.org/packages/3e/73/7881eee5ac31132a713ab19a22c9e5f1f7365c8b1df50abba5d45b781312/wrapt-2.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3fa272ca34332581e00bf7773e993d4f632594eb2d1b0b162a9038df0fd971dd", size = 113837, upload-time = "2025-11-07T00:43:42.921Z" }, + { url = "https://files.pythonhosted.org/packages/45/00/9499a3d14e636d1f7089339f96c4409bbc7544d0889f12264efa25502ae8/wrapt-2.0.1-cp311-cp311-win32.whl", hash = "sha256:fc007fdf480c77301ab1afdbb6ab22a5deee8885f3b1ed7afcb7e5e84a0e27be", size = 58028, upload-time = "2025-11-07T00:43:47.369Z" }, + { url = "https://files.pythonhosted.org/packages/70/5d/8f3d7eea52f22638748f74b102e38fdf88cb57d08ddeb7827c476a20b01b/wrapt-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:47434236c396d04875180171ee1f3815ca1eada05e24a1ee99546320d54d1d1b", size = 60385, upload-time = "2025-11-07T00:43:44.34Z" }, + { url = "https://files.pythonhosted.org/packages/14/e2/32195e57a8209003587bbbad44d5922f13e0ced2a493bb46ca882c5b123d/wrapt-2.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:837e31620e06b16030b1d126ed78e9383815cbac914693f54926d816d35d8edf", size = 58893, upload-time = "2025-11-07T00:43:46.161Z" }, + { url = "https://files.pythonhosted.org/packages/cb/73/8cb252858dc8254baa0ce58ce382858e3a1cf616acebc497cb13374c95c6/wrapt-2.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1fdbb34da15450f2b1d735a0e969c24bdb8d8924892380126e2a293d9902078c", size = 78129, upload-time = "2025-11-07T00:43:48.852Z" }, + { url = "https://files.pythonhosted.org/packages/19/42/44a0db2108526ee6e17a5ab72478061158f34b08b793df251d9fbb9a7eb4/wrapt-2.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3d32794fe940b7000f0519904e247f902f0149edbe6316c710a8562fb6738841", size = 61205, upload-time = "2025-11-07T00:43:50.402Z" }, + { url = "https://files.pythonhosted.org/packages/4d/8a/5b4b1e44b791c22046e90d9b175f9a7581a8cc7a0debbb930f81e6ae8e25/wrapt-2.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:386fb54d9cd903ee0012c09291336469eb7b244f7183d40dc3e86a16a4bace62", size = 61692, upload-time = "2025-11-07T00:43:51.678Z" }, + { url = "https://files.pythonhosted.org/packages/11/53/3e794346c39f462bcf1f58ac0487ff9bdad02f9b6d5ee2dc84c72e0243b2/wrapt-2.0.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7b219cb2182f230676308cdcacd428fa837987b89e4b7c5c9025088b8a6c9faf", size = 121492, upload-time = "2025-11-07T00:43:55.017Z" }, + { url = "https://files.pythonhosted.org/packages/c6/7e/10b7b0e8841e684c8ca76b462a9091c45d62e8f2de9c4b1390b690eadf16/wrapt-2.0.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:641e94e789b5f6b4822bb8d8ebbdfc10f4e4eae7756d648b717d980f657a9eb9", size = 123064, upload-time = "2025-11-07T00:43:56.323Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d1/3c1e4321fc2f5ee7fd866b2d822aa89b84495f28676fd976c47327c5b6aa/wrapt-2.0.1-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:fe21b118b9f58859b5ebaa4b130dee18669df4bd111daad082b7beb8799ad16b", size = 117403, upload-time = "2025-11-07T00:43:53.258Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b0/d2f0a413cf201c8c2466de08414a15420a25aa83f53e647b7255cc2fab5d/wrapt-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:17fb85fa4abc26a5184d93b3efd2dcc14deb4b09edcdb3535a536ad34f0b4dba", size = 121500, upload-time = "2025-11-07T00:43:57.468Z" }, + { url = "https://files.pythonhosted.org/packages/bd/45/bddb11d28ca39970a41ed48a26d210505120f925918592283369219f83cc/wrapt-2.0.1-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:b89ef9223d665ab255ae42cc282d27d69704d94be0deffc8b9d919179a609684", size = 116299, upload-time = "2025-11-07T00:43:58.877Z" }, + { url = "https://files.pythonhosted.org/packages/81/af/34ba6dd570ef7a534e7eec0c25e2615c355602c52aba59413411c025a0cb/wrapt-2.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a453257f19c31b31ba593c30d997d6e5be39e3b5ad9148c2af5a7314061c63eb", size = 120622, upload-time = "2025-11-07T00:43:59.962Z" }, + { url = "https://files.pythonhosted.org/packages/e2/3e/693a13b4146646fb03254636f8bafd20c621955d27d65b15de07ab886187/wrapt-2.0.1-cp312-cp312-win32.whl", hash = "sha256:3e271346f01e9c8b1130a6a3b0e11908049fe5be2d365a5f402778049147e7e9", size = 58246, upload-time = "2025-11-07T00:44:03.169Z" }, + { url = "https://files.pythonhosted.org/packages/a7/36/715ec5076f925a6be95f37917b66ebbeaa1372d1862c2ccd7a751574b068/wrapt-2.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:2da620b31a90cdefa9cd0c2b661882329e2e19d1d7b9b920189956b76c564d75", size = 60492, upload-time = "2025-11-07T00:44:01.027Z" }, + { url = "https://files.pythonhosted.org/packages/ef/3e/62451cd7d80f65cc125f2b426b25fbb6c514bf6f7011a0c3904fc8c8df90/wrapt-2.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:aea9c7224c302bc8bfc892b908537f56c430802560e827b75ecbde81b604598b", size = 58987, upload-time = "2025-11-07T00:44:02.095Z" }, + { url = "https://files.pythonhosted.org/packages/ad/fe/41af4c46b5e498c90fc87981ab2972fbd9f0bccda597adb99d3d3441b94b/wrapt-2.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:47b0f8bafe90f7736151f61482c583c86b0693d80f075a58701dd1549b0010a9", size = 78132, upload-time = "2025-11-07T00:44:04.628Z" }, + { url = "https://files.pythonhosted.org/packages/1c/92/d68895a984a5ebbbfb175512b0c0aad872354a4a2484fbd5552e9f275316/wrapt-2.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cbeb0971e13b4bd81d34169ed57a6dda017328d1a22b62fda45e1d21dd06148f", size = 61211, upload-time = "2025-11-07T00:44:05.626Z" }, + { url = "https://files.pythonhosted.org/packages/e8/26/ba83dc5ae7cf5aa2b02364a3d9cf74374b86169906a1f3ade9a2d03cf21c/wrapt-2.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb7cffe572ad0a141a7886a1d2efa5bef0bf7fe021deeea76b3ab334d2c38218", size = 61689, upload-time = "2025-11-07T00:44:06.719Z" }, + { url = "https://files.pythonhosted.org/packages/cf/67/d7a7c276d874e5d26738c22444d466a3a64ed541f6ef35f740dbd865bab4/wrapt-2.0.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c8d60527d1ecfc131426b10d93ab5d53e08a09c5fa0175f6b21b3252080c70a9", size = 121502, upload-time = "2025-11-07T00:44:09.557Z" }, + { url = "https://files.pythonhosted.org/packages/0f/6b/806dbf6dd9579556aab22fc92908a876636e250f063f71548a8660382184/wrapt-2.0.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c654eafb01afac55246053d67a4b9a984a3567c3808bb7df2f8de1c1caba2e1c", size = 123110, upload-time = "2025-11-07T00:44:10.64Z" }, + { url = "https://files.pythonhosted.org/packages/e5/08/cdbb965fbe4c02c5233d185d070cabed2ecc1f1e47662854f95d77613f57/wrapt-2.0.1-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:98d873ed6c8b4ee2418f7afce666751854d6d03e3c0ec2a399bb039cd2ae89db", size = 117434, upload-time = "2025-11-07T00:44:08.138Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d1/6aae2ce39db4cb5216302fa2e9577ad74424dfbe315bd6669725569e048c/wrapt-2.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9e850f5b7fc67af856ff054c71690d54fa940c3ef74209ad9f935b4f66a0233", size = 121533, upload-time = "2025-11-07T00:44:12.142Z" }, + { url = "https://files.pythonhosted.org/packages/79/35/565abf57559fbe0a9155c29879ff43ce8bd28d2ca61033a3a3dd67b70794/wrapt-2.0.1-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e505629359cb5f751e16e30cf3f91a1d3ddb4552480c205947da415d597f7ac2", size = 116324, upload-time = "2025-11-07T00:44:13.28Z" }, + { url = "https://files.pythonhosted.org/packages/e1/e0/53ff5e76587822ee33e560ad55876d858e384158272cd9947abdd4ad42ca/wrapt-2.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2879af909312d0baf35f08edeea918ee3af7ab57c37fe47cb6a373c9f2749c7b", size = 120627, upload-time = "2025-11-07T00:44:14.431Z" }, + { url = "https://files.pythonhosted.org/packages/7c/7b/38df30fd629fbd7612c407643c63e80e1c60bcc982e30ceeae163a9800e7/wrapt-2.0.1-cp313-cp313-win32.whl", hash = "sha256:d67956c676be5a24102c7407a71f4126d30de2a569a1c7871c9f3cabc94225d7", size = 58252, upload-time = "2025-11-07T00:44:17.814Z" }, + { url = "https://files.pythonhosted.org/packages/85/64/d3954e836ea67c4d3ad5285e5c8fd9d362fd0a189a2db622df457b0f4f6a/wrapt-2.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9ca66b38dd642bf90c59b6738af8070747b610115a39af2498535f62b5cdc1c3", size = 60500, upload-time = "2025-11-07T00:44:15.561Z" }, + { url = "https://files.pythonhosted.org/packages/89/4e/3c8b99ac93527cfab7f116089db120fef16aac96e5f6cdb724ddf286086d/wrapt-2.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:5a4939eae35db6b6cec8e7aa0e833dcca0acad8231672c26c2a9ab7a0f8ac9c8", size = 58993, upload-time = "2025-11-07T00:44:16.65Z" }, + { url = "https://files.pythonhosted.org/packages/f9/f4/eff2b7d711cae20d220780b9300faa05558660afb93f2ff5db61fe725b9a/wrapt-2.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a52f93d95c8d38fed0669da2ebdb0b0376e895d84596a976c15a9eb45e3eccb3", size = 82028, upload-time = "2025-11-07T00:44:18.944Z" }, + { url = "https://files.pythonhosted.org/packages/0c/67/cb945563f66fd0f61a999339460d950f4735c69f18f0a87ca586319b1778/wrapt-2.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e54bbf554ee29fcceee24fa41c4d091398b911da6e7f5d7bffda963c9aed2e1", size = 62949, upload-time = "2025-11-07T00:44:20.074Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ca/f63e177f0bbe1e5cf5e8d9b74a286537cd709724384ff20860f8f6065904/wrapt-2.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:908f8c6c71557f4deaa280f55d0728c3bca0960e8c3dd5ceeeafb3c19942719d", size = 63681, upload-time = "2025-11-07T00:44:21.345Z" }, + { url = "https://files.pythonhosted.org/packages/39/a1/1b88fcd21fd835dca48b556daef750952e917a2794fa20c025489e2e1f0f/wrapt-2.0.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e2f84e9af2060e3904a32cea9bb6db23ce3f91cfd90c6b426757cf7cc01c45c7", size = 152696, upload-time = "2025-11-07T00:44:24.318Z" }, + { url = "https://files.pythonhosted.org/packages/62/1c/d9185500c1960d9f5f77b9c0b890b7fc62282b53af7ad1b6bd779157f714/wrapt-2.0.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e3612dc06b436968dfb9142c62e5dfa9eb5924f91120b3c8ff501ad878f90eb3", size = 158859, upload-time = "2025-11-07T00:44:25.494Z" }, + { url = "https://files.pythonhosted.org/packages/91/60/5d796ed0f481ec003220c7878a1d6894652efe089853a208ea0838c13086/wrapt-2.0.1-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6d2d947d266d99a1477cd005b23cbd09465276e302515e122df56bb9511aca1b", size = 146068, upload-time = "2025-11-07T00:44:22.81Z" }, + { url = "https://files.pythonhosted.org/packages/04/f8/75282dd72f102ddbfba137e1e15ecba47b40acff32c08ae97edbf53f469e/wrapt-2.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7d539241e87b650cbc4c3ac9f32c8d1ac8a54e510f6dca3f6ab60dcfd48c9b10", size = 155724, upload-time = "2025-11-07T00:44:26.634Z" }, + { url = "https://files.pythonhosted.org/packages/5a/27/fe39c51d1b344caebb4a6a9372157bdb8d25b194b3561b52c8ffc40ac7d1/wrapt-2.0.1-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:4811e15d88ee62dbf5c77f2c3ff3932b1e3ac92323ba3912f51fc4016ce81ecf", size = 144413, upload-time = "2025-11-07T00:44:27.939Z" }, + { url = "https://files.pythonhosted.org/packages/83/2b/9f6b643fe39d4505c7bf926d7c2595b7cb4b607c8c6b500e56c6b36ac238/wrapt-2.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c1c91405fcf1d501fa5d55df21e58ea49e6b879ae829f1039faaf7e5e509b41e", size = 150325, upload-time = "2025-11-07T00:44:29.29Z" }, + { url = "https://files.pythonhosted.org/packages/bb/b6/20ffcf2558596a7f58a2e69c89597128781f0b88e124bf5a4cadc05b8139/wrapt-2.0.1-cp313-cp313t-win32.whl", hash = "sha256:e76e3f91f864e89db8b8d2a8311d57df93f01ad6bb1e9b9976d1f2e83e18315c", size = 59943, upload-time = "2025-11-07T00:44:33.211Z" }, + { url = "https://files.pythonhosted.org/packages/87/6a/0e56111cbb3320151eed5d3821ee1373be13e05b376ea0870711f18810c3/wrapt-2.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:83ce30937f0ba0d28818807b303a412440c4b63e39d3d8fc036a94764b728c92", size = 63240, upload-time = "2025-11-07T00:44:30.935Z" }, + { url = "https://files.pythonhosted.org/packages/1d/54/5ab4c53ea1f7f7e5c3e7c1095db92932cc32fd62359d285486d00c2884c3/wrapt-2.0.1-cp313-cp313t-win_arm64.whl", hash = "sha256:4b55cacc57e1dc2d0991dbe74c6419ffd415fb66474a02335cb10efd1aa3f84f", size = 60416, upload-time = "2025-11-07T00:44:32.002Z" }, + { url = "https://files.pythonhosted.org/packages/73/81/d08d83c102709258e7730d3cd25befd114c60e43ef3891d7e6877971c514/wrapt-2.0.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:5e53b428f65ece6d9dad23cb87e64506392b720a0b45076c05354d27a13351a1", size = 78290, upload-time = "2025-11-07T00:44:34.691Z" }, + { url = "https://files.pythonhosted.org/packages/f6/14/393afba2abb65677f313aa680ff0981e829626fed39b6a7e3ec807487790/wrapt-2.0.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ad3ee9d0f254851c71780966eb417ef8e72117155cff04821ab9b60549694a55", size = 61255, upload-time = "2025-11-07T00:44:35.762Z" }, + { url = "https://files.pythonhosted.org/packages/c4/10/a4a1f2fba205a9462e36e708ba37e5ac95f4987a0f1f8fd23f0bf1fc3b0f/wrapt-2.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7b822c61ed04ee6ad64bc90d13368ad6eb094db54883b5dde2182f67a7f22c0", size = 61797, upload-time = "2025-11-07T00:44:37.22Z" }, + { url = "https://files.pythonhosted.org/packages/12/db/99ba5c37cf1c4fad35349174f1e38bd8d992340afc1ff27f526729b98986/wrapt-2.0.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7164a55f5e83a9a0b031d3ffab4d4e36bbec42e7025db560f225489fa929e509", size = 120470, upload-time = "2025-11-07T00:44:39.425Z" }, + { url = "https://files.pythonhosted.org/packages/30/3f/a1c8d2411eb826d695fc3395a431757331582907a0ec59afce8fe8712473/wrapt-2.0.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e60690ba71a57424c8d9ff28f8d006b7ad7772c22a4af432188572cd7fa004a1", size = 122851, upload-time = "2025-11-07T00:44:40.582Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8d/72c74a63f201768d6a04a8845c7976f86be6f5ff4d74996c272cefc8dafc/wrapt-2.0.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3cd1a4bd9a7a619922a8557e1318232e7269b5fb69d4ba97b04d20450a6bf970", size = 117433, upload-time = "2025-11-07T00:44:38.313Z" }, + { url = "https://files.pythonhosted.org/packages/c7/5a/df37cf4042cb13b08256f8e27023e2f9b3d471d553376616591bb99bcb31/wrapt-2.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b4c2e3d777e38e913b8ce3a6257af72fb608f86a1df471cb1d4339755d0a807c", size = 121280, upload-time = "2025-11-07T00:44:41.69Z" }, + { url = "https://files.pythonhosted.org/packages/54/34/40d6bc89349f9931e1186ceb3e5fbd61d307fef814f09fbbac98ada6a0c8/wrapt-2.0.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3d366aa598d69416b5afedf1faa539fac40c1d80a42f6b236c88c73a3c8f2d41", size = 116343, upload-time = "2025-11-07T00:44:43.013Z" }, + { url = "https://files.pythonhosted.org/packages/70/66/81c3461adece09d20781dee17c2366fdf0cb8754738b521d221ca056d596/wrapt-2.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c235095d6d090aa903f1db61f892fffb779c1eaeb2a50e566b52001f7a0f66ed", size = 119650, upload-time = "2025-11-07T00:44:44.523Z" }, + { url = "https://files.pythonhosted.org/packages/46/3a/d0146db8be8761a9e388cc9cc1c312b36d583950ec91696f19bbbb44af5a/wrapt-2.0.1-cp314-cp314-win32.whl", hash = "sha256:bfb5539005259f8127ea9c885bdc231978c06b7a980e63a8a61c8c4c979719d0", size = 58701, upload-time = "2025-11-07T00:44:48.277Z" }, + { url = "https://files.pythonhosted.org/packages/1a/38/5359da9af7d64554be63e9046164bd4d8ff289a2dd365677d25ba3342c08/wrapt-2.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:4ae879acc449caa9ed43fc36ba08392b9412ee67941748d31d94e3cedb36628c", size = 60947, upload-time = "2025-11-07T00:44:46.086Z" }, + { url = "https://files.pythonhosted.org/packages/aa/3f/96db0619276a833842bf36343685fa04f987dd6e3037f314531a1e00492b/wrapt-2.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:8639b843c9efd84675f1e100ed9e99538ebea7297b62c4b45a7042edb84db03e", size = 59359, upload-time = "2025-11-07T00:44:47.164Z" }, + { url = "https://files.pythonhosted.org/packages/71/49/5f5d1e867bf2064bf3933bc6cf36ade23505f3902390e175e392173d36a2/wrapt-2.0.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:9219a1d946a9b32bb23ccae66bdb61e35c62773ce7ca6509ceea70f344656b7b", size = 82031, upload-time = "2025-11-07T00:44:49.4Z" }, + { url = "https://files.pythonhosted.org/packages/2b/89/0009a218d88db66ceb83921e5685e820e2c61b59bbbb1324ba65342668bc/wrapt-2.0.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:fa4184e74197af3adad3c889a1af95b53bb0466bced92ea99a0c014e48323eec", size = 62952, upload-time = "2025-11-07T00:44:50.74Z" }, + { url = "https://files.pythonhosted.org/packages/ae/18/9b968e920dd05d6e44bcc918a046d02afea0fb31b2f1c80ee4020f377cbe/wrapt-2.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c5ef2f2b8a53b7caee2f797ef166a390fef73979b15778a4a153e4b5fedce8fa", size = 63688, upload-time = "2025-11-07T00:44:52.248Z" }, + { url = "https://files.pythonhosted.org/packages/a6/7d/78bdcb75826725885d9ea26c49a03071b10c4c92da93edda612910f150e4/wrapt-2.0.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e042d653a4745be832d5aa190ff80ee4f02c34b21f4b785745eceacd0907b815", size = 152706, upload-time = "2025-11-07T00:44:54.613Z" }, + { url = "https://files.pythonhosted.org/packages/dd/77/cac1d46f47d32084a703df0d2d29d47e7eb2a7d19fa5cbca0e529ef57659/wrapt-2.0.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2afa23318136709c4b23d87d543b425c399887b4057936cd20386d5b1422b6fa", size = 158866, upload-time = "2025-11-07T00:44:55.79Z" }, + { url = "https://files.pythonhosted.org/packages/8a/11/b521406daa2421508903bf8d5e8b929216ec2af04839db31c0a2c525eee0/wrapt-2.0.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6c72328f668cf4c503ffcf9434c2b71fdd624345ced7941bc6693e61bbe36bef", size = 146148, upload-time = "2025-11-07T00:44:53.388Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c0/340b272bed297baa7c9ce0c98ef7017d9c035a17a6a71dce3184b8382da2/wrapt-2.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3793ac154afb0e5b45d1233cb94d354ef7a983708cc3bb12563853b1d8d53747", size = 155737, upload-time = "2025-11-07T00:44:56.971Z" }, + { url = "https://files.pythonhosted.org/packages/f3/93/bfcb1fb2bdf186e9c2883a4d1ab45ab099c79cbf8f4e70ea453811fa3ea7/wrapt-2.0.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:fec0d993ecba3991645b4857837277469c8cc4c554a7e24d064d1ca291cfb81f", size = 144451, upload-time = "2025-11-07T00:44:58.515Z" }, + { url = "https://files.pythonhosted.org/packages/d2/6b/dca504fb18d971139d232652656180e3bd57120e1193d9a5899c3c0b7cdd/wrapt-2.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:949520bccc1fa227274da7d03bf238be15389cd94e32e4297b92337df9b7a349", size = 150353, upload-time = "2025-11-07T00:44:59.753Z" }, + { url = "https://files.pythonhosted.org/packages/1d/f6/a1de4bd3653afdf91d250ca5c721ee51195df2b61a4603d4b373aa804d1d/wrapt-2.0.1-cp314-cp314t-win32.whl", hash = "sha256:be9e84e91d6497ba62594158d3d31ec0486c60055c49179edc51ee43d095f79c", size = 60609, upload-time = "2025-11-07T00:45:03.315Z" }, + { url = "https://files.pythonhosted.org/packages/01/3a/07cd60a9d26fe73efead61c7830af975dfdba8537632d410462672e4432b/wrapt-2.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:61c4956171c7434634401db448371277d07032a81cc21c599c22953374781395", size = 64038, upload-time = "2025-11-07T00:45:00.948Z" }, + { url = "https://files.pythonhosted.org/packages/41/99/8a06b8e17dddbf321325ae4eb12465804120f699cd1b8a355718300c62da/wrapt-2.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:35cdbd478607036fee40273be8ed54a451f5f23121bd9d4be515158f9498f7ad", size = 60634, upload-time = "2025-11-07T00:45:02.087Z" }, + { url = "https://files.pythonhosted.org/packages/15/d1/b51471c11592ff9c012bd3e2f7334a6ff2f42a7aed2caffcf0bdddc9cb89/wrapt-2.0.1-py3-none-any.whl", hash = "sha256:4d2ce1bf1a48c5277d7969259232b57645aae5686dba1eaeade39442277afbca", size = 44046, upload-time = "2025-11-07T00:45:32.116Z" }, ] [[package]] name = "wsproto" -version = "1.2.0" +version = "1.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425, upload-time = "2022-08-23T19:58:21.447Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226, upload-time = "2022-08-23T19:58:19.96Z" }, -] - -[[package]] -name = "zipp" -version = "3.23.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e3/02/0f2892c661036d50ede074e376733dca2ae7c6eb617489437771209d4180/zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166", size = 25547, upload-time = "2025-06-08T17:06:39.4Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/79/12135bdf8b9c9367b8701c2c19a14c913c120b882d50b014ca0d38083c2c/wsproto-1.3.2.tar.gz", hash = "sha256:b86885dcf294e15204919950f666e06ffc6c7c114ca900b060d6e16293528294", size = 50116, upload-time = "2025-11-20T18:18:01.871Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/54/647ade08bf0db230bfea292f893923872fd20be6ac6f53b2b936ba839d75/zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e", size = 10276, upload-time = "2025-06-08T17:06:38.034Z" }, + { url = "https://files.pythonhosted.org/packages/a4/f5/10b68b7b1544245097b2a1b8238f66f2fc6dcaeb24ba5d917f52bd2eed4f/wsproto-1.3.2-py3-none-any.whl", hash = "sha256:61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584", size = 24405, upload-time = "2025-11-20T18:18:00.454Z" }, ]