diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7a97743..b299420 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,18 +1,32 @@ version: 2 updates: -- package-ecosystem: "pip" - directory: "/" - schedule: - interval: "weekly" - groups: - python: - patterns: - - "*" -- package-ecosystem: "cargo" - directory: "/" - schedule: - interval: "weekly" - groups: - rust: - patterns: - - "*" + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "monthly" + cooldown: + default-days: 14 + groups: + python: + patterns: + - "*" + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "monthly" + cooldown: + default-days: 14 + groups: + rust: + patterns: + - "*" + - package-ecosystem: "github-actions" + directory: ".github/workflows" + schedule: + interval: "monthly" + cooldown: + default-days: 14 + groups: + actions: + patterns: + - "*" diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 5630ba4..0b06a31 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -12,13 +12,17 @@ concurrency: env: FORCE_COLOR: 1 +permissions: {} + jobs: check: runs-on: "ubuntu-latest" name: "check" steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + persist-credentials: false + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.12" diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 3b70b5f..d86dcf2 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -12,25 +12,32 @@ concurrency: env: FORCE_COLOR: 1 +permissions: {} + jobs: - pythonbuild: - if: ${{ needs.generate-matrix.outputs.pythonbuild_changed == 'true' || needs.generate-matrix.outputs.any_builds == 'true' || github.ref == 'refs/heads/main' }} + crate-build: needs: - generate-matrix - runs-on: depot-ubuntu-22.04 + runs-on: ${{ matrix.runner }} + strategy: + matrix: ${{ fromJson(needs.generate-matrix.outputs.crate-build-matrix) }} + fail-fast: false + name: crate / ${{ matrix.arch }} steps: - name: Install System Dependencies run: | sudo apt update sudo apt install -y --no-install-recommends libssl-dev pkg-config - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + persist-credentials: false - name: Emit rustc version run: | rustc --version > .rustc-version - - uses: actions/cache@v4 + - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: | ~/.cargo/registry @@ -43,40 +50,37 @@ jobs: cargo build --release - name: Upload pythonbuild Executable - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: pythonbuild + name: ${{ matrix.crate_artifact_name }} path: target/release/pythonbuild image: - if: ${{ needs.generate-matrix.outputs.any_builds == 'true' }} + if: ${{ needs.generate-matrix.outputs.pythonbuild_changed == 'true' || needs.generate-matrix.outputs.any_builds == 'true' || github.ref == 'refs/heads/main' }} needs: - generate-matrix strategy: fail-fast: false - matrix: - image: - - build - - build.cross - - build.cross-riscv64 - - gcc - name: ${{ matrix.image }} - runs-on: depot-ubuntu-22.04 + matrix: ${{ fromJson(needs.generate-matrix.outputs.docker-build-matrix) }} + name: image / ${{ matrix.arch }} / ${{ matrix.name }} + runs-on: ${{ matrix.runner }} permissions: packages: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: - python-version: '3.11' + python-version: "3.11" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3 + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Login to GitHub Container Registry - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -92,96 +96,114 @@ jobs: - name: Build Image id: build-image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + env: + SOURCE_DATE_EPOCH: 0 with: context: . - file: build/${{ matrix.image }}.Dockerfile + file: build/${{ matrix.name }}.Dockerfile labels: org.opencontainers.image.source=https://github.com/${{ env.REPO_NAME }} # Cache from/to the current branch of the current repo as the primary cache key. # Cache from the default branch of the current repo so branches can have cache hits. # Cache from the default branch of the canonical repo so forks can have cache hits. # Ignore errors on cache writes so CI of forks works without a valid GHCR config. cache-from: | - type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.image }}-${{ env.GIT_REF_NAME }} - type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.image }}-main - type=registry,ref=ghcr.io/astral-sh/python-build-standalone:${{ matrix.image }}-main + type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-linux_${{ matrix.arch }}-${{ env.GIT_REF_NAME }} + type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-linux_${{ matrix.arch }}-main + type=registry,ref=ghcr.io/astral-sh/python-build-standalone:${{ matrix.name }}-linux_${{ matrix.arch }}-main cache-to: | - type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.image }}-${{ env.GIT_REF_NAME }},ignore-error=true + type=registry,ref=ghcr.io/${{ env.REPO_NAME }}:${{ matrix.name }}-linux_${{ matrix.arch }}-${{ env.GIT_REF_NAME }},ignore-error=true outputs: | - type=docker,dest=build/image-${{ matrix.image }}.tar + type=docker,dest=build/image-${{ matrix.name }}.linux_${{ matrix.arch }}.tar - name: Compress Image run: | - echo ${{ steps.build-image.outputs.imageid }} > build/image-${{ matrix.image }} + echo ${STEPS_BUILD_IMAGE_OUTPUTS_IMAGEID} > build/image-${MATRIX_NAME}.linux_${MATRIX_ARCH} zstd -v -T0 -6 --rm build/image-*.tar + touch -t 197001010000 build/image-* + env: + STEPS_BUILD_IMAGE_OUTPUTS_IMAGEID: ${{ steps.build-image.outputs.imageid }} + MATRIX_NAME: ${{ matrix.name }} + MATRIX_ARCH: ${{ matrix.arch }} - name: Upload Docker Image - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: image-${{ matrix.image }} + name: image-${{ matrix.name }}-linux_${{ matrix.arch }} path: build/image-* + compression-level: '0' generate-matrix: + name: Generate build matrix runs-on: ubuntu-latest outputs: - matrix-0: ${{ steps.set-matrix.outputs.matrix-0 }} - matrix-1: ${{ steps.set-matrix.outputs.matrix-1 }} + python-build-matrix-0: ${{ steps.set-matrix.outputs.python-build-matrix-0 }} + python-build-matrix-1: ${{ steps.set-matrix.outputs.python-build-matrix-1 }} + docker-build-matrix: ${{ steps.set-matrix.outputs.docker-build-matrix }} + crate-build-matrix: ${{ steps.set-matrix.outputs.crate-build-matrix }} any_builds: ${{ steps.set-matrix.outputs.any_builds }} - pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: - fetch-depth: 0 # fetch history for subsequent `git diff` + fetch-depth: 0 + persist-credentials: false - name: Set up Python - uses: astral-sh/setup-uv@v4 + uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4.2.0 - name: Get pull request labels id: get-labels + env: + PULL_REQUEST_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }} run: | # Convert GitHub labels array to comma-separated string - LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")') + LABELS=$(echo "${PULL_REQUEST_LABELS}" | jq -r 'join(",")') echo "labels=$LABELS" >> $GITHUB_OUTPUT + - name: Check if the `pythonbuild` crate changed + id: check-pythonbuild + env: + BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }} + run: | + merge_base=$(git merge-base HEAD "origin/${BASE_REF}") + if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + - name: Generate build matrix id: set-matrix run: | uv run ci-matrix.py \ --platform linux \ - --labels '${{ steps.get-labels.outputs.labels }}' \ + --labels "${STEPS_GET_LABELS_OUTPUTS_LABELS}" \ --max-shards 2 \ + ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} \ > matrix.json - echo "matrix-0=$(jq -c '.["0"]' matrix.json)" >> $GITHUB_OUTPUT - echo "matrix-1=$(jq -c '.["1"]' matrix.json)" >> $GITHUB_OUTPUT + echo "python-build-matrix-0=$(jq -c '."python-build"["0"]' matrix.json)" >> $GITHUB_OUTPUT + echo "python-build-matrix-1=$(jq -c '."python-build"["1"]' matrix.json)" >> $GITHUB_OUTPUT + echo "docker-build-matrix=$(jq -c '."docker-build"' matrix.json)" >> $GITHUB_OUTPUT + echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT # Display the matrix for debugging too cat matrix.json | jq - if jq -e '.["0"].include | length > 0' matrix.json > /dev/null; then + if jq -e '."python-build"["0"].include | length > 0' matrix.json > /dev/null; then # Build matrix has entries echo "any_builds=true" >> $GITHUB_OUTPUT else # Build matrix is empty echo "any_builds=false" >> $GITHUB_OUTPUT fi - - - name: Check if the `pythonbuild` crate changed - id: check-pythonbuild env: - BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }} - run: | - merge_base=$(git merge-base HEAD "origin/${BASE_REF}") - if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then - echo "changed=false" >> "$GITHUB_OUTPUT" - else - echo "changed=true" >> "$GITHUB_OUTPUT" - fi + STEPS_GET_LABELS_OUTPUTS_LABELS: ${{ steps.get-labels.outputs.labels }} build-0: needs: - generate-matrix - - pythonbuild + - crate-build - image # Permissions used for actions/attest-build-provenance permissions: @@ -189,34 +211,35 @@ jobs: attestations: write runs-on: ${{ matrix.runner }} strategy: - matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-0) }} + matrix: ${{ fromJson(needs.generate-matrix.outputs.python-build-matrix-0) }} fail-fast: false name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 0 + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: - python-version: '3.11' + python-version: "3.11" - name: Download pythonbuild - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - name: pythonbuild + name: ${{ matrix.crate_artifact_name }} path: build - name: Download images - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: pattern: image-* path: build merge-multiple: true - name: Cache downloads - uses: actions/cache@v4 + uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: build/downloads key: ${{ matrix.target_triple }}-${{ hashFiles('pythonbuild/downloads.py')}} @@ -245,15 +268,32 @@ jobs: # Touch mtimes of all images so they are newer than autogenerated files above. touch build/image-* - ./build-linux.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }} + ./build-linux.py --target-triple ${MATRIX_TARGET_TRIPLE} --python cpython-${MATRIX_PYTHON} --options ${MATRIX_BUILD_OPTIONS} + env: + MATRIX_TARGET_TRIPLE: ${{ matrix.target_triple }} + MATRIX_PYTHON: ${{ matrix.python }} + MATRIX_BUILD_OPTIONS: ${{ matrix.build_options }} + + - name: Generate attestations + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0 + if: ${{ github.ref == 'refs/heads/main' }} + with: + subject-path: dist/* + + - name: Upload Distribution + if: ${{ ! matrix.dry-run }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }} + path: dist/* - name: Validate Distribution if: ${{ ! matrix.dry-run }} run: | chmod +x build/pythonbuild - if [ "${{ matrix.run }}" == "true" ]; then - if [ "${{ matrix.libc }}" == "musl" ]; then + if [ "${MATRIX_RUN}" == "true" ]; then + if [ "${MATRIX_LIBC}" == "musl" ]; then sudo apt install musl-dev # GitHub's setup-python action sets `LD_LIBRARY_PATH` which overrides `RPATH` @@ -264,24 +304,14 @@ jobs: fi build/pythonbuild validate-distribution ${EXTRA_ARGS} dist/*.tar.zst - - - name: Generate attestations - uses: actions/attest-build-provenance@v2 - if: ${{ github.ref == 'refs/heads/main' }} - with: - subject-path: dist/* - - - name: Upload Distribution - if: ${{ ! matrix.dry-run }} - uses: actions/upload-artifact@v4 - with: - name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }} - path: dist/* + env: + MATRIX_RUN: ${{ matrix.run }} + MATRIX_LIBC: ${{ matrix.libc }} build-1: needs: - generate-matrix - - pythonbuild + - crate-build - image # Permissions used for actions/attest-build-provenance permissions: @@ -289,34 +319,35 @@ jobs: attestations: write runs-on: ${{ matrix.runner }} strategy: - matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-1) }} + matrix: ${{ fromJson(needs.generate-matrix.outputs.python-build-matrix-1) }} fail-fast: false name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 0 + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: - python-version: '3.11' + python-version: "3.11" - name: Download pythonbuild - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - name: pythonbuild + name: ${{ matrix.crate_artifact_name }} path: build - name: Download images - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: pattern: image-* path: build merge-multiple: true - name: Cache downloads - uses: actions/cache@v4 + uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: build/downloads key: ${{ matrix.target_triple }}-${{ hashFiles('pythonbuild/downloads.py')}} @@ -345,15 +376,32 @@ jobs: # Touch mtimes of all images so they are newer than autogenerated files above. touch build/image-* - ./build-linux.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }} + ./build-linux.py --target-triple ${MATRIX_TARGET_TRIPLE} --python cpython-${MATRIX_PYTHON} --options ${MATRIX_BUILD_OPTIONS} + env: + MATRIX_TARGET_TRIPLE: ${{ matrix.target_triple }} + MATRIX_PYTHON: ${{ matrix.python }} + MATRIX_BUILD_OPTIONS: ${{ matrix.build_options }} + + - name: Generate attestations + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0 + if: ${{ github.ref == 'refs/heads/main' }} + with: + subject-path: dist/* + + - name: Upload Distribution + if: ${{ ! matrix.dry-run }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }} + path: dist/* - name: Validate Distribution if: ${{ ! matrix.dry-run }} run: | chmod +x build/pythonbuild - if [ "${{ matrix.run }}" == "true" ]; then - if [ "${{ matrix.libc }}" == "musl" ]; then + if [ "${MATRIX_RUN}" == "true" ]; then + if [ "${MATRIX_LIBC}" == "musl" ]; then sudo apt install musl-dev # GitHub's setup-python action sets `LD_LIBRARY_PATH` which overrides `RPATH` @@ -364,16 +412,6 @@ jobs: fi build/pythonbuild validate-distribution ${EXTRA_ARGS} dist/*.tar.zst - - - name: Generate attestations - uses: actions/attest-build-provenance@v2 - if: ${{ github.ref == 'refs/heads/main' }} - with: - subject-path: dist/* - - - name: Upload Distribution - if: ${{ ! matrix.dry-run }} - uses: actions/upload-artifact@v4 - with: - name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }} - path: dist/* + env: + MATRIX_RUN: ${{ matrix.run }} + MATRIX_LIBC: ${{ matrix.libc }} diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index af9a80f..b746a96 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -12,20 +12,27 @@ concurrency: env: FORCE_COLOR: 1 +permissions: {} + jobs: - pythonbuild: - if: ${{ needs.generate-matrix.outputs.pythonbuild_changed == 'true' || needs.generate-matrix.outputs.any_builds == 'true' || github.ref == 'refs/heads/main' }} + crate-build: needs: - generate-matrix - runs-on: depot-macos-latest + runs-on: ${{ matrix.runner }} + strategy: + matrix: ${{ fromJson(needs.generate-matrix.outputs.crate-build-matrix) }} + fail-fast: false + name: crate / ${{ matrix.arch }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + persist-credentials: false - name: Emit rustc version run: | rustc --version > .rustc-version - - uses: actions/cache@v4 + - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: | ~/.cargo/registry @@ -38,63 +45,74 @@ jobs: cargo build --release - name: Upload pythonbuild Executable - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: pythonbuild + name: ${{ matrix.crate_artifact_name }} path: target/release/pythonbuild generate-matrix: + name: Generate build matrix runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} + crate-build-matrix: ${{ steps.set-matrix.outputs.crate-build-matrix }} any_builds: ${{ steps.set-matrix.outputs.any_builds }} - pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: - fetch-depth: 0 # fetch history for subsequent `git diff` + fetch-depth: 0 + persist-credentials: false - name: Set up Python - uses: astral-sh/setup-uv@v4 + uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4.2.0 - name: Get pull request labels id: get-labels + env: + PULL_REQUEST_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }} run: | # Convert GitHub labels array to comma-separated string - LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")') + LABELS=$(echo "${PULL_REQUEST_LABELS}" | jq -r 'join(",")') echo "labels=$LABELS" >> $GITHUB_OUTPUT + - name: Check if the `pythonbuild` crate changed + id: check-pythonbuild + env: + BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }} + run: | + merge_base=$(git merge-base HEAD "origin/${BASE_REF}") + if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + - name: Generate build matrix id: set-matrix run: | - uv run ci-matrix.py --platform darwin --labels '${{ steps.get-labels.outputs.labels }}' > matrix.json && echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT + uv run ci-matrix.py --platform darwin --labels "${STEPS_GET_LABELS_OUTPUTS_LABELS}" ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json + + # Extract python-build matrix + echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT + echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT + # Display the matrix for debugging too cat matrix.json | jq - if jq -e '.include | length > 0' matrix.json > /dev/null; then + if jq -e '."python-build".include | length > 0' matrix.json > /dev/null; then # Build matrix has entries echo "any_builds=true" >> $GITHUB_OUTPUT else # Build matrix is empty echo "any_builds=false" >> $GITHUB_OUTPUT fi - - - name: Check if the `pythonbuild` crate changed - id: check-pythonbuild env: - BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }} - run: | - merge_base=$(git merge-base HEAD "origin/${BASE_REF}") - if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then - echo "changed=false" >> "$GITHUB_OUTPUT" - else - echo "changed=true" >> "$GITHUB_OUTPUT" - fi + STEPS_GET_LABELS_OUTPUTS_LABELS: ${{ steps.get-labels.outputs.labels }} build: needs: - generate-matrix - - pythonbuild + - crate-build # Permissions used for actions/attest-build-provenance permissions: id-token: write @@ -105,55 +123,61 @@ jobs: fail-fast: false name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 0 + persist-credentials: false - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: - python-version: '3.11' + python-version: "3.11" - name: Download pythonbuild - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - name: pythonbuild + name: ${{ matrix.crate_artifact_name }} path: build - name: Build if: ${{ ! matrix.dry-run }} run: | - if [ "${{ matrix.target_triple }}" = "aarch64-apple-darwin" ]; then + if [ "${MATRIX_TARGET_TRIPLE}" = "aarch64-apple-darwin" ]; then export APPLE_SDK_PATH=/Applications/Xcode_15.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk - elif [ "${{ matrix.target_triple }}" = "x86_64-apple-darwin" ]; then + elif [ "${MATRIX_TARGET_TRIPLE}" = "x86_64-apple-darwin" ]; then export APPLE_SDK_PATH=/Applications/Xcode_15.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.2.sdk else - echo "unhandled target triple: ${{ matrix.target_triple }}" + echo "unhandled target triple: ${MATRIX_TARGET_TRIPLE}" exit 1 fi - ./build-macos.py --target-triple ${{ matrix.target_triple }} --python cpython-${{ matrix.python }} --options ${{ matrix.build_options }} + ./build-macos.py --target-triple ${MATRIX_TARGET_TRIPLE} --python cpython-${MATRIX_PYTHON} --options ${MATRIX_BUILD_OPTIONS} + env: + MATRIX_TARGET_TRIPLE: ${{ matrix.target_triple }} + MATRIX_PYTHON: ${{ matrix.python }} + MATRIX_BUILD_OPTIONS: ${{ matrix.build_options }} - name: Generate attestations - uses: actions/attest-build-provenance@v2 + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0 if: ${{ github.ref == 'refs/heads/main' }} with: subject-path: dist/* - name: Upload Distributions if: ${{ ! matrix.dry-run }} - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: cpython-${{ matrix.python }}-${{ matrix.target_triple }}-${{ matrix.build_options }} path: dist/* - name: Checkout macOS SDKs for validation if: ${{ ! matrix.dry-run }} - uses: actions/checkout@v4 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: - repository: 'phracker/MacOSX-SDKs' + repository: phracker/MacOSX-SDKs ref: master path: macosx-sdks + persist-credentials: false - name: Validate Distribution if: ${{ ! matrix.dry-run }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6381b3e..343ac8a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,30 +18,39 @@ on: env: FORCE_COLOR: 1 -permissions: - contents: write - packages: write - # Permissions used for actions/attest-build-provenance - id-token: write - attestations: write +permissions: {} jobs: release: + name: Release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - runs-on: github-ubuntu-24.04-x86_64-16 + runs-on: ubuntu-latest + + permissions: + contents: write + packages: write + # Permissions used for actions/attest-build-provenance + id-token: write + attestations: write + steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: submodules: recursive + persist-credentials: true # needed for git operations below - - uses: extractions/setup-just@dd310ad5a97d8e7b41793f8ef055398d51ad4de6 # v2 + - uses: extractions/setup-crate@4993624604c307fbca528d28a3c8b60fa5ecc859 # v1.4.0 + with: + repo: casey/just + version: 1.42.4 # Perform a release in dry-run mode. - - run: just release-dry-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }} + - run: just release-dry-run ${GH_TOKEN} ${GITHUB_EVENT_INPUTS_SHA} ${GITHUB_EVENT_INPUTS_TAG} if: ${{ github.event.inputs.dry-run == 'true' }} - - # Set our identity for git operations (on the latest-release branch). + env: + GITHUB_EVENT_INPUTS_SHA: ${{ github.event.inputs.sha }} + GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }} - name: Configure Git identity if: ${{ github.event.inputs.dry-run == 'false' }} run: | @@ -51,30 +60,38 @@ jobs: # Fetch the commit so that it exists locally. - name: Fetch commit if: ${{ github.event.inputs.dry-run == 'false' }} - run: git fetch origin ${{ github.event.inputs.sha }} + run: git fetch origin ${GITHUB_EVENT_INPUTS_SHA} + env: + GITHUB_EVENT_INPUTS_SHA: ${{ github.event.inputs.sha }} # Associate the commit with the tag. - name: Create tag if: ${{ github.event.inputs.dry-run == 'false' }} - run: git tag ${{ github.event.inputs.tag }} ${{ github.event.inputs.sha }} - - # Push the tag to GitHub. + run: git tag ${GITHUB_EVENT_INPUTS_TAG} ${GITHUB_EVENT_INPUTS_SHA} + env: + GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }} + GITHUB_EVENT_INPUTS_SHA: ${{ github.event.inputs.sha }} - name: Push tag if: ${{ github.event.inputs.dry-run == 'false' }} - run: git push origin ${{ github.event.inputs.tag }} + run: git push origin ${GITHUB_EVENT_INPUTS_TAG} + env: + GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }} # Create a GitHub release. - name: Create GitHub Release if: ${{ github.event.inputs.dry-run == 'false' }} - run: just release-create ${{ github.event.inputs.tag }} + run: just release-create ${GITHUB_EVENT_INPUTS_TAG} + env: + GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }} # Uploading the relevant artifact to the GitHub release. - - run: just release-run ${{ secrets.GITHUB_TOKEN }} ${{ github.event.inputs.sha }} ${{ github.event.inputs.tag }} + - run: just release-run ${GH_TOKEN} ${GITHUB_EVENT_INPUTS_SHA} ${GITHUB_EVENT_INPUTS_TAG} if: ${{ github.event.inputs.dry-run == 'false' }} - - # We filter by *.tar.@(zst|gz) since actions/attest-build-provenance only supports up to 1024 subjects + env: + GITHUB_EVENT_INPUTS_SHA: ${{ github.event.inputs.sha }} + GITHUB_EVENT_INPUTS_TAG: ${{ github.event.inputs.tag }} - name: Generate attestations - uses: actions/attest-build-provenance@v2 + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0 if: ${{ github.event.inputs.dry-run == 'false' }} with: subject-path: | diff --git a/.github/workflows/security-3rd-party-pr-checks.yml b/.github/workflows/security-3rd-party-pr-checks.yml new file mode 100644 index 0000000..5337dab --- /dev/null +++ b/.github/workflows/security-3rd-party-pr-checks.yml @@ -0,0 +1,10 @@ +name: security-3rd-party-pr-checks +on: + # Allow for manual run of security workflows + workflow_dispatch: + # Scan changed files in PRs (diff-aware scanning): + pull_request: {} +jobs: + running-3rd-party-pr-security-checks: + uses: verkada/securitybots/.github/workflows/3rd-party-pr-checks.yml@main + secrets: inherit diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index a7535c6..30f5878 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,9 +1,7 @@ name: windows on: - push: - branches: [main] - pull_request: + workflow_dispatch: # Only run manually concurrency: group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }} @@ -12,20 +10,27 @@ concurrency: env: FORCE_COLOR: 1 +permissions: {} + jobs: - pythonbuild: - if: ${{ needs.generate-matrix.outputs.pythonbuild_changed == 'true' || needs.generate-matrix.outputs.any_builds == 'true' || github.ref == 'refs/heads/main' }} + crate-build: needs: - generate-matrix - runs-on: 'windows-2022' + runs-on: ${{ matrix.runner }} + strategy: + matrix: ${{ fromJson(needs.generate-matrix.outputs.crate-build-matrix) }} + fail-fast: false + name: crate / ${{ matrix.arch }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 + with: + persist-credentials: false - name: Emit rustc version run: | rustc --version > .rustc-version - - uses: actions/cache@v4 + - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: | C:/Rust/.cargo/registry @@ -38,63 +43,75 @@ jobs: cargo build --release - name: Upload executable - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: pythonbuild + name: ${{ matrix.crate_artifact_name }} path: target/release/pythonbuild.exe generate-matrix: + name: Generate build matrix runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} + crate-build-matrix: ${{ steps.set-matrix.outputs.crate-build-matrix }} any_builds: ${{ steps.set-matrix.outputs.any_builds }} - pythonbuild_changed: ${{ steps.check-pythonbuild.outputs.changed }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: - fetch-depth: 0 # fetch history for subsequent `git diff` + fetch-depth: 0 + persist-credentials: false - name: Set up Python - uses: astral-sh/setup-uv@v4 + uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4.2.0 - name: Get pull request labels id: get-labels + env: + PULL_REQUEST_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }} run: | # Convert GitHub labels array to comma-separated string - LABELS=$(echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | jq -r 'join(",")') + LABELS=$(echo "${PULL_REQUEST_LABELS}" | jq -r 'join(",")') echo "labels=$LABELS" >> $GITHUB_OUTPUT + - name: Check if the `pythonbuild` crate changed + id: check-pythonbuild + env: + BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }} + run: | + merge_base=$(git merge-base HEAD "origin/${BASE_REF}") + if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then + echo "changed=false" >> "$GITHUB_OUTPUT" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + - name: Generate build matrix id: set-matrix run: | - uv run ci-matrix.py --platform windows --labels '${{ steps.get-labels.outputs.labels }}' > matrix.json && echo "matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT + uv run ci-matrix.py --platform windows --labels "${STEPS_GET_LABELS_OUTPUTS_LABELS}" ${{ (steps.check-pythonbuild.outputs.changed == 'true' || github.ref == 'refs/heads/main') && '--force-crate-build' || '' }} > matrix.json + + # Extract python-build matrix + echo "matrix=$(jq -c '."python-build"' matrix.json)" >> $GITHUB_OUTPUT + echo "crate-build-matrix=$(jq -c '."crate-build"' matrix.json)" >> $GITHUB_OUTPUT + # Display the matrix for debugging too cat matrix.json | jq - if jq -e '.include | length > 0' matrix.json > /dev/null; then + if jq -e '."python-build".include | length > 0' matrix.json > /dev/null; then # Build matrix has entries echo "any_builds=true" >> $GITHUB_OUTPUT else # Build matrix is empty echo "any_builds=false" >> $GITHUB_OUTPUT fi - - - name: Check if the `pythonbuild` crate changed - id: check-pythonbuild env: - BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }} - run: | - merge_base=$(git merge-base HEAD "origin/${BASE_REF}") - if git diff --quiet "${merge_base}...HEAD" -- ':src/*.rs'; then - echo "changed=false" >> "$GITHUB_OUTPUT" - else - echo "changed=true" >> "$GITHUB_OUTPUT" - fi + STEPS_GET_LABELS_OUTPUTS_LABELS: ${{ steps.get-labels.outputs.labels }} build: + timeout-minutes: 60 needs: - generate-matrix - - pythonbuild + - crate-build # Permissions used for actions/attest-build-provenance permissions: id-token: write @@ -105,24 +122,25 @@ jobs: fail-fast: false name: ${{ matrix.target_triple }} / ${{ matrix.python }} / ${{ matrix.build_options }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 with: fetch-depth: 0 + persist-credentials: false - name: Install Cygwin Environment - uses: cygwin/cygwin-install-action@49f298a7ebb00d4b3ddf58000c3e78eff5fbd6b9 # v2 + uses: cygwin/cygwin-install-action@f2009323764960f80959895c7bc3bb30210afe4d # v6 with: packages: autoconf automake libtool - name: Install Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: - python-version: '3.12' + python-version: "3.12" - name: Download pythonbuild Executable - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - name: pythonbuild + name: ${{ matrix.crate_artifact_name }} # We need to do this before we activate the VC++ environment or else binary packages # don't get compiled properly. @@ -134,23 +152,27 @@ jobs: if: ${{ ! matrix.dry-run }} shell: cmd run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\${{ matrix.vcvars }}" - py.exe -3.12 build-windows.py --python cpython-${{ matrix.python }} --sh c:\cygwin\bin\sh.exe --options ${{ matrix.build_options }} - - - name: Validate Distribution - if: ${{ ! matrix.dry-run }} - run: | - $Dists = Resolve-Path -Path "dist/*.tar.zst" -Relative - .\pythonbuild.exe validate-distribution --run $Dists + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\%MATRIX_VCVARS%" + py.exe -3.12 build-windows.py --python cpython-%MATRIX_PYTHON% --sh c:\cygwin\bin\sh.exe --options %MATRIX_BUILD_OPTIONS% + env: + MATRIX_VCVARS: ${{ matrix.vcvars }} + MATRIX_PYTHON: ${{ matrix.python }} + MATRIX_BUILD_OPTIONS: ${{ matrix.build_options }} - name: Generate attestations - uses: actions/attest-build-provenance@v2 + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0 if: ${{ github.ref == 'refs/heads/main' }} with: subject-path: dist/* - name: Upload Distributions - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: cpython-${{ matrix.python }}-${{ matrix.vcvars }}-${{ matrix.build_options }} path: dist/* + + - name: Validate Distribution + if: ${{ ! matrix.dry-run }} + run: | + $Dists = Resolve-Path -Path "dist/*.tar.zst" -Relative + .\pythonbuild.exe validate-distribution --run $Dists diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000..a60e286 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,24 @@ +name: zizmor + +on: + push: + branches: ["main"] + pull_request: + branches: ["**"] + +permissions: {} + +jobs: + zizmor: + name: Run zizmor + runs-on: ubuntu-latest + permissions: + security-events: write + steps: + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: Run zizmor + uses: zizmorcore/zizmor-action@f52a838cfabf134edcbaa7c8b3677dde20045018 # v0.1.1 diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 0000000..e7920e8 --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,5 @@ +rules: + unpinned-uses: + config: + policies: + "*": hash-pin diff --git a/Cargo.lock b/Cargo.lock index b0db167..6a2f089 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -263,8 +263,10 @@ checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-targets", ] @@ -327,6 +329,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -395,17 +407,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derive_more" -version = "0.99.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "digest" version = "0.10.7" @@ -782,25 +783,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "log", - "rustls 0.22.4", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.25.0", - "tower-service", -] - [[package]] name = "hyper-rustls" version = "0.27.5" @@ -811,10 +793,12 @@ dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.22", + "log", + "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.1", + "tokio-rustls", "tower-service", "webpki-roots", ] @@ -1217,7 +1201,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework", + "security-framework 2.11.1", "security-framework-sys", "tempfile", ] @@ -1264,29 +1248,29 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ - "flate2", "memchr", - "ruzstd", ] [[package]] name = "object" -version = "0.36.7" +version = "0.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a" dependencies = [ + "flate2", "memchr", + "ruzstd", ] [[package]] name = "octocrab" -version = "0.34.3" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4e00a4268539fda6c431a0fd01d016d4b44c361f9c283d0eb8f1ab7408a517" +checksum = "86996964f8b721067b6ed238aa0ccee56ecad6ee5e714468aa567992d05d2b91" dependencies = [ "arc-swap", "async-trait", @@ -1302,7 +1286,7 @@ dependencies = [ "http-body", "http-body-util", "hyper", - "hyper-rustls 0.26.0", + "hyper-rustls", "hyper-timeout", "hyper-util", "jsonwebtoken", @@ -1316,10 +1300,11 @@ dependencies = [ "serde_urlencoded", "snafu", "tokio", - "tower 0.4.13", + "tower", "tower-http", "tracing", "url", + "web-time", ] [[package]] @@ -1567,7 +1552,7 @@ dependencies = [ "hyper", "hyper-util", "normalize-path", - "object 0.32.2", + "object 0.37.1", "octocrab", "once_cell", "pdb", @@ -1585,6 +1570,7 @@ dependencies = [ "tempfile", "text-stub-library", "tokio", + "tokio-util", "url", "version-compare", "zip", @@ -1611,7 +1597,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.22", + "rustls", "socket2", "thiserror 2.0.11", "tokio", @@ -1629,7 +1615,7 @@ dependencies = [ "rand", "ring", "rustc-hash", - "rustls 0.23.22", + "rustls", "rustls-pki-types", "slab", "thiserror 2.0.11", @@ -1745,7 +1731,7 @@ dependencies = [ "http-body", "http-body-util", "hyper", - "hyper-rustls 0.27.5", + "hyper-rustls", "hyper-tls", "hyper-util", "ipnet", @@ -1757,7 +1743,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.22", + "rustls", "rustls-pemfile", "rustls-pki-types", "serde", @@ -1767,9 +1753,9 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls 0.26.1", + "tokio-rustls", "tokio-util", - "tower 0.5.2", + "tower", "tower-service", "url", "wasm-bindgen", @@ -1865,26 +1851,13 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "rustls" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - [[package]] name = "rustls" version = "0.23.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7" dependencies = [ + "log", "once_cell", "ring", "rustls-pki-types", @@ -1895,15 +1868,14 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.3" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" dependencies = [ "openssl-probe", - "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 3.2.0", ] [[package]] @@ -1943,12 +1915,10 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ruzstd" -version = "0.5.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d" +checksum = "3640bec8aad418d7d03c72ea2de10d5c646a598f9883c7babc160d91e3c1b26c" dependencies = [ - "byteorder", - "derive_more", "twox-hash", ] @@ -2001,9 +1971,9 @@ dependencies = [ [[package]] name = "secrecy" -version = "0.8.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" dependencies = [ "zeroize", ] @@ -2015,7 +1985,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.8.0", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +dependencies = [ + "bitflags 2.8.0", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -2206,12 +2189,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" version = "0.11.1" @@ -2262,7 +2239,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.8.0", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys", ] @@ -2433,24 +2410,13 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.22", + "rustls", "tokio", ] @@ -2467,23 +2433,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower" version = "0.5.2" @@ -2495,25 +2444,26 @@ dependencies = [ "pin-project-lite", "sync_wrapper", "tokio", + "tokio-util", "tower-layer", "tower-service", + "tracing", ] [[package]] name = "tower-http" -version = "0.5.2" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" dependencies = [ "bitflags 2.8.0", "bytes", "futures-util", "http", "http-body", - "http-body-util", "iri-string", "pin-project-lite", - "tower 0.4.13", + "tower", "tower-layer", "tower-service", "tracing", @@ -2571,13 +2521,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "twox-hash" -version = "1.6.3" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "static_assertions", -] +checksum = "8b907da542cbced5261bd3256de1b3a1bf340a3d37f93425a07362a1d687de56" [[package]] name = "typenum" @@ -2809,6 +2755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", + "serde", "wasm-bindgen", ] diff --git a/Cargo.toml b/Cargo.toml index 82f0298..beca9e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "pythonbuild" version = "0.1.0" authors = ["Gregory Szorc "] -edition = "2021" +edition = "2024" [dependencies] anyhow = "1.0.80" @@ -19,8 +19,8 @@ http-body-util = "0.1.0" hyper = { version = "1.2.0", features = ["client"] } hyper-util = { version = "0.1.3" } normalize-path = "0.2.1" -object = "0.32.2" -octocrab = { version = "0.34.1", features = ["rustls", "stream"] } +object = "0.37.1" +octocrab = { version = "0.44.1", features = ["rustls", "stream"] } once_cell = "1.19.0" pdb = "0.8.0" pep440_rs = "0.6.6" @@ -37,6 +37,7 @@ tar = "0.4.40" tempfile = "3.10.0" text-stub-library = "0.9.0" tokio = "1.43.1" +tokio-util = "0.7.13" url = "2.5.0" version-compare = "0.1.1" zip = "0.6.6" diff --git a/Justfile b/Justfile index c9b8167..1118075 100644 --- a/Justfile +++ b/Justfile @@ -28,15 +28,15 @@ cat-python-json archive: # Download release artifacts from GitHub Actions release-download-distributions token commit: mkdir -p dist - cargo run --release -- fetch-release-distributions --token {{token}} --commit {{commit}} --dest dist + cargo run --release -- fetch-release-distributions --org verkada --token {{token}} --commit {{commit}} --dest dist # Upload release artifacts to a GitHub release. release-upload-distributions token datetime tag: - cargo run --release -- upload-release-distributions --token {{token}} --datetime {{datetime}} --tag {{tag}} --dist dist + cargo run --release -- upload-release-distributions --org verkada --token {{token}} --datetime {{datetime}} --tag {{tag}} --dist dist # "Upload" release artifacts to a GitHub release in dry-run mode (skip upload). release-upload-distributions-dry-run token datetime tag: - cargo run --release -- upload-release-distributions --token {{token}} --datetime {{datetime}} --tag {{tag}} --dist dist -n + cargo run --release -- upload-release-distributions --org verkada --token {{token}} --datetime {{datetime}} --tag {{tag}} --dist dist -n # Promote a tag to "latest" by pushing to the `latest-release` branch. release-set-latest-release tag: diff --git a/build-windows.py b/build-windows.py index df836b6..4a8c897 100644 --- a/build-windows.py +++ b/build-windows.py @@ -5,6 +5,7 @@ import os import pathlib +import platform import subprocess import sys import venv @@ -15,7 +16,8 @@ VENV = BUILD / "venv" PIP = VENV / "Scripts" / "pip.exe" PYTHON = VENV / "Scripts" / "python.exe" -REQUIREMENTS = ROOT / "requirements.win.txt" +ARCH = "-arm64" if platform.machine() == "ARM64" else "" +REQUIREMENTS = ROOT / f"requirements.win{ARCH}.txt" WINDOWS_DIR = ROOT / "cpython-windows" diff --git a/ci-matrix.py b/ci-matrix.py index c9bccce..91cfa95 100644 --- a/ci-matrix.py +++ b/ci-matrix.py @@ -20,6 +20,21 @@ CI_MATRIX_SIZE_LIMIT = 256 # The maximum size of a matrix in GitHub Actions +# Docker images for building toolchains and dependencies +DOCKER_BUILD_IMAGES = [ + {"name": "build", "arch": "x86_64"}, + {"name": "build.cross", "arch": "x86_64"}, + {"name": "build.cross-riscv64", "arch": "x86_64"}, + {"name": "build.debian9", "arch": "aarch64"}, + {"name": "gcc", "arch": "x86_64"}, + {"name": "gcc.debian9", "arch": "aarch64"}, +] + + +def crate_artifact_name(platform: str, arch: str) -> str: + return f"crate-{platform}-{arch}" + + def meets_conditional_version(version: str, min_version: str) -> bool: return Version(version) >= Version(min_version) @@ -89,12 +104,87 @@ def should_include_entry(entry: dict[str, str], filters: dict[str, set[str]]) -> return True -def generate_matrix_entries( +def generate_docker_matrix_entries( + runners: dict[str, Any], + platform_filter: Optional[str] = None, +) -> list[dict[str, str]]: + """Generate matrix entries for docker image builds.""" + if platform_filter and platform_filter != "linux": + return [] + + matrix_entries = [] + for image in DOCKER_BUILD_IMAGES: + # Find appropriate runner for Linux platform with the specified architecture + runner = find_runner(runners, "linux", image["arch"], False) + + entry = { + "name": image["name"], + "arch": image["arch"], + "runner": runner, + } + matrix_entries.append(entry) + + return matrix_entries + + +def generate_crate_build_matrix_entries( + python_entries: list[dict[str, str]], + runners: dict[str, Any], + config: dict[str, Any], + force_crate_build: bool = False, + platform_filter: Optional[str] = None, +) -> list[dict[str, str]]: + """Generate matrix entries for crate builds based on python build matrix.""" + needed_builds = set() + for entry in python_entries: + # The crate build will need to match the runner's architecture + runner = runners[entry["runner"]] + needed_builds.add((entry["platform"], runner["arch"])) + + # If forcing crate build, also include all possible native builds + if force_crate_build: + for platform, platform_config in config.items(): + # Filter by platform if specified + if platform_filter and platform != platform_filter: + continue + + for target_config in platform_config.values(): + # Only include if native (run: true means native) + if not target_config.get("run"): + continue + + arch = target_config["arch"] + needed_builds.add((platform, arch)) + + # Create matrix entries for each needed build + return [ + { + "platform": platform, + "arch": arch, + # Use the GitHub runner for Windows, because the Depot one is + # missing a Rust toolchain. On Linux, it's important that the the + # `python-build` runner matches the `crate-build` runner because of + # GLIBC version mismatches. + "runner": find_runner( + runners, platform, arch, True if platform == "windows" else False + ), + "crate_artifact_name": crate_artifact_name( + platform, + arch, + ), + } + for platform, arch in needed_builds + if not platform_filter or platform == platform_filter + ] + + +def generate_python_build_matrix_entries( config: dict[str, Any], runners: dict[str, Any], platform_filter: Optional[str] = None, label_filters: Optional[dict[str, set[str]]] = None, ) -> list[dict[str, str]]: + """Generate matrix entries for python builds.""" matrix_entries = [] for platform, platform_config in config.items(): @@ -102,13 +192,13 @@ def generate_matrix_entries( continue for target_triple, target_config in platform_config.items(): - add_matrix_entries_for_config( + add_python_build_entries_for_config( matrix_entries, target_triple, target_config, platform, runners, - label_filters.get("directives", set()), + label_filters.get("directives", set()) if label_filters else set(), ) # Apply label filters if present @@ -122,10 +212,12 @@ def generate_matrix_entries( return matrix_entries -def find_runner(runners: dict[str, Any], platform: str, arch: str) -> str: +def find_runner(runners: dict[str, Any], platform: str, arch: str, free: bool) -> str: # Find a matching platform first match_platform = [ - runner for runner in runners if runners[runner]["platform"] == platform + runner + for runner in runners + if runners[runner]["platform"] == platform and runners[runner]["free"] == free ] # Then, find a matching architecture @@ -141,10 +233,12 @@ def find_runner(runners: dict[str, Any], platform: str, arch: str) -> str: if match_platform: return match_platform[0] - raise RuntimeError(f"No runner found for platform {platform!r} and arch {arch!r}") + raise RuntimeError( + f"No runner found for platform {platform!r} and arch {arch!r} with free={free}" + ) -def add_matrix_entries_for_config( +def add_python_build_entries_for_config( matrix_entries: list[dict[str, str]], target_triple: str, config: dict[str, Any], @@ -152,10 +246,11 @@ def add_matrix_entries_for_config( runners: dict[str, Any], directives: set[str], ) -> None: + """Add python build matrix entries for a specific target configuration.""" python_versions = config["python_versions"] build_options = config["build_options"] arch = config["arch"] - runner = find_runner(runners, platform, arch) + runner = find_runner(runners, platform, arch, False) # Create base entry that will be used for all variants base_entry = { @@ -166,6 +261,8 @@ def add_matrix_entries_for_config( # If `run` is in the config, use that — otherwise, default to if the # runner architecture matches the build architecture "run": str(config.get("run", runners[runner]["arch"] == arch)).lower(), + # Use the crate artifact built for the runner's architecture + "crate_artifact_name": crate_artifact_name(platform, runners[runner]["arch"]), } # Add optional fields if they exist @@ -233,6 +330,17 @@ def parse_args() -> argparse.Namespace: action="store_true", help="If only free runners should be used.", ) + parser.add_argument( + "--force-crate-build", + action="store_true", + help="Force crate builds to be included even without python builds.", + ) + parser.add_argument( + "--matrix-type", + choices=["python-build", "docker-build", "crate-build", "all"], + default="all", + help="Which matrix types to generate (default: all)", + ) return parser.parse_args() @@ -254,36 +362,70 @@ def main() -> None: if runner_config.get("free") } - entries = generate_matrix_entries( + result = {} + + # Generate python build entries + python_entries = generate_python_build_matrix_entries( config, runners, args.platform, labels, ) - if args.max_shards: - matrix = {} - shards = (len(entries) // CI_MATRIX_SIZE_LIMIT) + 1 - if shards > args.max_shards: - print( - f"error: matrix of size {len(entries)} requires {shards} shards, but the maximum is {args.max_shards}; consider increasing `--max-shards`", - file=sys.stderr, - ) - sys.exit(1) - for shard in range(args.max_shards): - shard_entries = entries[ - shard * CI_MATRIX_SIZE_LIMIT : (shard + 1) * CI_MATRIX_SIZE_LIMIT - ] - matrix[str(shard)] = {"include": shard_entries} - else: - if len(entries) > CI_MATRIX_SIZE_LIMIT: - print( - f"warning: matrix of size {len(entries)} exceeds limit of {CI_MATRIX_SIZE_LIMIT} but sharding is not enabled; consider setting `--max-shards`", - file=sys.stderr, + # Output python-build matrix if requested + if args.matrix_type in ["python-build", "all"]: + if args.max_shards: + python_build_matrix = {} + shards = (len(python_entries) // CI_MATRIX_SIZE_LIMIT) + 1 + if shards > args.max_shards: + print( + f"error: python-build matrix of size {len(python_entries)} requires {shards} shards, but the maximum is {args.max_shards}; consider increasing `--max-shards`", + file=sys.stderr, + ) + sys.exit(1) + for shard in range(args.max_shards): + shard_entries = python_entries[ + shard * CI_MATRIX_SIZE_LIMIT : (shard + 1) * CI_MATRIX_SIZE_LIMIT + ] + python_build_matrix[str(shard)] = {"include": shard_entries} + result["python-build"] = python_build_matrix + else: + if len(python_entries) > CI_MATRIX_SIZE_LIMIT: + print( + f"warning: python-build matrix of size {len(python_entries)} exceeds limit of {CI_MATRIX_SIZE_LIMIT} but sharding is not enabled; consider setting `--max-shards`", + file=sys.stderr, + ) + result["python-build"] = {"include": python_entries} + + # Generate docker-build matrix if requested + # Only include docker builds if there are Linux python builds + if args.matrix_type in ["docker-build", "all"]: + # Check if we have any Linux python builds + has_linux_builds = any( + entry.get("platform") == "linux" for entry in python_entries + ) + + # If no platform filter or explicitly requesting docker-build only, include docker builds + # Otherwise, only include if there are Linux python builds + if args.matrix_type == "docker-build" or has_linux_builds: + docker_entries = generate_docker_matrix_entries( + runners, + args.platform, ) - matrix = {"include": entries} - - print(json.dumps(matrix)) + result["docker-build"] = {"include": docker_entries} + + # Generate crate-build matrix if requested + if args.matrix_type in ["crate-build", "all"]: + crate_entries = generate_crate_build_matrix_entries( + python_entries, + runners, + config, + args.force_crate_build, + args.platform, + ) + result["crate-build"] = {"include": crate_entries} + + print(json.dumps(result)) if __name__ == "__main__": diff --git a/ci-runners.yaml b/ci-runners.yaml index aeb0e5c..6eff628 100644 --- a/ci-runners.yaml +++ b/ci-runners.yaml @@ -1,37 +1,46 @@ # Describes the runners that the CI system can use -depot-ubuntu-22.04: +ubuntu-latest: arch: x86_64 platform: linux - free: false - -# TODO: Enable this runner to perform native builds for aarch64 -# depot-ubuntu-22.04-arm: -# arch: aarch64 -# platform: linux -# free: false + free: true -depot-macos-latest: +ubuntu-24.04: arch: x86_64 - platform: darwin - free: false + platform: linux + free: true -ubuntu-latest: +ubuntu-22.04: arch: x86_64 platform: linux free: true +ubuntu-latest-aarch64: + arch: aarch64 + platform: linux + free: true + macos-latest: arch: x86_64 platform: darwin free: true -windows-latest-large: +macos-14: + arch: aarch64 + platform: darwin + free: true + +macos-13: arch: x86_64 - platform: windows - free: false + platform: darwin + free: true windows-latest: arch: x86_64 platform: windows free: true + +windows-2022: + arch: x86_64 + platform: windows + free: true diff --git a/ci-targets.yaml b/ci-targets.yaml index 70078e8..417333e 100644 --- a/ci-targets.yaml +++ b/ci-targets.yaml @@ -4,7 +4,6 @@ darwin: aarch64-apple-darwin: arch: aarch64 python_versions: - - "3.9" - "3.10" - "3.11" - "3.12" @@ -22,7 +21,6 @@ darwin: x86_64-apple-darwin: arch: x86_64 python_versions: - - "3.9" - "3.10" - "3.11" - "3.12" @@ -42,112 +40,6 @@ linux: arch: aarch64 libc: gnu python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug - - noopt - - lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+noopt - - freethreaded+lto - minimum-python-version: "3.13" - - armv7-unknown-linux-gnueabi: - arch: armv7 - libc: gnu - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug - - noopt - - lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+noopt - - freethreaded+lto - minimum-python-version: "3.13" - - armv7-unknown-linux-gnueabihf: - arch: armv7 - libc: gnu - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug - - noopt - - lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+noopt - - freethreaded+lto - minimum-python-version: "3.13" - - s390x-unknown-linux-gnu: - arch: s390x - libc: gnu - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug - - noopt - - lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+noopt - - freethreaded+lto - minimum-python-version: "3.13" - - ppc64le-unknown-linux-gnu: - arch: ppc64le - libc: gnu - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug - - noopt - - lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+noopt - - freethreaded+lto - minimum-python-version: "3.13" - - riscv64-unknown-linux-gnu: - arch: riscv64 - libc: gnu - python_versions: - - "3.9" - "3.10" - "3.11" - "3.12" @@ -168,7 +60,6 @@ linux: arch: x86_64 libc: gnu python_versions: - - "3.9" - "3.10" - "3.11" - "3.12" @@ -183,204 +74,3 @@ linux: - freethreaded+pgo+lto minimum-python-version: "3.13" run: true - - x86_64_v2-unknown-linux-gnu: - arch: x86_64 - arch_variant: v2 - libc: gnu - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug - - pgo+lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+pgo+lto - minimum-python-version: "3.13" - run: true - - x86_64_v3-unknown-linux-gnu: - arch: x86_64 - arch_variant: v3 - libc: gnu - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug - - pgo+lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+pgo+lto - minimum-python-version: "3.13" - run: true - - x86_64_v4-unknown-linux-gnu: - arch: x86_64 - arch_variant: v4 - libc: gnu - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug - - pgo+lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+pgo+lto - minimum-python-version: "3.13" - run: true - - x86_64-unknown-linux-musl: - arch: x86_64 - libc: musl - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug+static - - noopt+static - - lto+static - - debug - - noopt - - lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+noopt - - freethreaded+lto - minimum-python-version: "3.13" - run: true - - x86_64_v2-unknown-linux-musl: - arch: x86_64 - arch_variant: v2 - libc: musl - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug+static - - noopt+static - - lto+static - - debug - - noopt - - lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+noopt - - freethreaded+lto - minimum-python-version: "3.13" - run: true - - x86_64_v3-unknown-linux-musl: - arch: x86_64 - arch_variant: v3 - libc: musl - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug+static - - noopt+static - - lto+static - - debug - - noopt - - lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+noopt - - freethreaded+lto - minimum-python-version: "3.13" - run: true - - x86_64_v4-unknown-linux-musl: - arch: x86_64 - arch_variant: v4 - libc: musl - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - debug+static - - noopt+static - - lto+static - - debug - - noopt - - lto - build_options_conditional: - - options: - - freethreaded+debug - - freethreaded+noopt - - freethreaded+lto - minimum-python-version: "3.13" - run: true - -windows: - i686-pc-windows-msvc: - arch: x86 - vcvars: vcvars32.bat - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - pgo - build_options_conditional: - - options: - - freethreaded+pgo - minimum-python-version: "3.13" - - x86_64-pc-windows-msvc: - arch: x86_64 - vcvars: vcvars64.bat - python_versions: - - "3.9" - - "3.10" - - "3.11" - - "3.12" - - "3.13" - - "3.14" - build_options: - - pgo - build_options_conditional: - - options: - - freethreaded+pgo - minimum-python-version: "3.13" diff --git a/cpython-unix/Makefile b/cpython-unix/Makefile index 4cacaff..7e56414 100644 --- a/cpython-unix/Makefile +++ b/cpython-unix/Makefile @@ -66,7 +66,7 @@ TOOLCHAIN_DEPENDS := \ PYTHON_DEP_DEPENDS := \ $(OUTDIR)/targets/$(TARGET_TRIPLE) \ - $(if $(PYBUILD_NO_DOCKER),,$(OUTDIR)/image-$(DOCKER_IMAGE_BUILD).tar) \ + $(if $(PYBUILD_NO_DOCKER),,$(OUTDIR)/image-$(DOCKER_IMAGE_BUILD).$(HOST_PLATFORM).tar) \ $(TOOLCHAIN_DEPENDS) \ $(NULL) @@ -75,18 +75,18 @@ HOST_PYTHON_DEPENDS := $(OUTDIR)/cpython-$(PYTHON_MAJOR_VERSION)-$(CPYTHON_$(PYT default: $(OUTDIR)/cpython-$(CPYTHON_$(PYTHON_MAJOR_VERSION)_VERSION)-$(PACKAGE_SUFFIX).tar ifndef PYBUILD_NO_DOCKER -$(OUTDIR)/image-%.tar: $(OUTDIR)/%.Dockerfile +$(OUTDIR)/image-%.$(HOST_PLATFORM).tar: $(OUTDIR)/%.Dockerfile $(RUN_BUILD) --toolchain image-$* endif -$(OUTDIR)/binutils-$(BINUTILS_VERSION)-$(HOST_PLATFORM).tar: $(OUTDIR)/image-gcc.tar $(HERE)/build-binutils.sh - $(RUN_BUILD) --toolchain binutils +$(OUTDIR)/binutils-$(BINUTILS_VERSION)-$(HOST_PLATFORM).tar: $(OUTDIR)/image-$(DOCKER_IMAGE_GCC).$(HOST_PLATFORM).tar $(HERE)/build-binutils.sh + $(RUN_BUILD) --toolchain --docker-image $(DOCKER_IMAGE_GCC) binutils $(OUTDIR)/$(CLANG_FILENAME): $(RUN_BUILD) --toolchain clang --target-triple $(TARGET_TRIPLE) $(OUTDIR)/musl-$(MUSL_VERSION)-$(HOST_PLATFORM).tar: $(BASE_TOOLCHAIN_DEPENDS) $(HERE)/build-musl.sh - $(RUN_BUILD) --toolchain musl + $(RUN_BUILD) --toolchain musl --docker-image $(DOCKER_IMAGE_GCC) ifeq ($(HOST_PLATFORM),linux_x86_64) TOOLCHAIN_TARGET := $(OUTDIR)/musl-$(MUSL_VERSION)-$(HOST_PLATFORM).tar @@ -125,7 +125,7 @@ $(OUTDIR)/libffi-3.3-$(LIBFFI_3.3_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_D $(OUTDIR)/libffi-$(LIBFFI_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-libffi.sh $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) libffi -$(OUTDIR)/libpthread-stubs-$(LIBPTHREAD_STUBS_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-libpthread-stubs.sh $(OUTDIR)/image-$(DOCKER_IMAGE_BUILD).tar +$(OUTDIR)/libpthread-stubs-$(LIBPTHREAD_STUBS_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-libpthread-stubs.sh $(OUTDIR)/image-$(DOCKER_IMAGE_BUILD).$(HOST_PLATFORM).tar $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) libpthread-stubs LIBX11_DEPENDS = \ @@ -192,18 +192,14 @@ $(OUTDIR)/patchelf-$(PATCHELF_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPEN $(OUTDIR)/sqlite-$(SQLITE_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-sqlite.sh $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) sqlite -$(OUTDIR)/tcl-$(TCL_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-tcl.sh - $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) tcl - -TIX_DEPENDS = \ - $(HERE)/build-tix.sh \ - $(OUTDIR)/tcl-$(TCL_VERSION)-$(PACKAGE_SUFFIX).tar \ - $(OUTDIR)/tk-$(TK_VERSION)-$(PACKAGE_SUFFIX).tar \ - $(if $(NEED_LIBX11),$(OUTDIR)/libX11-$(LIBX11_VERSION)-$(PACKAGE_SUFFIX).tar) \ +TCL_DEPENDS = \ + $(PYTHON_DEP_DEPENDS) \ + $(HERE)/build-tcl.sh \ + $(OUTDIR)/zlib-$(ZLIB_VERSION)-$(PACKAGE_SUFFIX).tar \ $(NULL) -$(OUTDIR)/tix-$(TIX_VERSION)-$(PACKAGE_SUFFIX).tar: $(TIX_DEPENDS) - $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) tix +$(OUTDIR)/tcl-$(TCL_VERSION)-$(PACKAGE_SUFFIX).tar: $(TCL_DEPENDS) + $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) tcl TK_DEPENDS = \ $(HOST_PYTHON_DEPENDS) \ @@ -236,6 +232,9 @@ $(OUTDIR)/xz-$(XZ_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/ $(OUTDIR)/zlib-$(ZLIB_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-zlib.sh $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) zlib +$(OUTDIR)/zstd-$(ZSTD_VERSION)-$(PACKAGE_SUFFIX).tar: $(PYTHON_DEP_DEPENDS) $(HERE)/build-zstd.sh + $(RUN_BUILD) --docker-image $(DOCKER_IMAGE_BUILD) zstd + PYTHON_HOST_DEPENDS := \ $(PYTHON_DEP_DEPENDS) \ $(HERE)/build-cpython-host.sh \ @@ -268,10 +267,10 @@ PYTHON_DEPENDS_$(1) := \ $$(if $$(NEED_SQLITE),$$(OUTDIR)/sqlite-$$(SQLITE_VERSION)-$$(PACKAGE_SUFFIX).tar) \ $$(if $$(NEED_TCL),$$(OUTDIR)/tcl-$$(TCL_VERSION)-$$(PACKAGE_SUFFIX).tar) \ $$(if $$(NEED_TK),$$(OUTDIR)/tk-$$(TK_VERSION)-$$(PACKAGE_SUFFIX).tar) \ - $$(if $$(NEED_TIX),$$(OUTDIR)/tix-$$(TIX_VERSION)-$$(PACKAGE_SUFFIX).tar) \ $$(if $$(NEED_UUID),$$(OUTDIR)/uuid-$$(UUID_VERSION)-$$(PACKAGE_SUFFIX).tar) \ $$(if $$(NEED_XZ),$$(OUTDIR)/xz-$$(XZ_VERSION)-$$(PACKAGE_SUFFIX).tar) \ $$(if $$(NEED_ZLIB),$$(OUTDIR)/zlib-$$(ZLIB_VERSION)-$$(PACKAGE_SUFFIX).tar) \ + $$(if $$(NEED_ZSTD),$$(OUTDIR)/zstd-$$(ZSTD_VERSION)-$$(PACKAGE_SUFFIX).tar) \ $$(NULL) ALL_PYTHON_DEPENDS_$(1) = \ diff --git a/cpython-unix/base.debian9.Dockerfile b/cpython-unix/base.debian9.Dockerfile new file mode 100644 index 0000000..1b47b35 --- /dev/null +++ b/cpython-unix/base.debian9.Dockerfile @@ -0,0 +1,38 @@ +# Debian Stretch. +FROM debian@sha256:c5c5200ff1e9c73ffbf188b4a67eb1c91531b644856b4aefe86a58d2f0cb05be +MAINTAINER Gregory Szorc + +RUN groupadd -g 1000 build && \ + useradd -u 1000 -g 1000 -d /build -s /bin/bash -m build && \ + mkdir /tools && \ + chown -R build:build /build /tools + +ENV HOME=/build \ + SHELL=/bin/bash \ + USER=build \ + LOGNAME=build \ + HOSTNAME=builder \ + DEBIAN_FRONTEND=noninteractive + +CMD ["/bin/bash", "--login"] +WORKDIR '/build' + +RUN for s in debian_stretch debian_stretch-updates debian-security_stretch/updates; do \ + echo "deb http://snapshot.debian.org/archive/${s%_*}/20230423T032736Z/ ${s#*_} main"; \ + done > /etc/apt/sources.list && \ + ( echo 'quiet "true";'; \ + echo 'APT::Get::Assume-Yes "true";'; \ + echo 'APT::Install-Recommends "false";'; \ + echo 'Acquire::Check-Valid-Until "false";'; \ + echo 'Acquire::Retries "5";'; \ + ) > /etc/apt/apt.conf.d/99cpython-portable + +# apt iterates all available file descriptors up to rlim_max and calls +# fcntl(fd, F_SETFD, FD_CLOEXEC). This can result in millions of system calls +# (we've seen 1B in the wild) and cause operations to take seconds to minutes. +# Setting a fd limit mitigates. +# +# Attempts at enforcing the limit globally via /etc/security/limits.conf and +# /root/.bashrc were not successful. Possibly because container image builds +# don't perform a login or use a shell the way we expect. +RUN ulimit -n 10000 && apt-get update diff --git a/cpython-unix/build-binutils.sh b/cpython-unix/build-binutils.sh index c52e823..2bb8936 100755 --- a/cpython-unix/build-binutils.sh +++ b/cpython-unix/build-binutils.sh @@ -11,9 +11,15 @@ tar -xf binutils-${BINUTILS_VERSION}.tar.xz mkdir binutils-objdir pushd binutils-objdir +if [ "$(uname -m)" = "x86_64" ]; then + triple="x86_64-unknown-linux-gnu" +else + triple="aarch64-unknown-linux-gnu" +fi + # gprofng requires a bison newer than what we have. So just disable it. ../binutils-${BINUTILS_VERSION}/configure \ - --build=x86_64-unknown-linux-gnu \ + --build=${triple} \ --prefix=/tools/host \ --enable-plugins \ --enable-gprofng=no \ diff --git a/cpython-unix/build-cpython-host.sh b/cpython-unix/build-cpython-host.sh index 99b021d..ff7c3a4 100755 --- a/cpython-unix/build-cpython-host.sh +++ b/cpython-unix/build-cpython-host.sh @@ -70,6 +70,11 @@ case "${BUILD_TRIPLE}" in EXTRA_HOST_CPPFLAGS="${EXTRA_HOST_CPPFLAGS} -I/usr/include/x86_64-linux-gnu" EXTRA_HOST_LDFLAGS="${EXTRA_HOST_LDFLAGS} -L/usr/lib/x86_64-linux-gnu" ;; + aarch64-unknown-linux-gnu) + EXTRA_HOST_CFLAGS="${EXTRA_HOST_CFLAGS} -I/usr/include/aarch64-linux-gnu" + EXTRA_HOST_CPPFLAGS="${EXTRA_HOST_CPPFLAGS} -I/usr/include/aarch64-linux-gnu" + EXTRA_HOST_LDFLAGS="${EXTRA_HOST_LDFLAGS} -L/usr/lib/aarch64-linux-gnu" + ;; *) ;; esac diff --git a/cpython-unix/build-cpython.sh b/cpython-unix/build-cpython.sh index 820b6a2..cb0cbce 100755 --- a/cpython-unix/build-cpython.sh +++ b/cpython-unix/build-cpython.sh @@ -44,7 +44,7 @@ sed "${sed_args[@]}" "s|/tools/host|${TOOLS_PATH}/host|g" ${TOOLS_PATH}/host/sha # We force linking of external static libraries by removing the shared # libraries. This is hacky. But we're building in a temporary container # and it gets the job done. -find ${TOOLS_PATH}/deps -name '*.so*' -exec rm {} \; +find ${TOOLS_PATH}/deps -name '*.so*' ! -name 'libtcl*.so*' ! -name 'libtk*.so*' ! -name 'fips.so' -exec rm {} \; tar -xf Python-${PYTHON_VERSION}.tar.xz @@ -76,13 +76,6 @@ if [ -n "${CROSS_COMPILING}" ]; then fi fi -# `uuid.getnode()` is not stable on our libuuid, CPython should fallback to another method -# Cherry-pick https://github.com/python/cpython/pull/134704 until it is released -# We could backport this to more versions too, it won't be done by the upstream -if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]]; then - patch -p1 -i ${ROOT}/patch-uuid-getnode-stable-3.13.patch -fi - # This patch is slightly different on Python 3.10+. if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_10}" ]; then patch -p1 -i ${ROOT}/patch-xopen-source-ios.patch @@ -90,12 +83,6 @@ else patch -p1 -i ${ROOT}/patch-xopen-source-ios-legacy.patch fi -# See https://github.com/python/cpython/pull/135146 -# TODO(zanieb): Drop in 3.14b3 -if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then - patch -p1 -i ${ROOT}/patch-static-remote-debug-3.14.patch -fi - # LIBTOOL_CRUFT is unused and breaks cross-compiling on macOS. Nuke it. # Submitted upstream at https://github.com/python/cpython/pull/101048. if [ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_11}" ]; then @@ -122,17 +109,12 @@ fi # Clang 13 actually prints something with --print-multiarch, confusing CPython's # configure. This is reported as https://bugs.python.org/issue45405. We nerf the # check since we know what we're doing. -if [ "${CC}" = "clang" ]; then +if [[ "${CC}" = "clang" || "${CC}" = "musl-clang" ]]; then if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch else patch -p1 -i ${ROOT}/patch-disable-multiarch.patch fi -elif [ "${CC}" = "musl-clang" ]; then - # Similarly, this is a problem for musl Clang on Python 3.13+ - if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then - patch -p1 -i ${ROOT}/patch-disable-multiarch-13.patch - fi fi # Python 3.11 supports using a provided Python to use during bootstrapping @@ -383,6 +365,16 @@ if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_12}" && "${TARGET_TRIPLE}" = "ppc64le LDFLAGS="${LDFLAGS} -Wl,--no-tls-get-addr-optimize" fi +# We're calling install_name_tool -add_rpath on extension modules, which +# eats up 0x20 bytes of space in the Mach-O header, and we need to make +# sure there's still enough room to add a code signature (0x10 bytes) on +# non-arm64 where there's no automatic ad-hoc signature. We are somehow +# on a toolchain that doesn't make sure there's enough space by default +# so give it plenty of space. +if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then + LDFLAGS="${LDFLAGS} -Wl,-headerpad,40" +fi + CPPFLAGS=$CFLAGS CONFIGURE_FLAGS=" @@ -478,17 +470,16 @@ if [ -n "${CPYTHON_OPTIMIZED}" ]; then if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then # Do not enable on x86-64 macOS because the JIT requires macOS 11+ and we are currently - # using 10.15 as a miniumum version. + # using 10.15 as a minimum version. # Do not enable when free-threading, because they're not compatible yet. if [[ ! ( "${TARGET_TRIPLE}" == "x86_64-apple-darwin" || -n "${CPYTHON_FREETHREADED}" ) ]]; then CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --enable-experimental-jit=yes-off" fi # Respect CFLAGS during JIT compilation. + # # Backports https://github.com/python/cpython/pull/134276 - if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then - patch -p1 -i ${ROOT}/patch-jit-cflags-314.patch - elif [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]; then + if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" && -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_13}" ]]; then patch -p1 -i ${ROOT}/patch-jit-cflags-313.patch fi @@ -653,7 +644,19 @@ fi # We patched configure.ac above. Reflect those changes. autoconf -CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS LDFLAGS=$LDFLAGS \ +# Ensure `CFLAGS` are propagated to JIT compilation for 3.13+ (note this variable has no effect on +# 3.12 and earlier) +CFLAGS_JIT="${CFLAGS}" + +# In 3.14+, the JIT compiler on x86-64 Linux uses a model that conflicts with `-fPIC`, so strip it +# from the flags. See: +# - https://github.com/python/cpython/issues/135690 +# - https://github.com/python/cpython/pull/130097 +if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" && "${TARGET_TRIPLE}" == x86_64* ]]; then + CFLAGS_JIT="${CFLAGS_JIT//-fPIC/}" +fi + +CFLAGS=$CFLAGS CPPFLAGS=$CFLAGS CFLAGS_JIT=$CFLAGS_JIT LDFLAGS=$LDFLAGS \ ./configure ${CONFIGURE_FLAGS} # Supplement produced Makefile with our modifications. @@ -700,6 +703,8 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION} # Python's build system doesn't make this file writable. + # TODO(geofft): @executable_path/ is a weird choice here, who is + # relying on it? Should probably be @loader_path. chmod 755 ${ROOT}/out/python/install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME} install_name_tool \ -change /install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME} @executable_path/${LIBPYTHON_SHARED_LIBRARY_BASENAME} \ @@ -718,6 +723,13 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then -change /install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME} @executable_path/../lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME} \ ${ROOT}/out/python/install/bin/python${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX} fi + + # At the moment, python3 and libpython don't have shared-library + # dependencies, but at some point we will want to run this for + # them too. + for module in ${ROOT}/out/python/install/lib/python*/lib-dynload/*.so; do + install_name_tool -add_rpath @loader_path/../.. "$module" + done else # (not macos) LIBPYTHON_SHARED_LIBRARY_BASENAME=libpython${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}.so.1.0 LIBPYTHON_SHARED_LIBRARY=${ROOT}/out/python/install/lib/${LIBPYTHON_SHARED_LIBRARY_BASENAME} @@ -1075,8 +1087,14 @@ touch "${LIB_DYNLOAD}/.empty" # Symlink libpython so we don't have 2 copies. case "${TARGET_TRIPLE}" in -aarch64-unknown-linux-gnu) - PYTHON_ARCH="aarch64-linux-gnu" +aarch64-unknown-linux-*) + # In Python 3.13+, the musl target is identified in cross compiles and the output directory + # is named accordingly. + if [[ "${CC}" = "musl-clang" && -n "${PYTHON_MEETS_MINIMUM_VERSION_3_13}" ]]; then + PYTHON_ARCH="aarch64-linux-musl" + else + PYTHON_ARCH="aarch64-linux-gnu" + fi ;; # This is too aggressive. But we don't have patches in place for # setting the platform name properly on non-Darwin. @@ -1205,7 +1223,7 @@ ${BUILD_PYTHON} ${ROOT}/fix_shebangs.py ${ROOT}/out/python/install # downstream consumers. OBJECT_DIRS="Objects Parser Parser/lexer Parser/pegen Parser/tokenizer Programs Python Python/deepfreeze" OBJECT_DIRS="${OBJECT_DIRS} Modules" -for ext in _blake2 cjkcodecs _ctypes _ctypes/darwin _decimal _expat _hacl _io _multiprocessing _sha3 _sqlite _sre _testinternalcapi _xxtestfuzz ; do +for ext in _blake2 cjkcodecs _ctypes _ctypes/darwin _decimal _expat _hacl _io _multiprocessing _sha3 _sqlite _sre _testinternalcapi _xxtestfuzz _zstd; do OBJECT_DIRS="${OBJECT_DIRS} Modules/${ext}" done @@ -1239,16 +1257,20 @@ fi rm -f ${ROOT}/out/python/build/lib/{libdb-6.0,libxcb-*,libX11-xcb}.a if [ -d "${TOOLS_PATH}/deps/lib/tcl8" ]; then - # Copy tcl/tk/tix resources needed by tkinter. + # Copy tcl/tk resources needed by tkinter. mkdir ${ROOT}/out/python/install/lib/tcl # Keep this list in sync with tcl_library_paths. for source in ${TOOLS_PATH}/deps/lib/{itcl4.2.4,tcl8,tcl8.6,thread2.8.9,tk8.6}; do cp -av $source ${ROOT}/out/python/install/lib/ done - if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then - cp -av ${TOOLS_PATH}/deps/lib/Tix8.4.3 ${ROOT}/out/python/install/lib/ - fi + ( + shopt -s nullglob + dylibs=(${TOOLS_PATH}/deps/lib/lib*.dylib ${TOOLS_PATH}/deps/lib/lib*.so) + if [ "${#dylibs[@]}" -gt 0 ]; then + cp -av "${dylibs[@]}" ${ROOT}/out/python/install/lib/ + fi + ) fi # Copy the terminfo database if present. @@ -1256,6 +1278,13 @@ if [ -d "${TOOLS_PATH}/deps/usr/share/terminfo" ]; then cp -av ${TOOLS_PATH}/deps/usr/share/terminfo ${ROOT}/out/python/install/share/ fi +# Copy files required to enable FIPS if enabled. +if [ -f ${TOOLS_PATH}/deps/fipsmodule.cnf ]; then + mkdir -p ${ROOT}/out/python/install/share/ssl + cp -rv ${TOOLS_PATH}/deps/lib/ossl-modules ${ROOT}/out/python/install/share/ssl + cp -av ${TOOLS_PATH}/deps/fipsmodule.cnf ${ROOT}/out/python/install/share/ssl +fi + # config.c defines _PyImport_Inittab and extern references to modules, which # downstream consumers may want to strip. We bundle config.c and config.c.in so # a custom one can be produced downstream. diff --git a/cpython-unix/build-libX11.sh b/cpython-unix/build-libX11.sh index bb45028..9be17ee 100755 --- a/cpython-unix/build-libX11.sh +++ b/cpython-unix/build-libX11.sh @@ -99,6 +99,11 @@ if [ -n "${CROSS_COMPILING}" ]; then esac fi +# Avoid dlopen("libXcursor.so.1") from the OS, which can go horribly wrong. We +# might not need to avoid this if we switch to shipping X11 as shared +# libraries, and ideally if we ship libXcursor ourselves. +EXTRA_FLAGS="${EXTRA_FLAGS} --disable-loadable-xcursor" + # CC_FOR_BUILD is here because configure doesn't look for `clang` when # cross-compiling. So we force it. CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC -I/tools/deps/include" \ diff --git a/cpython-unix/build-libedit.sh b/cpython-unix/build-libedit.sh index 08387ec..6122059 100755 --- a/cpython-unix/build-libedit.sh +++ b/cpython-unix/build-libedit.sh @@ -82,6 +82,32 @@ index 614795f..4671f1b 100755 fi EOF +# When libedit receives a signal, it re-broadcasts it to its entire pgroup. +# This seems intended to preserve normal ^C behavior in "raw" mode when the +# terminal's ISIG flag is cleared? However, libedit does not in fact clear +# ISIG. (And Jack can't find any evidence of any version that ever did.) This +# sometimes results in the parent process receiving ^C twice back-to-back, +# depending on the vagaries of signal coalescing. More pathologically, if the +# parent tries to signal the child directly with e.g. `kill(pid, SIGTERM)`, +# libedit *signals the parent right back* (not to mention any other pgroup +# siblings or grandparents). This is just wild behavior, even though it's +# probably rare that it matters in practice. Patch it out. See also: +# https://github.com/astral-sh/uv/issues/13919#issuecomment-2960501229. +patch -p1 << "EOF" +diff --git i/src/sig.c w/src/sig.c +index d2b77e7..884b2dd 100644 +--- i/src/sig.c ++++ w/src/sig.c +@@ -107,7 +107,7 @@ sig_handler(int signo) + sel->el_signal->sig_action[i].sa_flags = 0; + sigemptyset(&sel->el_signal->sig_action[i].sa_mask); + (void) sigprocmask(SIG_SETMASK, &oset, NULL); +- (void) kill(0, signo); ++ (void) raise(signo); + errno = save_errno; + } +EOF + cflags="${EXTRA_TARGET_CFLAGS} -fPIC -I${TOOLS_PATH}/deps/include -I${TOOLS_PATH}/deps/include/ncursesw" ldflags="${EXTRA_TARGET_LDFLAGS} -L${TOOLS_PATH}/deps/lib" diff --git a/cpython-unix/build-libffi.sh b/cpython-unix/build-libffi.sh index 9b18802..562d4d5 100755 --- a/cpython-unix/build-libffi.sh +++ b/cpython-unix/build-libffi.sh @@ -225,7 +225,7 @@ index 60cfa50..6a9a561 100644 BTI_C - /* Sign the lr with x1 since that is where it will be stored */ + PAC_CFI_WINDOW_SAVE -+ /* Sign the lr with x1 since that is the CFA which is the modifer used in auth instructions */ ++ /* Sign the lr with x1 since that is the CFA which is the modifier used in auth instructions */ SIGN_LR_WITH_REG(x1) - /* Use a stack frame allocated by our caller. */ @@ -352,7 +352,7 @@ index 6a9a561..e83bc65 100644 + cfi_startproc BTI_C PAC_CFI_WINDOW_SAVE - /* Sign the lr with x1 since that is the CFA which is the modifer used in auth instructions */ + /* Sign the lr with x1 since that is the CFA which is the modifier used in auth instructions */ @@ -348,8 +348,8 @@ CNAME(ffi_closure_SYSV_V): #endif diff --git a/cpython-unix/build-main.py b/cpython-unix/build-main.py index a353daf..23d473e 100755 --- a/cpython-unix/build-main.py +++ b/cpython-unix/build-main.py @@ -95,6 +95,7 @@ def main(): "toolchain-image-build", "toolchain-image-build.cross", "toolchain-image-build.cross-riscv64", + "toolchain-image-build.debian9", "toolchain-image-gcc", "toolchain-image-xcb", "toolchain-image-xcb.cross", @@ -181,7 +182,7 @@ def main(): # because we can get some speedup from parallel operations. But we also don't # share a make job server with each build. So if we didn't limit the # parallelism we could easily oversaturate the CPU. Higher levels of - # parallelism don't result in meaningful build speedups because tk/tix has + # parallelism don't result in meaningful build speedups because tk has # a long, serial dependency chain that can't be built in parallel. parallelism = min(1 if args.serial else 4, multiprocessing.cpu_count()) diff --git a/cpython-unix/build-openssl-3.0.sh b/cpython-unix/build-openssl-3.0.sh index 1d1f913..74526de 100755 --- a/cpython-unix/build-openssl-3.0.sh +++ b/cpython-unix/build-openssl-3.0.sh @@ -16,18 +16,23 @@ pushd openssl-${OPENSSL_3_0_VERSION} # Otherwise it gets set to /tools/deps/ssl by default. case "${TARGET_TRIPLE}" in *apple*) - EXTRA_FLAGS="--openssldir=/private/etc/ssl" + OPENSSL_DIR=/private/etc/ssl ;; *) - EXTRA_FLAGS="--openssldir=/etc/ssl" + OPENSSL_DIR=/etc/ssl ;; esac +EXTRA_FLAGS="--openssldir=${OPENSSL_DIR}" +EXTRA_INSTALL_FLAGS="" # musl is missing support for various primitives. # TODO disable secure memory is a bit scary. We should look into a proper # workaround. if [ "${CC}" = "musl-clang" ]; then EXTRA_FLAGS="${EXTRA_FLAGS} no-async -DOPENSSL_NO_ASYNC -D__STDC_NO_ATOMICS__=1 no-engine -DOPENSSL_NO_SECURE_MEMORY" +else + EXTRA_INSTALL_FLAGS="install_fips" + EXTRA_FLAGS="${EXTRA_FLAGS} enable-fips" fi # The -arch cflags confuse Configure. And OpenSSL adds them anyway. @@ -35,6 +40,10 @@ fi EXTRA_TARGET_CFLAGS=${EXTRA_TARGET_CFLAGS/\-arch arm64/} EXTRA_TARGET_CFLAGS=${EXTRA_TARGET_CFLAGS/\-arch x86_64/} +# With -fvisibility=hidden, OSSL_provider_init symbol is not exported in fips module preventing it from loaded +# OSSL_provider_init is supposed to be `extern` so it should not happen but I can't find a more targeted solution +# at the moment. +EXTRA_TARGET_CFLAGS=${EXTRA_TARGET_CFLAGS//-fvisibility=hidden/} EXTRA_FLAGS="${EXTRA_FLAGS} ${EXTRA_TARGET_CFLAGS}" /usr/bin/perl ./Configure \ @@ -47,4 +56,9 @@ EXTRA_FLAGS="${EXTRA_FLAGS} ${EXTRA_TARGET_CFLAGS}" ${EXTRA_FLAGS} make -j ${NUM_CPUS} -make -j ${NUM_CPUS} install_sw install_ssldirs DESTDIR=${ROOT}/out +make -j ${NUM_CPUS} install_sw install_ssldirs ${EXTRA_INSTALL_FLAGS} DESTDIR=${ROOT}/out + +if [ -f ${ROOT}/out${OPENSSL_DIR}/fipsmodule.cnf ]; then + # install_fips does not use DESTDIR. we need to copy it so it gets added to the archive. + cp ${ROOT}/out${OPENSSL_DIR}/fipsmodule.cnf ${ROOT}/out/tools/deps/fipsmodule.cnf +fi diff --git a/cpython-unix/build-sqlite.sh b/cpython-unix/build-sqlite.sh index b045bb8..ef7c6a6 100755 --- a/cpython-unix/build-sqlite.sh +++ b/cpython-unix/build-sqlite.sh @@ -14,7 +14,7 @@ pushd sqlite-autoconf-${SQLITE_VERSION} CONFIGURE_FLAGS="--build=${BUILD_TRIPLE} --host=${TARGET_TRIPLE}" -CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --prefix /tools/deps --disable-shared" +CONFIGURE_FLAGS="${CONFIGURE_FLAGS} --prefix=/tools/deps --disable-shared" if [ "${TARGET_TRIPLE}" = "aarch64-apple-ios" ]; then CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_search_system=no" @@ -22,7 +22,26 @@ elif [ "${TARGET_TRIPLE}" = "x86_64-apple-ios" ]; then CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_search_system=no" fi -CFLAGS="${EXTRA_TARGET_CFLAGS} -DSQLITE_ENABLE_DBSTAT_VTAB -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS3_TOKENIZER -fPIC" CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure ${CONFIGURE_FLAGS} - -make -j ${NUM_CPUS} -make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out +# The SQLite autosetup looks for the C++ compiler if the variable is set and will fail if it's not +# found, even if it's not needed. We don't actually have a C++ compiler in some builds, so ensure +# it's not looked for. +unset CXX + +CC_FOR_BUILD="${HOST_CC}" \ +CFLAGS="${EXTRA_TARGET_CFLAGS} \ + -DSQLITE_ENABLE_DBSTAT_VTAB \ + -DSQLITE_ENABLE_FTS3 \ + -DSQLITE_ENABLE_FTS3_PARENTHESIS \ + -DSQLITE_ENABLE_FTS3_TOKENIZER \ + -DSQLITE_ENABLE_FTS4 \ + -DSQLITE_ENABLE_FTS5 \ + -DSQLITE_ENABLE_GEOPOLY \ + -DSQLITE_ENABLE_RTREE \ + -fPIC" \ +CPPFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC" \ +LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure ${CONFIGURE_FLAGS} + +make -j ${NUM_CPUS} libsqlite3.a +make install-lib DESTDIR=${ROOT}/out +make install-headers DESTDIR=${ROOT}/out +make install-pc DESTDIR=${ROOT}/out diff --git a/cpython-unix/build-tcl.sh b/cpython-unix/build-tcl.sh index 43a4a6a..bfbc22f 100755 --- a/cpython-unix/build-tcl.sh +++ b/cpython-unix/build-tcl.sh @@ -7,6 +7,12 @@ set -ex ROOT=`pwd` +# Force linking to static libraries from our dependencies. +# TODO(geofft): This is copied from build-cpython.sh. Really this should +# be done at the end of the build of each dependency, rather than before +# the build of each consumer. +find ${TOOLS_PATH}/deps -name '*.so*' -exec rm {} \; + export PATH=${TOOLS_PATH}/${TOOLCHAIN}/bin:${TOOLS_PATH}/host/bin:$PATH export PKG_CONFIG_PATH=${TOOLS_PATH}/deps/share/pkgconfig:${TOOLS_PATH}/deps/lib/pkgconfig @@ -20,9 +26,8 @@ if [ -n "${STATIC}" ]; then # `checking whether musl-clang accepts -g...` fails with a duplicate definition error TARGET_TRIPLE="$(echo "${TARGET_TRIPLE}" | sed -e 's/-unknown-linux-musl/-unknown-linux-gnu/g')" fi -fi -patch -p1 << 'EOF' + patch -p1 << 'EOF' diff --git a/unix/Makefile.in b/unix/Makefile.in --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -36,6 +41,7 @@ diff --git a/unix/Makefile.in b/unix/Makefile.in fi; \ fi; \ EOF +fi # Remove packages we don't care about and can pull in unwanted symbols. rm -rf pkgs/sqlite* pkgs/tdbc* @@ -43,17 +49,23 @@ rm -rf pkgs/sqlite* pkgs/tdbc* pushd unix CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC -I${TOOLS_PATH}/deps/include" +LDFLAGS="${EXTRA_TARGET_CFLAGS} -L${TOOLS_PATH}/deps/lib" +if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then + LDFLAGS="${LDFLAGS} -Wl,--exclude-libs,ALL" +fi -CFLAGS="${CFLAGS}" CPPFLAGS="${CFLAGS}" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" ./configure \ +CFLAGS="${CFLAGS}" CPPFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" ./configure \ --build=${BUILD_TRIPLE} \ --host=${TARGET_TRIPLE} \ --prefix=/tools/deps \ - --enable-shared=no \ + --enable-shared"${STATIC:+=no}" \ --enable-threads -make -j ${NUM_CPUS} -make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out +make -j ${NUM_CPUS} DYLIB_INSTALL_DIR=@rpath +make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out DYLIB_INSTALL_DIR=@rpath make -j ${NUM_CPUS} install-private-headers DESTDIR=${ROOT}/out -# For some reason libtcl*.a have weird permissions. Fix that. -chmod 644 ${ROOT}/out/tools/deps/lib/libtcl*.a +if [ -n "${STATIC}" ]; then + # For some reason libtcl*.a have weird permissions. Fix that. + chmod 644 ${ROOT}/out/tools/deps/lib/libtcl*.a +fi diff --git a/cpython-unix/build-tk.sh b/cpython-unix/build-tk.sh index 2769a63..bd936c8 100755 --- a/cpython-unix/build-tk.sh +++ b/cpython-unix/build-tk.sh @@ -7,6 +7,12 @@ set -ex ROOT=`pwd` +# Force linking to static libraries from our dependencies. +# TODO(geofft): This is copied from build-cpython.sh. Really this should +# be done at the end of the build of each dependency, rather than before +# the build of each consumer. +find ${TOOLS_PATH}/deps -name '*.so*' -exec rm {} \; + export PATH=${TOOLS_PATH}/deps/bin:${TOOLS_PATH}/${TOOLCHAIN}/bin:${TOOLS_PATH}/host/bin:$PATH export PKG_CONFIG_PATH=${TOOLS_PATH}/deps/share/pkgconfig:${TOOLS_PATH}/deps/lib/pkgconfig @@ -23,6 +29,7 @@ if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then LDFLAGS="-L${TOOLS_PATH}/deps/lib" EXTRA_CONFIGURE_FLAGS="--enable-aqua=yes --without-x" else + LDFLAGS="${LDFLAGS} -Wl,--exclude-libs,ALL" EXTRA_CONFIGURE_FLAGS="--x-includes=${TOOLS_PATH}/deps/include --x-libraries=${TOOLS_PATH}/deps/lib" fi @@ -31,29 +38,38 @@ CFLAGS="${CFLAGS}" CPPFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}" ./configure \ --host=${TARGET_TRIPLE} \ --prefix=/tools/deps \ --with-tcl=${TOOLS_PATH}/deps/lib \ - --enable-shared=no \ + --enable-shared"${STATIC:+=no}" \ --enable-threads \ ${EXTRA_CONFIGURE_FLAGS} # Remove wish, since we don't need it. -if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then - sed -i 's/all: binaries libraries doc/all: libraries/' Makefile - sed -i 's/install-binaries: $(TK_STUB_LIB_FILE) $(TK_LIB_FILE) ${WISH_EXE}/install-binaries: $(TK_STUB_LIB_FILE) $(TK_LIB_FILE)/' Makefile +if [[ "${PYBUILD_PLATFORM}" = macos* ]]; then + sed_args=(-i '' -e) +else + sed_args=(-i) fi +sed "${sed_args[@]}" 's/all: binaries libraries doc/all: libraries/' Makefile +sed "${sed_args[@]}" 's/install-binaries: $(TK_STUB_LIB_FILE) $(TK_LIB_FILE) ${WISH_EXE}/install-binaries: $(TK_STUB_LIB_FILE) $(TK_LIB_FILE)/' Makefile -# For some reason musl isn't link libXau and libxcb. So we hack the Makefile -# to do what we want. -if [ "${CC}" = "musl-clang" ]; then - sed -i 's/-ldl -lpthread /-ldl -lpthread -lXau -lxcb/' tkConfig.sh - sed -i 's/-lpthread $(X11_LIB_SWITCHES) -ldl -lpthread/-lpthread $(X11_LIB_SWITCHES) -ldl -lpthread -lXau -lxcb/' Makefile +# We are statically linking libX11, and static libraries do not carry +# information about dependencies. pkg-config --static does, but Tcl/Tk's +# build system apparently is too old for that. So we need to manually +# inform the build process that libX11.a needs libxcb.a and libXau.a. +# Note that the order is significant, for static libraries: X11 requires +# xcb, which requires Xau. +MAKE_VARS=(DYLIB_INSTALL_DIR=@rpath) +if [[ "${PYBUILD_PLATFORM}" != macos* ]]; then + MAKE_VARS+=(X11_LIB_SWITCHES="-lX11 -lxcb -lXau") fi -make -j ${NUM_CPUS} +make -j ${NUM_CPUS} "${MAKE_VARS[@]}" touch wish -make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out +make -j ${NUM_CPUS} install DESTDIR=${ROOT}/out "${MAKE_VARS[@]}" make -j ${NUM_CPUS} install-private-headers DESTDIR=${ROOT}/out # For some reason libtk*.a have weird permissions. Fix that. -chmod 644 /${ROOT}/out/tools/deps/lib/libtk*.a +if [ -n "${STATIC}" ]; then + chmod 644 /${ROOT}/out/tools/deps/lib/libtk*.a +fi rm ${ROOT}/out/tools/deps/bin/wish* diff --git a/cpython-unix/build-zstd.sh b/cpython-unix/build-zstd.sh new file mode 100755 index 0000000..bcce804 --- /dev/null +++ b/cpython-unix/build-zstd.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. + +set -ex + +ROOT=`pwd` + +export PATH=${TOOLS_PATH}/${TOOLCHAIN}/bin:${TOOLS_PATH}/host/bin:$PATH +export PREFIX="/tools/deps" + +tar -xf zstd-${ZSTD_VERSION}.tar.gz + +pushd cpython-source-deps-zstd-${ZSTD_VERSION}/lib + +if [ "${CC}" = "musl-clang" ]; then + # In order to build the library with intrinsics, we need musl-clang to find + # headers that provide access to the intrinsics, as they are not provided by musl. These are + # part of the include files that are part of clang. But musl-clang eliminates them from the + # default include path. So copy them into place. + for h in ${TOOLS_PATH}/${TOOLCHAIN}/lib/clang/*/include/*intrin.h ${TOOLS_PATH}/${TOOLCHAIN}/lib/clang/*/include/{__wmmintrin_aes.h,__wmmintrin_pclmul.h,emmintrin.h,immintrin.h,mm_malloc.h,arm_neon.h,arm_neon_sve_bridge.h,arm_bf16.h,arm_fp16.h,arm_acle.h,arm_vector_types.h}; do + filename=$(basename "$h") + if [ -f "$h" ]; then + if [ -e "${TOOLS_PATH}/host/include/${filename}" ]; then + echo "warning: ${filename} already exists" + fi + cp "$h" ${TOOLS_PATH}/host/include/ + else + echo "warning: ${filename} not found (skipping)" + fi + done + EXTRA_TARGET_CFLAGS="${EXTRA_TARGET_CFLAGS} -I${TOOLS_PATH}/host/include/" + + # `qsort_r` is only available in musl 1.2.3+ but we use 1.2.2. The zstd source provides a + # fallback implementation, but they do not have a `configure`-style detection of whether + # `qsort_r` is actually available so we patch it to include a check for glibc. + patch -p1 <suffix, ctx->suffixSize, sizeof(U32), + ctx, + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp)); +-#elif defined(_GNU_SOURCE) ++#elif defined(_GNU_SOURCE) && defined(__GLIBC__) + qsort_r(ctx->suffix, ctx->suffixSize, sizeof(U32), + (ctx->d <= 8 ? &COVER_strict_cmp8 : &COVER_strict_cmp), + ctx); +EOF +fi + +CFLAGS="${EXTRA_TARGET_CFLAGS} -fPIC -DZSTD_MULTITHREAD -O3" LDFLAGS="${EXTRA_TARGET_LDFLAGS}" make -j ${NUM_CPUS} VERBOSE=1 libzstd.a +make -j ${NUM_CPUS} install-static DESTDIR=${ROOT}/out +make -j ${NUM_CPUS} install-includes DESTDIR=${ROOT}/out +MT=1 make -j ${NUM_CPUS} install-pc DESTDIR=${ROOT}/out diff --git a/cpython-unix/build.debian9.Dockerfile b/cpython-unix/build.debian9.Dockerfile new file mode 100644 index 0000000..1f7c91b --- /dev/null +++ b/cpython-unix/build.debian9.Dockerfile @@ -0,0 +1,16 @@ +{% include 'base.debian9.Dockerfile' %} + +RUN ulimit -n 10000 && apt-get install \ + bzip2 \ + file \ + libc6-dev \ + libffi-dev \ + make \ + patch \ + perl \ + pkg-config \ + tar \ + xz-utils \ + unzip \ + zip \ + zlib1g-dev diff --git a/cpython-unix/build.py b/cpython-unix/build.py index 6f98e99..c5d73a1 100755 --- a/cpython-unix/build.py +++ b/cpython-unix/build.py @@ -88,14 +88,26 @@ def add_target_env(env, build_platform, target_triple, build_env): extra_host_cflags = [] extra_host_ldflags = [] - if build_platform == "linux_x86_64": - env["BUILD_TRIPLE"] = "x86_64-unknown-linux-gnu" + # Add compiler-rt for aarch64-musl to resolve missing builtins + if target_triple == "aarch64-unknown-linux-musl": + extra_target_cflags.append("--rtlib=compiler-rt") + extra_target_ldflags.append("--rtlib=compiler-rt") - env["TARGET_TRIPLE"] = ( - target_triple.replace("x86_64_v2-", "x86_64-") - .replace("x86_64_v3-", "x86_64-") - .replace("x86_64_v4-", "x86_64-") - ) + if build_platform.startswith("linux_"): + machine = platform.machine() + + if machine == "aarch64": + env["BUILD_TRIPLE"] = "aarch64-unknown-linux-gnu" + env["TARGET_TRIPLE"] = target_triple + elif machine == "x86_64": + env["BUILD_TRIPLE"] = "x86_64-unknown-linux-gnu" + env["TARGET_TRIPLE"] = ( + target_triple.replace("x86_64_v2-", "x86_64-") + .replace("x86_64_v3-", "x86_64-") + .replace("x86_64_v4-", "x86_64-") + ) + else: + raise Exception("unhandled Linux machine value: %s" % machine) # This will make x86_64_v2, etc count as cross-compiling. This is # semantically correct, since the current machine may not support @@ -105,7 +117,7 @@ def add_target_env(env, build_platform, target_triple, build_env): ): env["CROSS_COMPILING"] = "1" - if build_platform.startswith("macos_"): + elif build_platform.startswith("macos_"): machine = platform.machine() if machine == "arm64": @@ -188,6 +200,8 @@ def add_target_env(env, build_platform, target_triple, build_env): extra_host_cflags.extend(["-isysroot", host_sdk_path]) extra_host_ldflags.extend(["-isysroot", host_sdk_path]) + else: + raise Exception("unhandled build platform: %s" % build_platform) env["EXTRA_HOST_CFLAGS"] = " ".join(extra_host_cflags) env["EXTRA_HOST_LDFLAGS"] = " ".join(extra_host_ldflags) @@ -370,48 +384,6 @@ def build_libedit( build_env.get_tools_archive(dest_archive, "deps") -def build_tix( - settings, client, image, host_platform, target_triple, build_options, dest_archive -): - tcl_archive = download_entry("tcl", DOWNLOADS_PATH) - tk_archive = download_entry("tk", DOWNLOADS_PATH) - tix_archive = download_entry("tix", DOWNLOADS_PATH) - - with build_environment(client, image) as build_env: - if settings.get("needs_toolchain"): - build_env.install_toolchain( - BUILD, - host_platform, - target_triple, - binutils=install_binutils(host_platform), - clang=True, - musl="musl" in target_triple, - static="static" in build_options, - ) - - depends = {"tcl", "tk"} - if not host_platform.startswith("macos_"): - depends |= {"libX11", "xorgproto"} - - for p in sorted(depends): - build_env.install_artifact_archive(BUILD, p, target_triple, build_options) - - for p in (tcl_archive, tk_archive, tix_archive, SUPPORT / "build-tix.sh"): - build_env.copy_file(p) - - env = { - "TOOLCHAIN": "clang-%s" % host_platform, - "TCL_VERSION": DOWNLOADS["tcl"]["version"], - "TIX_VERSION": DOWNLOADS["tix"]["version"], - "TK_VERSION": DOWNLOADS["tk"]["version"], - } - - add_target_env(env, host_platform, target_triple, build_env) - - build_env.run("build-tix.sh", environment=env) - build_env.get_tools_archive(dest_archive, "deps") - - def build_cpython_host( client, image, @@ -496,10 +468,14 @@ def python_build_info( binary_suffix = "" - if platform == "linux_x86_64": + if platform in ("linux_x86_64", "linux_aarch64"): + arch = platform.removeprefix("linux_") + bi["core"]["static_lib"] = ( - "install/lib/python{version}/config-{version}{binary_suffix}-x86_64-linux-gnu/libpython{version}{binary_suffix}.a".format( - version=version, binary_suffix=binary_suffix + "install/lib/python{version}/config-{version}{binary_suffix}-{arch}-linux-gnu/libpython{version}{binary_suffix}.a".format( + version=version, + binary_suffix=binary_suffix, + arch=arch, ) ) @@ -541,7 +517,7 @@ def python_build_info( bi["object_file_format"] = object_file_format - # Determine allowed libaries on Linux + # Determine allowed libraries on Linux libs = extra_metadata["python_config_vars"].get("LIBS", "").split() mips = target_triple.split("-")[0] in {"mips", "mipsel"} linux_allowed_system_libraries = LINUX_ALLOW_SYSTEM_LIBRARIES.copy() @@ -579,7 +555,10 @@ def python_build_info( if lib.startswith("-l"): lib = lib[2:] - if platform == "linux_x86_64" and lib not in linux_allowed_system_libraries: + if ( + platform in ("linux_x86_64", "linux_aarch64") + and lib not in linux_allowed_system_libraries + ): raise Exception("unexpected library in LIBS (%s): %s" % (libs, lib)) elif ( platform.startswith("macos_") @@ -851,7 +830,7 @@ def build_cpython( extension_module_loading = ["builtin"] crt_features = [] - if host_platform == "linux_x86_64": + if host_platform in ("linux_x86_64", "linux_aarch64"): if "static" in parsed_build_options: crt_features.append("static") else: @@ -930,9 +909,6 @@ def build_cpython( "tk8.6", ] - if "-apple" not in target_triple: - python_info["tcl_library_paths"].append("Tix8.4.3") - if "-apple" in target_triple: python_info["apple_sdk_platform"] = env["APPLE_SDK_PLATFORM"] python_info["apple_sdk_version"] = env["APPLE_SDK_VERSION"] @@ -1080,10 +1056,14 @@ def main(): with image_path.open("rb") as fh: image_data = fh.read() - build_docker_image(client, image_data, BUILD, image_name) + build_docker_image(client, image_data, BUILD, image_name, host_platform) elif action == "binutils": - build_binutils(client, get_image(client, ROOT, BUILD, "gcc"), host_platform) + build_binutils( + client, + get_image(client, ROOT, BUILD, docker_image, host_platform), + host_platform, + ) elif action == "clang": materialize_clang(host_platform, target_triple) @@ -1091,7 +1071,7 @@ def main(): elif action == "musl": build_musl( client, - get_image(client, ROOT, BUILD, "gcc"), + get_image(client, ROOT, BUILD, docker_image, host_platform), host_platform, target_triple, build_options, @@ -1101,7 +1081,7 @@ def main(): simple_build( settings, client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), action, host_platform=host_platform, target_triple=target_triple, @@ -1115,7 +1095,7 @@ def main(): build_libedit( settings, client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), host_platform=host_platform, target_triple=target_triple, build_options=build_options, @@ -1143,18 +1123,23 @@ def main(): "xtrans", "xz", "zlib", + "zstd", ): tools_path = "host" if action in ("m4", "patchelf") else "deps" + extra_archives = { + "tcl": {"zlib"}, + }.get(action) simple_build( settings, client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), action, host_platform=host_platform, target_triple=target_triple, build_options=build_options, dest_archive=dest_archive, + extra_archives=extra_archives, tools_path=tools_path, ) @@ -1162,7 +1147,7 @@ def main(): simple_build( settings, client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), action, host_platform=host_platform, target_triple=target_triple, @@ -1182,7 +1167,7 @@ def main(): simple_build( settings, client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), action, host_platform=host_platform, target_triple=target_triple, @@ -1195,7 +1180,7 @@ def main(): simple_build( settings, client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), action, host_platform=host_platform, target_triple=target_triple, @@ -1208,7 +1193,7 @@ def main(): simple_build( settings, client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), action, host_platform=host_platform, target_triple=target_triple, @@ -1218,19 +1203,8 @@ def main(): python_host_version=python_host_version, ) - elif action == "tix": - build_tix( - settings, - client, - get_image(client, ROOT, BUILD, docker_image), - host_platform=host_platform, - target_triple=target_triple, - build_options=build_options, - dest_archive=dest_archive, - ) - elif action == "tk": - extra_archives = {"tcl"} + extra_archives = {"tcl", "zlib"} if not host_platform.startswith("macos_"): extra_archives |= { "libX11", @@ -1243,7 +1217,7 @@ def main(): simple_build( settings, client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), action, host_platform=host_platform, target_triple=target_triple, @@ -1256,7 +1230,7 @@ def main(): elif action.startswith("cpython-") and action.endswith("-host"): build_cpython_host( client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), action[:-5], host_platform=host_platform, target_triple=target_triple, @@ -1275,7 +1249,7 @@ def main(): build_cpython( settings, client, - get_image(client, ROOT, BUILD, docker_image), + get_image(client, ROOT, BUILD, docker_image, host_platform), host_platform=host_platform, target_triple=target_triple, build_options=build_options, diff --git a/cpython-unix/extension-modules.yml b/cpython-unix/extension-modules.yml index 3d69f04..214d90a 100644 --- a/cpython-unix/extension-modules.yml +++ b/cpython-unix/extension-modules.yml @@ -145,6 +145,7 @@ _ctypes: - dl _ctypes_test: + build-mode: shared sources: - _ctypes/_ctypes_test.c links: @@ -206,6 +207,9 @@ _curses_panel: _datetime: sources: - _datetimemodule.c + setup-enabled-conditional: + - enabled: true + minimum-python-version: "3.14" _dbm: sources: @@ -529,8 +533,6 @@ _sqlite3: - include includes: - Modules/_sqlite - defines: - - "MODULE_NAME=\\\"sqlite3\\\"" defines-conditional: # Require dynamic binaries to load extensions. Cannot load on iOS. # 3.11+ uses opt in. <3.11 uses opt out. @@ -544,6 +546,8 @@ _sqlite3: - define: SQLITE_OMIT_LOAD_EXTENSION=1 targets: - .*-ios + - define: "MODULE_NAME=\\\"sqlite3\\\"" + maximum-python-version: "3.9" links: - sqlite3 @@ -670,45 +674,27 @@ _tkinter: sources: - _tkinter.c - tkappinit.c - # TODO consider adding WITH_TIX, as Modules/Setup seems to recommend it. This also - # initializes tix at init time, which seems desirable. defines: - WITH_APPINIT includes-deps: - include/X11 + build-mode: shared links: - tcl8.6 - tk8.6 - - # Without -ObjC, we get a crash: -[TKApplication tkProcessEvent:]: unrecognized selector sent to instance. - # See also https://core.tcl-lang.org/tk/tktview/85f316beb15108ac43b03fa6c8608e31f3ae5f92. - # This is apparently an issue with static linking Objective-C binaries. - linker-args: - - args: ["-ObjC"] - targets: - - .*-apple-darwin links-conditional: - name: X11 targets: - .*-unknown-linux-.* + build-mode: static - name: xcb targets: - .*-unknown-linux-.* + build-mode: static - name: Xau targets: - .*-unknown-linux-.* - # Many of these are dependencies of libtcl and libtk. - frameworks: - - AppKit - - ApplicationServices - - Carbon - - Cocoa - - CoreFoundation - - CoreServices - - CoreGraphics - - IOKit - - QuartzCore - - UniformTypeIdentifiers + build-mode: static _tokenize: minimum-python-version: "3.11" @@ -772,15 +758,14 @@ _xxtestfuzz: - _xxtestfuzz/fuzzer.c _zstd: - # Disable on all targets until we add a zstd library - disabled-targets: - - .* minimum-python-version: '3.14' sources: - _zstd/_zstdmodule.c - - _zstd/zdict.c + - _zstd/zstddict.c - _zstd/compressor.c - _zstd/decompressor.c + links: + - zstd _zoneinfo: minimum-python-version: "3.9" diff --git a/cpython-unix/gcc.debian9.Dockerfile b/cpython-unix/gcc.debian9.Dockerfile new file mode 100644 index 0000000..92d764e --- /dev/null +++ b/cpython-unix/gcc.debian9.Dockerfile @@ -0,0 +1,14 @@ +{% include 'base.debian9.Dockerfile' %} +RUN ulimit -n 10000 && apt-get install \ + autoconf \ + automake \ + bison \ + build-essential \ + gawk \ + gcc \ + libtool \ + make \ + tar \ + texinfo \ + xz-utils \ + unzip diff --git a/cpython-unix/patch-jit-cflags-314.patch b/cpython-unix/patch-jit-cflags-314.patch deleted file mode 100644 index 3a16fb5..0000000 --- a/cpython-unix/patch-jit-cflags-314.patch +++ /dev/null @@ -1,74 +0,0 @@ -diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py -index d0a1c081ffe..deb83f275d2 100644 ---- a/Tools/jit/_targets.py -+++ b/Tools/jit/_targets.py -@@ -10,6 +10,7 @@ - import sys - import tempfile - import typing -+import shlex - - import _llvm - import _schema -@@ -46,6 +47,7 @@ class _Target(typing.Generic[_S, _R]): - stable: bool = False - debug: bool = False - verbose: bool = False -+ cflags: str = "" - known_symbols: dict[str, int] = dataclasses.field(default_factory=dict) - pyconfig_dir: pathlib.Path = pathlib.Path.cwd().resolve() - -@@ -120,6 +122,7 @@ async def _compile( - ) -> _stencils.StencilGroup: - o = tempdir / f"{opname}.o" - args = [ -+ *shlex.split(self.cflags), - f"--target={self.triple}", - "-DPy_BUILD_CORE_MODULE", - "-D_DEBUG" if self.debug else "-DNDEBUG", -diff --git a/Tools/jit/build.py b/Tools/jit/build.py -index 1afd0c76bad..96c4cb07593 100644 ---- a/Tools/jit/build.py -+++ b/Tools/jit/build.py -@@ -39,11 +39,15 @@ - parser.add_argument( - "-v", "--verbose", action="store_true", help="echo commands as they are run" - ) -+ parser.add_argument( -+ "--with-cflags", help="additional flags to pass to the compiler", default="" -+ ) - args = parser.parse_args() - for target in args.target: - target.debug = args.debug - target.force = args.force - target.verbose = args.verbose -+ target.cflags = args.with_cflags - target.pyconfig_dir = args.pyconfig_dir - target.build( - comment=comment, -diff --git a/configure b/configure -index 884f8a4b068..2e6740c33d9 100755 ---- a/configure -+++ b/configure -@@ -10863,7 +10863,7 @@ then : - - else case e in #( - e) as_fn_append CFLAGS_NODIST " $jit_flags" -- REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir ." -+ REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --with-cflags=\"\$(CONFIGURE_CFLAGS)\"" - JIT_STENCILS_H="jit_stencils.h" - if test "x$Py_DEBUG" = xtrue - then : -diff --git a/configure.ac b/configure.ac -index cf25148bad2..f8bfab7bf96 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -2776,7 +2776,7 @@ AS_VAR_IF([jit_flags], - [], - [AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"]) - AS_VAR_SET([REGEN_JIT_COMMAND], -- ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir ."]) -+ ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --with-cflags=\"\$(CONFIGURE_CFLAGS)\""]) - AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"]) - AS_VAR_IF([Py_DEBUG], - [true], diff --git a/cpython-unix/patch-static-remote-debug-3.14.patch b/cpython-unix/patch-static-remote-debug-3.14.patch deleted file mode 100644 index 1c359c3..0000000 --- a/cpython-unix/patch-static-remote-debug-3.14.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/Python/remote_debug.h b/Python/remote_debug.h -index 6cbf1c8deaa..ab494ea71da 100644 ---- a/Python/remote_debug.h -+++ b/Python/remote_debug.h -@@ -131,7 +131,7 @@ _Py_RemoteDebug_FreePageCache(proc_handle_t *handle) - } - } - --void -+static void - _Py_RemoteDebug_ClearCache(proc_handle_t *handle) - { - for (int i = 0; i < MAX_PAGES; i++) { -@@ -989,7 +989,7 @@ _Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address - #endif - } - --int -+static int - _Py_RemoteDebug_PagedReadRemoteMemory(proc_handle_t *handle, - uintptr_t addr, - size_t size, diff --git a/cpython-unix/patch-uuid-getnode-stable-3.13.patch b/cpython-unix/patch-uuid-getnode-stable-3.13.patch deleted file mode 100644 index 11bdf83..0000000 --- a/cpython-unix/patch-uuid-getnode-stable-3.13.patch +++ /dev/null @@ -1,708 +0,0 @@ -diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py -index e7e44c6413c2e2..ce396aa942b6ed 100755 ---- a/Lib/test/test_uuid.py -+++ b/Lib/test/test_uuid.py -@@ -1,6 +1,7 @@ - import unittest - from test import support - from test.support import import_helper -+from test.support.script_helper import assert_python_ok - import builtins - import contextlib - import copy -@@ -773,10 +774,37 @@ def test_cli_uuid5_ouputted_with_valid_namespace_and_name(self): - class TestUUIDWithoutExtModule(BaseTestUUID, unittest.TestCase): - uuid = py_uuid - -+ - @unittest.skipUnless(c_uuid, 'requires the C _uuid module') - class TestUUIDWithExtModule(BaseTestUUID, unittest.TestCase): - uuid = c_uuid - -+ def check_has_stable_libuuid_extractable_node(self): -+ if not self.uuid._has_stable_extractable_node: -+ self.skipTest("libuuid cannot deduce MAC address") -+ -+ @unittest.skipUnless(os.name == 'posix', 'POSIX only') -+ def test_unix_getnode_from_libuuid(self): -+ self.check_has_stable_libuuid_extractable_node() -+ script = 'import uuid; print(uuid._unix_getnode())' -+ _, n_a, _ = assert_python_ok('-c', script) -+ _, n_b, _ = assert_python_ok('-c', script) -+ n_a, n_b = n_a.decode().strip(), n_b.decode().strip() -+ self.assertTrue(n_a.isdigit()) -+ self.assertTrue(n_b.isdigit()) -+ self.assertEqual(n_a, n_b) -+ -+ @unittest.skipUnless(os.name == 'nt', 'Windows only') -+ def test_windows_getnode_from_libuuid(self): -+ self.check_has_stable_libuuid_extractable_node() -+ script = 'import uuid; print(uuid._windll_getnode())' -+ _, n_a, _ = assert_python_ok('-c', script) -+ _, n_b, _ = assert_python_ok('-c', script) -+ n_a, n_b = n_a.decode().strip(), n_b.decode().strip() -+ self.assertTrue(n_a.isdigit()) -+ self.assertTrue(n_b.isdigit()) -+ self.assertEqual(n_a, n_b) -+ - - class BaseTestInternals: - _uuid = py_uuid -diff --git a/Lib/uuid.py b/Lib/uuid.py -index c286eac38e1ef4..6ab1658cc5249a 100644 ---- a/Lib/uuid.py -+++ b/Lib/uuid.py -@@ -572,22 +572,24 @@ def _netstat_getnode(): - try: - import _uuid - _generate_time_safe = getattr(_uuid, "generate_time_safe", None) -+ _has_stable_extractable_node = getattr(_uuid, "has_stable_extractable_node", False) - _UuidCreate = getattr(_uuid, "UuidCreate", None) - except ImportError: - _uuid = None - _generate_time_safe = None -+ _has_stable_extractable_node = False - _UuidCreate = None - - - def _unix_getnode(): - """Get the hardware address on Unix using the _uuid extension module.""" -- if _generate_time_safe: -+ if _generate_time_safe and _has_stable_extractable_node: - uuid_time, _ = _generate_time_safe() - return UUID(bytes=uuid_time).node - - def _windll_getnode(): - """Get the hardware address on Windows using the _uuid extension module.""" -- if _UuidCreate: -+ if _UuidCreate and _has_stable_extractable_node: - uuid_bytes = _UuidCreate() - return UUID(bytes_le=uuid_bytes).node - -diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c -index c5e78b1510b5e3..c31a7e8fea5608 100644 ---- a/Modules/_uuidmodule.c -+++ b/Modules/_uuidmodule.c -@@ -78,23 +78,47 @@ py_UuidCreate(PyObject *Py_UNUSED(context), - return NULL; - } - -+static int -+py_windows_has_stable_node(void) -+{ -+ UUID uuid; -+ RPC_STATUS res; -+ Py_BEGIN_ALLOW_THREADS -+ res = UuidCreateSequential(&uuid); -+ Py_END_ALLOW_THREADS -+ return res == RPC_S_OK; -+} - #endif /* MS_WINDOWS */ - - - static int --uuid_exec(PyObject *module) { -+uuid_exec(PyObject *module) -+{ -+#define ADD_INT(NAME, VALUE) \ -+ do { \ -+ if (PyModule_AddIntConstant(module, (NAME), (VALUE)) < 0) { \ -+ return -1; \ -+ } \ -+ } while (0) -+ - assert(sizeof(uuid_t) == 16); - #if defined(MS_WINDOWS) -- int has_uuid_generate_time_safe = 0; -+ ADD_INT("has_uuid_generate_time_safe", 0); - #elif defined(HAVE_UUID_GENERATE_TIME_SAFE) -- int has_uuid_generate_time_safe = 1; -+ ADD_INT("has_uuid_generate_time_safe", 1); - #else -- int has_uuid_generate_time_safe = 0; -+ ADD_INT("has_uuid_generate_time_safe", 0); - #endif -- if (PyModule_AddIntConstant(module, "has_uuid_generate_time_safe", -- has_uuid_generate_time_safe) < 0) { -- return -1; -- } -+ -+#if defined(MS_WINDOWS) -+ ADD_INT("has_stable_extractable_node", py_windows_has_stable_node()); -+#elif defined(HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC) -+ ADD_INT("has_stable_extractable_node", 1); -+#else -+ ADD_INT("has_stable_extractable_node", 0); -+#endif -+ -+#undef ADD_INT - return 0; - } - -diff --git a/configure b/configure -index 1cd1f690f7b9c1..cc976aafc09b34 100755 ---- a/configure -+++ b/configure -@@ -13381,6 +13381,7 @@ fi - - - -+ - have_uuid=missing - - for ac_header in uuid.h -@@ -13390,6 +13391,7 @@ if test "x$ac_cv_header_uuid_h" = xyes - then : - printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h - -+ - for ac_func in uuid_create uuid_enc_be - do : - as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | $as_tr_sh` -@@ -13399,7 +13401,9 @@ then : - cat >>confdefs.h <<_ACEOF - #define `printf "%s\n" "HAVE_$ac_func" | $as_tr_cpp` 1 - _ACEOF -- have_uuid=yes -+ -+ have_uuid=yes -+ ac_cv_have_uuid_h=yes - LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} - LIBUUID_LIBS=${LIBUUID_LIBS-""} - -@@ -13489,6 +13493,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes - then : - printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h - -+ ac_cv_have_uuid_uuid_h=yes - py_check_lib_save_LIBS=$LIBS - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 - printf %s "checking for uuid_generate_time in -luuid... " >&6; } -@@ -13570,8 +13575,9 @@ fi - printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; } - if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes - then : -- have_uuid=yes -- printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h -+ -+ have_uuid=yes -+ ac_cv_have_uuid_generate_time_safe=yes - - fi - -@@ -13615,6 +13621,7 @@ if test "x$ac_cv_header_uuid_uuid_h" = xyes - then : - printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h - -+ ac_cv_have_uuid_uuid_h=yes - py_check_lib_save_LIBS=$LIBS - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5 - printf %s "checking for uuid_generate_time in -luuid... " >&6; } -@@ -13696,8 +13703,9 @@ fi - printf "%s\n" "$ac_cv_lib_uuid_uuid_generate_time_safe" >&6; } - if test "x$ac_cv_lib_uuid_uuid_generate_time_safe" = xyes - then : -- have_uuid=yes -- printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h -+ -+ have_uuid=yes -+ ac_cv_have_uuid_generate_time_safe=yes - - fi - -@@ -13727,11 +13735,25 @@ else - LIBUUID_LIBS=$pkg_cv_LIBUUID_LIBS - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 - printf "%s\n" "yes" >&6; } -+<<<<<<< HEAD - have_uuid=yes - printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h - - printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h - -+======= -+ have_uuid=yes -+ ac_cv_have_uuid_generate_time_safe=yes -+ # The uuid.h file to include may be *or* . -+ # Since pkg-config --cflags uuid may return -I/usr/include/uuid, -+ # it's possible to write '#include ' in _uuidmodule.c, -+ # assuming that the compiler flags are properly updated. -+ # -+ # Ideally, we should have defined HAVE_UUID_H if and only if -+ # #include can be written, *without* assuming extra -+ # include path. -+ ac_cv_have_uuid_h=yes -+>>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901)) - - fi - -@@ -13752,6 +13774,7 @@ if test "x$ac_cv_func_uuid_generate_time" = xyes - then : - - have_uuid=yes -+ ac_cv_have_uuid_uuid_h=yes - LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} - LIBUUID_LIBS=${LIBUUID_LIBS-""} - -@@ -13764,11 +13787,198 @@ done - - fi - -+<<<<<<< HEAD -+======= -+if test "x$ac_cv_have_uuid_h" = xyes -+then : -+ printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h -+ -+fi -+if test "x$ac_cv_have_uuid_uuid_h" = xyes -+then : -+ printf "%s\n" "#define HAVE_UUID_UUID_H 1" >>confdefs.h -+ -+fi -+if test "x$ac_cv_have_uuid_generate_time_safe" = xyes -+then : -+ -+ printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h -+ -+ -+fi -+ -+# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4. -+# This restriction inhibits the proper generation of time-based UUIDs. -+if test "$ac_sys_system" = "NetBSD"; then -+ have_uuid=missing -+ printf "%s\n" "#define HAVE_UUID_H 0" >>confdefs.h -+ -+fi -+ -+>>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901)) - if test "x$have_uuid" = xmissing - then : - have_uuid=no - fi - -+# gh-132710: The UUID node is fetched by using libuuid when possible -+# and cached. While the node is constant within the same process, -+# different interpreters may have different values as libuuid may -+# randomize the node value if the latter cannot be deduced. -+# -+# Consumers may define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC -+# to indicate that libuuid is unstable and should not be relied -+# upon to deduce the MAC address. -+ -+ -+if test "$have_uuid" = "yes" -a "$HAVE_UUID_GENERATE_TIME_SAFE" = "1" -+then -+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if uuid_generate_time_safe() node value is stable" >&5 -+printf %s "checking if uuid_generate_time_safe() node value is stable... " >&6; } -+ save_CFLAGS=$CFLAGS -+save_CPPFLAGS=$CPPFLAGS -+save_LDFLAGS=$LDFLAGS -+save_LIBS=$LIBS -+ -+ -+ # Be sure to add the extra include path if we used pkg-config -+ # as HAVE_UUID_H may be set even though is only reachable -+ # by adding extra -I flags. -+ # -+ # If the following script does not compile, we simply assume that -+ # libuuid is missing. -+ CFLAGS="$CFLAGS $LIBUUID_CFLAGS" -+ LIBS="$LIBS $LIBUUID_LIBS" -+ if test "$cross_compiling" = yes -+then : -+ -+ -+else case e in #( -+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+ #include // PRIu64 -+ #include // uint64_t -+ #include // fopen(), fclose() -+ -+ #ifdef HAVE_UUID_H -+ #include -+ #else -+ #include -+ #endif -+ -+ #define ERR 1 -+ int main(void) { -+ uuid_t uuid; // unsigned char[16] -+ (void)uuid_generate_time_safe(uuid); -+ uint64_t node = 0; -+ for (size_t i = 0; i < 6; i++) { -+ node |= (uint64_t)uuid[15 - i] << (8 * i); -+ } -+ FILE *fp = fopen("conftest.out", "w"); -+ if (fp == NULL) { -+ return ERR; -+ } -+ int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0; -+ rc |= fclose(fp); -+ return rc == 0 ? 0 : ERR; -+ } -+_ACEOF -+if ac_fn_c_try_run "$LINENO" -+then : -+ -+ py_cv_uuid_node1=`cat conftest.out` -+ -+fi -+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ -+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;; -+esac -+fi -+ -+CFLAGS=$save_CFLAGS -+CPPFLAGS=$save_CPPFLAGS -+LDFLAGS=$save_LDFLAGS -+LIBS=$save_LIBS -+ -+ -+ save_CFLAGS=$CFLAGS -+save_CPPFLAGS=$CPPFLAGS -+save_LDFLAGS=$LDFLAGS -+save_LIBS=$LIBS -+ -+ -+ # Be sure to add the extra include path if we used pkg-config -+ # as HAVE_UUID_H may be set even though is only reachable -+ # by adding extra -I flags. -+ # -+ # If the following script does not compile, we simply assume that -+ # libuuid is missing. -+ CFLAGS="$CFLAGS $LIBUUID_CFLAGS" -+ LIBS="$LIBS $LIBUUID_LIBS" -+ if test "$cross_compiling" = yes -+then : -+ -+ -+else case e in #( -+ e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+ -+ #include // PRIu64 -+ #include // uint64_t -+ #include // fopen(), fclose() -+ -+ #ifdef HAVE_UUID_H -+ #include -+ #else -+ #include -+ #endif -+ -+ #define ERR 1 -+ int main(void) { -+ uuid_t uuid; // unsigned char[16] -+ (void)uuid_generate_time_safe(uuid); -+ uint64_t node = 0; -+ for (size_t i = 0; i < 6; i++) { -+ node |= (uint64_t)uuid[15 - i] << (8 * i); -+ } -+ FILE *fp = fopen("conftest.out", "w"); -+ if (fp == NULL) { -+ return ERR; -+ } -+ int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0; -+ rc |= fclose(fp); -+ return rc == 0 ? 0 : ERR; -+ } -+_ACEOF -+if ac_fn_c_try_run "$LINENO" -+then : -+ -+ py_cv_uuid_node2=`cat conftest.out` -+ -+fi -+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ -+ conftest.$ac_objext conftest.beam conftest.$ac_ext ;; -+esac -+fi -+ -+CFLAGS=$save_CFLAGS -+CPPFLAGS=$save_CPPFLAGS -+LDFLAGS=$save_LDFLAGS -+LIBS=$save_LIBS -+ -+ -+ if test -n "$py_cv_uuid_node1" -a "$py_cv_uuid_node1" = "$py_cv_uuid_node2" -+ then -+ printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC 1" >>confdefs.h -+ -+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: stable" >&5 -+printf "%s\n" "stable" >&6; } -+ else -+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unstable" >&5 -+printf "%s\n" "unstable" >&6; } -+ fi -+fi -+ - # 'Real Time' functions on Solaris - # posix4 on Solaris 2.6 - # pthread (first!) on Linux -diff --git a/configure.ac b/configure.ac -index 3fcb18922c5330..9898af7ffd5f25 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -3740,15 +3740,17 @@ dnl check for uuid dependencies - AH_TEMPLATE([HAVE_UUID_H], [Define to 1 if you have the header file.]) - AH_TEMPLATE([HAVE_UUID_UUID_H], [Define to 1 if you have the header file.]) - AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE], [Define if uuid_generate_time_safe() exists.]) -+AH_TEMPLATE([HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC], [Define if uuid_generate_time_safe() is able to deduce a MAC address.]) - have_uuid=missing - - dnl AIX provides support for RFC4122 (uuid) in libc.a starting with AIX 6.1 - dnl (anno 2007). FreeBSD and OpenBSD provides support in libc as well. - dnl Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet - dnl stream in big-endian byte-order --AC_CHECK_HEADERS([uuid.h], -- [AC_CHECK_FUNCS([uuid_create uuid_enc_be], -- [have_uuid=yes -+AC_CHECK_HEADERS([uuid.h], [ -+ AC_CHECK_FUNCS([uuid_create uuid_enc_be], [ -+ have_uuid=yes -+ ac_cv_have_uuid_h=yes - LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} - LIBUUID_LIBS=${LIBUUID_LIBS-""} - ]) -@@ -3758,19 +3760,29 @@ AS_VAR_IF([have_uuid], [missing], [ - PKG_CHECK_MODULES( - [LIBUUID], [uuid >= 2.20], - [dnl linux-util's libuuid has uuid_generate_time_safe() since v2.20 (2011) -- dnl and provides . -+ dnl and provides assuming specific include paths are given - have_uuid=yes -- AC_DEFINE([HAVE_UUID_H], [1]) -- AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) -+ ac_cv_have_uuid_generate_time_safe=yes -+ # The uuid.h file to include may be *or* . -+ # Since pkg-config --cflags uuid may return -I/usr/include/uuid, -+ # it's possible to write '#include ' in _uuidmodule.c, -+ # assuming that the compiler flags are properly updated. -+ # -+ # Ideally, we should have defined HAVE_UUID_H if and only if -+ # #include can be written, *without* assuming extra -+ # include path. -+ ac_cv_have_uuid_h=yes - ], [ - WITH_SAVE_ENV([ - CPPFLAGS="$CPPFLAGS $LIBUUID_CFLAGS" - LIBS="$LIBS $LIBUUID_LIBS" - AC_CHECK_HEADERS([uuid/uuid.h], [ -+ ac_cv_have_uuid_uuid_h=yes - PY_CHECK_LIB([uuid], [uuid_generate_time], [have_uuid=yes]) -- PY_CHECK_LIB([uuid], [uuid_generate_time_safe], -- [have_uuid=yes -- AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) ]) ]) -+ PY_CHECK_LIB([uuid], [uuid_generate_time_safe], [ -+ have_uuid=yes -+ ac_cv_have_uuid_generate_time_safe=yes -+ ])]) - AS_VAR_IF([have_uuid], [yes], [ - LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} - LIBUUID_LIBS=${LIBUUID_LIBS-"-luuid"} -@@ -3785,14 +3797,90 @@ AS_VAR_IF([have_uuid], [missing], [ - AC_CHECK_HEADERS([uuid/uuid.h], [ - AC_CHECK_FUNC([uuid_generate_time], [ - have_uuid=yes -+ ac_cv_have_uuid_uuid_h=yes - LIBUUID_CFLAGS=${LIBUUID_CFLAGS-""} - LIBUUID_LIBS=${LIBUUID_LIBS-""} - ]) - ]) - ]) - -+AS_VAR_IF([ac_cv_have_uuid_h], [yes], [AC_DEFINE([HAVE_UUID_H], [1])]) -+AS_VAR_IF([ac_cv_have_uuid_uuid_h], [yes], [AC_DEFINE([HAVE_UUID_UUID_H], [1])]) -+AS_VAR_IF([ac_cv_have_uuid_generate_time_safe], [yes], [ -+ AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE], [1]) -+]) -+ -+# gh-124228: While the libuuid library is available on NetBSD, it supports only UUID version 4. -+# This restriction inhibits the proper generation of time-based UUIDs. -+if test "$ac_sys_system" = "NetBSD"; then -+ have_uuid=missing -+ AC_DEFINE([HAVE_UUID_H], [0]) -+fi -+ - AS_VAR_IF([have_uuid], [missing], [have_uuid=no]) - -+# gh-132710: The UUID node is fetched by using libuuid when possible -+# and cached. While the node is constant within the same process, -+# different interpreters may have different values as libuuid may -+# randomize the node value if the latter cannot be deduced. -+# -+# Consumers may define HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC -+# to indicate that libuuid is unstable and should not be relied -+# upon to deduce the MAC address. -+AC_DEFUN([PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC], [WITH_SAVE_ENV([ -+ # Be sure to add the extra include path if we used pkg-config -+ # as HAVE_UUID_H may be set even though is only reachable -+ # by adding extra -I flags. -+ # -+ # If the following script does not compile, we simply assume that -+ # libuuid is missing. -+ CFLAGS="$CFLAGS $LIBUUID_CFLAGS" -+ LIBS="$LIBS $LIBUUID_LIBS" -+ AC_RUN_IFELSE([AC_LANG_SOURCE([[ -+ #include // PRIu64 -+ #include // uint64_t -+ #include // fopen(), fclose() -+ -+ #ifdef HAVE_UUID_H -+ #include -+ #else -+ #include -+ #endif -+ -+ #define ERR 1 -+ int main(void) { -+ uuid_t uuid; // unsigned char[16] -+ (void)uuid_generate_time_safe(uuid); -+ uint64_t node = 0; -+ for (size_t i = 0; i < 6; i++) { -+ node |= (uint64_t)uuid[15 - i] << (8 * i); -+ } -+ FILE *fp = fopen("conftest.out", "w"); -+ if (fp == NULL) { -+ return ERR; -+ } -+ int rc = fprintf(fp, "%" PRIu64 "\n", node) >= 0; -+ rc |= fclose(fp); -+ return rc == 0 ? 0 : ERR; -+ }]])], [ -+ AS_VAR_SET([$1], [`cat conftest.out`]) -+ ], [], [] -+ )])]) -+ -+if test "$have_uuid" = "yes" -a "$HAVE_UUID_GENERATE_TIME_SAFE" = "1" -+then -+ AC_MSG_CHECKING([if uuid_generate_time_safe() node value is stable]) -+ PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC([py_cv_uuid_node1]) -+ PY_EXTRACT_UUID_GENERATE_TIME_SAFE_MAC([py_cv_uuid_node2]) -+ if test -n "$py_cv_uuid_node1" -a "$py_cv_uuid_node1" = "$py_cv_uuid_node2" -+ then -+ AC_DEFINE([HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC], [1]) -+ AC_MSG_RESULT([stable]) -+ else -+ AC_MSG_RESULT([unstable]) -+ fi -+fi -+ - # 'Real Time' functions on Solaris - # posix4 on Solaris 2.6 - # pthread (first!) on Linux -diff --git a/pyconfig.h.in b/pyconfig.h.in -index 3c16c694c84599..73358a0f35ae82 100644 ---- a/pyconfig.h.in -+++ b/pyconfig.h.in -@@ -1548,6 +1548,9 @@ - /* Define if uuid_generate_time_safe() exists. */ - #undef HAVE_UUID_GENERATE_TIME_SAFE - -+/* Define if uuid_generate_time_safe() is able to deduce a MAC address. */ -+#undef HAVE_UUID_GENERATE_TIME_SAFE_STABLE_MAC -+ - /* Define to 1 if you have the header file. */ - #undef HAVE_UUID_H - - -From cb0f32a7d64b6dc4a63c4a683bb52a97ebe1d78a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= - <10796600+picnixz@users.noreply.github.com> -Date: Mon, 26 May 2025 12:34:00 +0200 -Subject: [PATCH 2/2] rgen - ---- - configure | 25 ++++++------------------- - 1 file changed, 6 insertions(+), 19 deletions(-) - -diff --git a/configure b/configure -index cc976aafc09b34..47e4f29e23a7ac 100755 ---- a/configure -+++ b/configure -@@ -13735,14 +13735,7 @@ else - LIBUUID_LIBS=$pkg_cv_LIBUUID_LIBS - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 - printf "%s\n" "yes" >&6; } --<<<<<<< HEAD - have_uuid=yes -- printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h -- -- printf "%s\n" "#define HAVE_UUID_GENERATE_TIME_SAFE 1" >>confdefs.h -- --======= -- have_uuid=yes - ac_cv_have_uuid_generate_time_safe=yes - # The uuid.h file to include may be *or* . - # Since pkg-config --cflags uuid may return -I/usr/include/uuid, -@@ -13753,7 +13746,6 @@ printf "%s\n" "yes" >&6; } - # #include can be written, *without* assuming extra - # include path. - ac_cv_have_uuid_h=yes -->>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901)) - - fi - -@@ -13787,8 +13779,6 @@ done - - fi - --<<<<<<< HEAD --======= - if test "x$ac_cv_have_uuid_h" = xyes - then : - printf "%s\n" "#define HAVE_UUID_H 1" >>confdefs.h -@@ -13815,7 +13805,6 @@ if test "$ac_sys_system" = "NetBSD"; then - - fi - -->>>>>>> 3bffada4672 (gh-132710: only use stable `_uuid.generate_time_safe()` to deduce MAC address (#132901)) - if test "x$have_uuid" = xmissing - then : - have_uuid=no -@@ -13853,8 +13842,8 @@ save_LIBS=$LIBS - then : - - --else case e in #( -- e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+else $as_nop -+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - - #include // PRIu64 -@@ -13891,8 +13880,7 @@ then : - - fi - rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ -- conftest.$ac_objext conftest.beam conftest.$ac_ext ;; --esac -+ conftest.$ac_objext conftest.beam conftest.$ac_ext - fi - - CFLAGS=$save_CFLAGS -@@ -13919,8 +13907,8 @@ save_LIBS=$LIBS - then : - - --else case e in #( -- e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+else $as_nop -+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext - /* end confdefs.h. */ - - #include // PRIu64 -@@ -13957,8 +13945,7 @@ then : - - fi - rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ -- conftest.$ac_objext conftest.beam conftest.$ac_ext ;; --esac -+ conftest.$ac_objext conftest.beam conftest.$ac_ext - fi - - CFLAGS=$save_CFLAGS diff --git a/cpython-unix/targets.yml b/cpython-unix/targets.yml index 1b47dba..451b984 100644 --- a/cpython-unix/targets.yml +++ b/cpython-unix/targets.yml @@ -108,6 +108,7 @@ aarch64-apple-darwin: - tk - uuid - xz + - zstd openssl_target: darwin64-arm64-cc aarch64-apple-ios: @@ -151,11 +152,13 @@ aarch64-apple-ios: - openssl-3.0 - sqlite - xz + - zstd openssl_target: ios64-cross aarch64-unknown-linux-gnu: host_platforms: - linux_x86_64 + - linux_aarch64 pythons_supported: - '3.9' - '3.10' @@ -163,11 +166,16 @@ aarch64-unknown-linux-gnu: - '3.12' - '3.13' - '3.14' - docker_image_suffix: .cross - host_cc: /usr/bin/x86_64-linux-gnu-gcc - host_cxx: /usr/bin/x86_64-linux-gnu-g++ - target_cc: /usr/bin/aarch64-linux-gnu-gcc - target_cxx: /usr/bin/aarch64-linux-gnu-g++ + docker_image_suffix: .debian9 + needs_toolchain: true + host_cc: clang + host_cxx: clang++ + target_cc: clang + target_cxx: clang++ + target_cflags: + - '-fvisibility=hidden' + # Needed to prevent BOLT from crashing. + - '-fdebug-default-version=4' needs: - autoconf - bdb @@ -187,12 +195,17 @@ aarch64-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-aarch64 + # Blocked on: + # BOLT-ERROR: Cannot relax adr in non-simple function + # trampoline_code_table/1. Use --strict option to override + # See https://github.com/llvm/llvm-project/issues/146541 + # bolt_capable: true arm64-apple-tvos: host_platforms: @@ -234,6 +247,7 @@ arm64-apple-tvos: - openssl-3.0 - sqlite - xz + - zstd openssl_target: todo armv7-unknown-linux-gnueabi: @@ -270,11 +284,11 @@ armv7-unknown-linux-gnueabi: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-armv4 armv7-unknown-linux-gnueabihf: @@ -311,11 +325,11 @@ armv7-unknown-linux-gnueabihf: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-armv4 mips-unknown-linux-gnu: @@ -352,11 +366,11 @@ mips-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-mips32 mipsel-unknown-linux-gnu: @@ -393,11 +407,11 @@ mipsel-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-mips32 ppc64le-unknown-linux-gnu: @@ -434,11 +448,11 @@ ppc64le-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-ppc64le riscv64-unknown-linux-gnu: @@ -475,11 +489,11 @@ riscv64-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux64-riscv64 s390x-unknown-linux-gnu: @@ -516,11 +530,11 @@ s390x-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux64-s390x thumb7k-apple-watchos: @@ -563,6 +577,7 @@ thumb7k-apple-watchos: - openssl-3.0 - sqlite - xz + - zstd openssl_target: todo # Intel macOS. @@ -618,6 +633,7 @@ x86_64-apple-darwin: - tk - uuid - xz + - zstd openssl_target: darwin64-x86_64-cc x86_64-apple-ios: @@ -661,6 +677,7 @@ x86_64-apple-ios: - openssl-3.0 - sqlite - xz + - zstd openssl_target: darwin64-x86_64-cc x86_64-apple-tvos: @@ -703,6 +720,7 @@ x86_64-apple-tvos: - openssl-3.0 - sqlite - xz + - zstd openssl_target: todo x86_64-apple-watchos: @@ -745,6 +763,7 @@ x86_64-apple-watchos: - openssl-3.0 - sqlite - xz + - zstd openssl_target: todo x86_64-unknown-linux-gnu: @@ -785,11 +804,11 @@ x86_64-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-x86_64 bolt_capable: true @@ -832,11 +851,11 @@ x86_64_v2-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-x86_64 bolt_capable: true @@ -879,11 +898,11 @@ x86_64_v3-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-x86_64 bolt_capable: true @@ -926,11 +945,11 @@ x86_64_v4-unknown-linux-gnu: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-x86_64 bolt_capable: true @@ -971,11 +990,11 @@ x86_64-unknown-linux-musl: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-x86_64 x86_64_v2-unknown-linux-musl: @@ -1016,11 +1035,11 @@ x86_64_v2-unknown-linux-musl: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-x86_64 x86_64_v3-unknown-linux-musl: @@ -1061,11 +1080,11 @@ x86_64_v3-unknown-linux-musl: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-x86_64 x86_64_v4-unknown-linux-musl: @@ -1106,9 +1125,56 @@ x86_64_v4-unknown-linux-musl: - sqlite - tcl - tk - - tix - uuid - xorgproto - xz - zlib + - zstd openssl_target: linux-x86_64 + +aarch64-unknown-linux-musl: + host_platforms: + - linux_x86_64 + - linux_aarch64 + pythons_supported: + - '3.9' + - '3.10' + - '3.11' + - '3.12' + - '3.13' + - '3.14' + needs_toolchain: true + docker_image_suffix: .debian9 + needs_toolchain: true + host_cc: clang + host_cxx: clang++ + target_cc: musl-clang + target_cxx: clang++ + target_cflags: + - '-fvisibility=hidden' + needs: + - autoconf + - bdb + - binutils + - bzip2 + - expat + - libedit + - libffi-3.3 + - libX11 + - libXau + - libxcb + - m4 + - mpdecimal + - musl + - ncurses + - openssl-3.0 + - patchelf + - sqlite + - tcl + - tk + - uuid + - xorgproto + - xz + - zlib + - zstd + openssl_target: linux-aarch64 diff --git a/cpython-windows/build.py b/cpython-windows/build.py index 15b0a44..5fce1ab 100644 --- a/cpython-windows/build.py +++ b/cpython-windows/build.py @@ -370,7 +370,7 @@ def hack_props( mpdecimal_version = DOWNLOADS["mpdecimal"]["version"] - if meets_python_minimum_version(python_version, "3.14"): + if meets_python_minimum_version(python_version, "3.14") or arch == "arm64": tcltk_commit = DOWNLOADS["tk-windows-bin"]["git_commit"] else: tcltk_commit = DOWNLOADS["tk-windows-bin-8612"]["git_commit"] @@ -464,6 +464,8 @@ def hack_props( suffix = b"-x64" elif arch == "win32": suffix = b"" + elif arch == "arm64": + suffix = b"" else: raise Exception("unhandled architecture: %s" % arch) @@ -505,6 +507,7 @@ def hack_project_files( build_directory: str, python_version: str, zlib_entry: str, + arch: str, ): """Hacks Visual Studio project files to work with our build.""" @@ -518,6 +521,17 @@ def hack_project_files( zlib_entry, ) + # `--include-tcltk` is forced off on arm64, undo that + # See https://github.com/python/cpython/pull/132650 + try: + static_replace_in_file( + cpython_source_path / "PC" / "layout" / "main.py", + rb'if ns.arch in ("arm32", "arm64"):', + rb'if ns.arch == "arm32":', + ) + except NoSearchStringError: + pass + # Our SQLite directory is named weirdly. This throws off version detection # in the project file. Replace the parsing logic with a static string. sqlite3_version = DOWNLOADS["sqlite"]["actual_version"].encode("ascii") @@ -603,14 +617,18 @@ def hack_project_files( # have a standalone zlib DLL, so we remove references to it. For Python # 3.14+, we're using tk-windows-bin 8.6.14 which includes a prebuilt zlib # DLL, so we skip this patch there. - if meets_python_minimum_version( - python_version, "3.12" - ) and meets_python_maximum_version(python_version, "3.13"): - static_replace_in_file( - pcbuild_path / "_tkinter.vcxproj", - rb'<_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDllName)" />', - rb"", - ) + # On arm64, we use the new version of tk-windows-bin for all versions. + if meets_python_minimum_version(python_version, "3.12") and ( + meets_python_maximum_version(python_version, "3.13") or arch == "arm64" + ): + try: + static_replace_in_file( + pcbuild_path / "_tkinter.vcxproj", + rb'<_TclTkDLL Include="$(tcltkdir)\bin\$(tclZlibDllName)" />', + rb"", + ) + except NoSearchStringError: + pass # We don't need to produce python_uwp.exe and its *w variant. Or the # python3.dll, pyshellext, or pylauncher. @@ -730,9 +748,11 @@ def build_openssl_for_arch( elif arch == "amd64": configure = "VC-WIN64A" prefix = "64" + elif arch == "arm64": + configure = "VC-WIN64-ARM" + prefix = "arm64" else: - print("invalid architecture: %s" % arch) - sys.exit(1) + raise Exception("unhandled architecture: %s" % arch) # The official CPython OpenSSL builds hack ms/uplink.c to change the # ``GetModuleHandle(NULL)`` invocation to load things from _ssl.pyd @@ -780,6 +800,12 @@ def build_openssl_for_arch( log("copying %s to %s" % (source, dest)) shutil.copyfile(source, dest) + # Copy `applink.c` to the include directory. + source_applink = source_root / "ms" / "applink.c" + dest_applink = install_root / "include" / "openssl" / "applink.c" + log("copying %s to %s" % (source_applink, dest_applink)) + shutil.copyfile(source_applink, dest_applink) + def build_openssl( entry: str, @@ -801,6 +827,7 @@ def build_openssl( root_32 = td / "x86" root_64 = td / "x64" + root_arm64 = td / "arm64" if arch == "x86": root_32.mkdir() @@ -824,13 +851,28 @@ def build_openssl( root_64, jom_archive=jom_archive, ) + elif arch == "arm64": + root_arm64.mkdir() + build_openssl_for_arch( + perl_path, + "arm64", + openssl_archive, + openssl_version, + nasm_archive, + root_arm64, + jom_archive=jom_archive, + ) else: - raise ValueError("unhandled arch: %s" % arch) + raise Exception("unhandled architecture: %s" % arch) install = td / "out" if arch == "x86": shutil.copytree(root_32 / "install" / "32", install / "openssl" / "win32") + elif arch == "arm64": + shutil.copytree( + root_arm64 / "install" / "arm64", install / "openssl" / "arm64" + ) else: shutil.copytree(root_64 / "install" / "64", install / "openssl" / "amd64") @@ -901,9 +943,14 @@ def build_libffi( if arch == "x86": args.append("-x86") artifacts_path = ffi_source_path / "i686-pc-cygwin" - else: + elif arch == "arm64": + args.append("-arm64") + artifacts_path = ffi_source_path / "aarch64-w64-cygwin" + elif arch == "amd64": args.append("-x64") artifacts_path = ffi_source_path / "x86_64-w64-cygwin" + else: + raise Exception("unhandled architecture: %s" % arch) subprocess.run(args, env=env, check=True) @@ -1069,8 +1116,10 @@ def find_additional_dependencies(project: pathlib.Path): abi_platform = "win_amd64" elif arch == "win32": abi_platform = "win32" + elif arch == "arm64": + abi_platform = "win_arm64" else: - raise ValueError("unhandled arch: %s" % arch) + raise Exception("unhandled architecture: %s" % arch) if freethreaded: abi_tag = ".cp%st-%s" % (python_majmin, abi_platform) @@ -1171,8 +1220,8 @@ def find_additional_dependencies(project: pathlib.Path): if name == "zlib": name = zlib_entry - # On 3.14+, we use the latest tcl/tk version - if ext == "_tkinter" and python_majmin == "314": + # On 3.14+ and aarch64, we use the latest tcl/tk version + if ext == "_tkinter" and (python_majmin == "314" or arch == "arm64"): name = name.replace("-8612", "") download_entry = DOWNLOADS[name] @@ -1258,16 +1307,18 @@ def build_cpython( setuptools_wheel = download_entry("setuptools", BUILD) pip_wheel = download_entry("pip", BUILD) - # On CPython 3.14+, we use the latest tcl/tk version which has additional runtime - # dependencies, so we are conservative and use the old version elsewhere. - if meets_python_minimum_version(python_version, "3.14"): - tk_bin_archive = download_entry( - "tk-windows-bin", BUILD, local_name="tk-windows-bin.tar.gz" - ) - else: - tk_bin_archive = download_entry( - "tk-windows-bin-8612", BUILD, local_name="tk-windows-bin.tar.gz" - ) + # On CPython 3.14+, we use the latest tcl/tk version which has additional + # runtime dependencies, so we are conservative and use the old version + # elsewhere. The old version isn't built for arm64, so we use the new + # version there too + tk_bin_entry = ( + "tk-windows-bin" + if meets_python_minimum_version(python_version, "3.14") or arch == "arm64" + else "tk-windows-bin-8612" + ) + tk_bin_archive = download_entry( + tk_bin_entry, BUILD, local_name="tk-windows-bin.tar.gz" + ) # On CPython 3.14+, zstd is included if meets_python_minimum_version(python_version, "3.14"): @@ -1297,8 +1348,11 @@ def build_cpython( elif arch == "x86": build_platform = "win32" build_directory = "win32" + elif arch == "arm64": + build_platform = "arm64" + build_directory = "arm64" else: - raise ValueError("unhandled arch: %s" % arch) + raise Exception("unhandled architecture: %s" % arch) tempdir_opts = ( {"ignore_cleanup_errors": True} if sys.version_info >= (3, 12) else {} @@ -1332,7 +1386,7 @@ def build_cpython( # We need all the OpenSSL library files in the same directory to appease # install rules. - openssl_arch = {"amd64": "amd64", "x86": "win32"}[arch] + openssl_arch = {"amd64": "amd64", "x86": "win32", "arm64": "arm64"}[arch] openssl_root = td / "openssl" / openssl_arch openssl_bin_path = openssl_root / "bin" openssl_lib_path = openssl_root / "lib" @@ -1346,6 +1400,18 @@ def build_cpython( log("copying %s to %s" % (source, dest)) shutil.copyfile(source, dest) + # Delete the tk nmake helper, it's not needed and links msvc + if tk_bin_entry == "tk-windows-bin": + tcltk_commit: str = DOWNLOADS[tk_bin_entry]["git_commit"] + tcltk_path = td / ("cpython-bin-deps-%s" % tcltk_commit) + ( + tcltk_path + / build_directory + / "lib" + / "nmake" + / "x86_64-w64-mingw32-nmakehlp.exe" + ).unlink() + cpython_source_path = td / ("Python-%s" % python_version) pcbuild_path = cpython_source_path / "PCbuild" @@ -1368,6 +1434,7 @@ def build_cpython( build_directory, python_version=python_version, zlib_entry=zlib_entry, + arch=arch, ) if pgo: @@ -1509,7 +1576,7 @@ def build_cpython( # import their contents. According to # https://github.com/pypa/pip/issues/11146 running pip from a wheel is not # supported. But it has historically worked and is simple. So do this until - # it stops working and we need to switch to running pip from the filesytem. + # it stops working and we need to switch to running pip from the filesystem. pip_env = dict(os.environ) pip_env["PYTHONPATH"] = str(pip_wheel) @@ -1775,7 +1842,7 @@ def main() -> None: ) parser.add_argument( "--windows-sdk-version", - default="10.0.20348.0", + default="10.0.26100.0", help="Windows SDK version to build with", ) @@ -1790,9 +1857,14 @@ def main() -> None: if os.environ.get("Platform") == "x86": target_triple = "i686-pc-windows-msvc" arch = "x86" - else: + elif os.environ.get("Platform") == "arm64": + target_triple = "aarch64-pc-windows-msvc" + arch = "arm64" + elif os.environ.get("Platform") == "x64": target_triple = "x86_64-pc-windows-msvc" arch = "amd64" + else: + raise Exception("unhandled architecture: %s" % os.environ.get("Platform")) # TODO need better dependency checking. diff --git a/docs/building.rst b/docs/building.rst index c6a07e2..605f5f0 100644 --- a/docs/building.rst +++ b/docs/building.rst @@ -87,7 +87,7 @@ Visual Studio 2017 (or later) is required. A compatible Windows SDK is required (10.0.17763.0 as per CPython 3.7.2). * A ``git.exe`` on ``PATH`` (to clone ``libffi`` from source). -* An installation of Cywgin with the ``autoconf``, ``automake``, ``libtool``, +* An installation of Cygwin with the ``autoconf``, ``automake``, ``libtool``, and ``make`` packages installed. (``libffi`` build dependency.) To build a dynamically linked Python distribution for Windows x64:: diff --git a/docs/distributions.rst b/docs/distributions.rst index 3dd6125..16fb238 100644 --- a/docs/distributions.rst +++ b/docs/distributions.rst @@ -112,7 +112,7 @@ python_implementation_cache_tag (Version 5 or above only.) python_implementation_hex_version - Hexidecimal expression of implementation version. + Hexadecimal expression of implementation version. This is the value exposed by ``sys.implementation.hexversion``. @@ -237,7 +237,7 @@ python_suffixes (Version 5 or above only.) python_bytecode_magic_number - Magic number to use for bytecode files, expressed as a hexidecimal + Magic number to use for bytecode files, expressed as a hexadecimal string. (Version 5 or above only.) @@ -388,8 +388,8 @@ license_path tcl_library_path Relative path to location of tcl library files. The path should be a directory tree containing tcl files to support the tkinter extension. - This will include a subset of the library files provided by the tcl, tk, - and tix packages. + This will include a subset of the library files provided by the tcl + and tk packages. This points to the root directory containing tcl resources. Actual tcl resources are in sub-directories underneath, as identified by diff --git a/docs/quirks.rst b/docs/quirks.rst index 8900cd6..84b2e1e 100644 --- a/docs/quirks.rst +++ b/docs/quirks.rst @@ -71,18 +71,21 @@ ncurses/libedit/readline are loaded. .. _quirk_macos_no_tix: -No tix on macOS -=============== +No tix on UNIX +============== + +Tix is an old widget library for Tcl/Tk. Python previously had a wrapper +for it in ``tkinter.tix``, but it was deprecated in Python 3.6 (the +recommendation is to use ``tkinter.ttk``) and removed in Python 3.13. -macOS distributions do not contain tix tcl support files. This means that -``tkinter.tix`` module functionality will likely break at run-time. The -module will import fine. But attempting to instantiate a ``tkinter.tix.Tk`` -instance or otherwise attempt to run tix tcl files will result in a run-time -error. +The macOS and Linux distributions from this project do not build and +ship Tix, even for Python versions 3.12 and below. -``tkinter.tix`` has been deprecated since Python 3.6 and the official Python -macOS installers do not ship the tix support files. So this project behaves -similarly to the official CPython distributions. +We had previously attempted to ship Tix support on Linux, but it was +broken and nobody reported an issue about it. The macOS distributions +from this project never shipped support for Tix. The official Python.org +macOS installers and Apple's build of Python do not ship support for +Tix, either, so this project behaves similarly to those distributions. .. _quirk_windows_no_pip: @@ -139,64 +142,6 @@ Some functionality may behave subtly differently as a result of our choice to link ``libedit`` by default. (We choose ``libedit`` by default to avoid GPL licensing requirements of ``readline``.) -.. _quirk_linux_libx11: - -Static Linking of ``libX11`` / Incompatibility with PyQt on Linux -================================================================= - -The ``_tkinter`` Python extension module in the Python standard library -statically links against ``libX11``, ``libxcb``, and ``libXau`` on Linux. -In addition, the ``_tkinter`` extension module is statically linked into -``libpython`` and isn't a standalone shared library file. This effectively -means that all these X11 libraries are statically linked into the main -Python interpreter. - -On typical builds of Python on Linux, ``_tkinter`` will link against -external shared libraries. e.g.:: - - $ ldd /usr/lib/python3.9/lib-dynload/_tkinter.cpython-39-x86_64-linux-gnu.so - linux-vdso.so.1 (0x00007fff3be9d000) - libBLT.2.5.so.8.6 => /lib/libBLT.2.5.so.8.6 (0x00007fdb6a6f8000) - libtk8.6.so => /lib/x86_64-linux-gnu/libtk8.6.so (0x00007fdb6a584000) - libtcl8.6.so => /lib/x86_64-linux-gnu/libtcl8.6.so (0x00007fdb6a3c1000) - libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdb6a1d5000) - libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007fdb6a097000) - libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdb69f49000) - libXft.so.2 => /lib/x86_64-linux-gnu/libXft.so.2 (0x00007fdb69f2e000) - libfontconfig.so.1 => /lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007fdb69ee6000) - libXss.so.1 => /lib/x86_64-linux-gnu/libXss.so.1 (0x00007fdb69ee1000) - libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fdb69eda000) - libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fdb69ebe000) - libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fdb69e9c000) - /lib64/ld-linux-x86-64.so.2 (0x00007fdb6a892000) - libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007fdb69e70000) - libfreetype.so.6 => /lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007fdb69dad000) - libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007fdb69da0000) - libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007fdb69d71000) - libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007fdb69d68000) - libXext.so.6 => /lib/x86_64-linux-gnu/libXext.so.6 (0x00007fdb69d53000) - libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007fdb69d4b000) - libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007fdb69d43000) - libpng16.so.16 => /lib/x86_64-linux-gnu/libpng16.so.16 (0x00007fdb69d08000) - libbrotlidec.so.1 => /lib/x86_64-linux-gnu/libbrotlidec.so.1 (0x00007fdb69cfa000) - libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007fdb69ce2000) - libbrotlicommon.so.1 => /lib/x86_64-linux-gnu/libbrotlicommon.so.1 (0x00007fdb69cbd000) - libmd.so.0 => /lib/x86_64-linux-gnu/libmd.so.0 (0x00007fdb69cb0000) - -The static linking of ``libX11`` and other libraries can cause problems when -3rd party Python extension modules also loading similar libraries are also -loaded into the process. For example, extension modules associated with ``PyQt`` -are known to link against a shared ``libX11.so.6``. If multiple versions of -``libX11`` are loaded into the same process, run-time crashes / segfaults can -occur. See e.g. https://github.com/astral-sh/python-build-standalone/issues/95. - -The conceptual workaround is to not statically link ``libX11`` and similar -libraries into ``libpython``. However, this requires re-linking a custom -``libpython`` without ``_tkinter``. It is possible to do this with the object -files included in the distributions. But there isn't a turnkey way to do this. -And you can't easily remove ``_tkinter`` and its symbols from the pre-built -and ready-to-use Python install included in this project's distribution -artifacts. .. _quirk_references_to_build_paths: @@ -251,6 +196,7 @@ make distributions more portable, please file a GitHub issue. .. _quirk_former: .. _quirk_missing_libcrypt: +.. _quirk_linux_libx11: Former quirks ============= @@ -280,4 +226,13 @@ been resolved. New in Python 3.13`_ about third-party replacements for the ``crypt`` module. +* "Static Linking of ``libX11`` / Incompatibility with PyQt on Linux": + The 20220318 release and earlier exported dynamic symbols for the + internal, statically-linked build of ``libX11`` and other libraries. + These would cause conflicts and potential crashes when using + third-party extension modules such as PyQt that load an actual shared + ``libX11`` library (usually provided by your OS). Starting with the + 20220502 release, symbols from internal dependencies are no longer + exported. + .. _What's New in Python 3.13: https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-pep594 diff --git a/docs/status.rst b/docs/status.rst index ef172e0..cd50e07 100644 --- a/docs/status.rst +++ b/docs/status.rst @@ -285,7 +285,7 @@ test_spwd test_startfile object has no attribute 'startfile' test_tix - cannot run without OS X gui process + tix is not built by this project test_tk cannot run without OS X gui process test_ttk_guionly diff --git a/pythonbuild/cpython.py b/pythonbuild/cpython.py index f339037..bd7213b 100644 --- a/pythonbuild/cpython.py +++ b/pythonbuild/cpython.py @@ -69,6 +69,7 @@ "properties": { "name": {"type": "string"}, "targets": {"type": "array", "items": {"type": "string"}}, + "build-mode": {"type": "string"}, }, "additionalProperties": False, }, @@ -535,7 +536,17 @@ def derive_setup_local( python_version, entry.get("maximum-python-version", "100.0") ) - if target_match and (python_min_match and python_max_match): + if build_mode := entry.get("build-mode"): + build_mode_match = section == build_mode + else: + build_mode_match = True + + if ( + target_match + and python_min_match + and python_max_match + and build_mode_match + ): if source := entry.get("source"): line += f" {source}" for source in entry.get("sources", []): @@ -672,7 +683,7 @@ def derive_setup_local( } -RE_INITTAB_ENTRY = re.compile('\{"([^"]+)", ([^\}]+)\},') +RE_INITTAB_ENTRY = re.compile(r'\{"([^"]+)", ([^\}]+)\},') def parse_config_c(s: str): diff --git a/pythonbuild/docker.py b/pythonbuild/docker.py index 4269b2b..0be78e4 100644 --- a/pythonbuild/docker.py +++ b/pythonbuild/docker.py @@ -29,8 +29,10 @@ def write_dockerfiles(source_dir: pathlib.Path, dest_dir: pathlib.Path): write_if_different(dest_dir / f, data.encode("utf-8")) -def build_docker_image(client, image_data: bytes, image_dir: pathlib.Path, name): - image_path = image_dir / ("image-%s" % name) +def build_docker_image( + client, image_data: bytes, image_dir: pathlib.Path, name, host_platform +): + image_path = image_dir / f"image-{name}.{host_platform}" return ensure_docker_image(client, io.BytesIO(image_data), image_path=image_path) @@ -66,11 +68,14 @@ def ensure_docker_image(client, fh, image_path=None): return image -def get_image(client, source_dir: pathlib.Path, image_dir: pathlib.Path, name): +def get_image( + client, source_dir: pathlib.Path, image_dir: pathlib.Path, name, host_platform +): if client is None: return None - image_path = image_dir / ("image-%s" % name) + image_name = f"image-{name}.{host_platform}" + image_path = image_dir / image_name tar_path = image_path.with_suffix(".tar") with image_path.open("r") as fh: @@ -88,7 +93,9 @@ def get_image(client, source_dir: pathlib.Path, image_dir: pathlib.Path, name): return image_id else: - return build_docker_image(client, str(source_dir).encode(), image_dir, name) + return build_docker_image( + client, str(source_dir).encode(), image_dir, name, host_platform + ) def copy_file_to_container(path, container, container_path, archive_path=None): diff --git a/pythonbuild/downloads.py b/pythonbuild/downloads.py index f59afd8..e1562c0 100644 --- a/pythonbuild/downloads.py +++ b/pythonbuild/downloads.py @@ -73,19 +73,19 @@ "python_tag": "cp312", }, "cpython-3.13": { - "url": "https://www.python.org/ftp/python/3.13.5/Python-3.13.5.tar.xz", - "size": 22856016, - "sha256": "93e583f243454e6e9e4588ca2c2662206ad961659863277afcdb96801647d640", - "version": "3.13.5", + "url": "https://www.python.org/ftp/python/3.13.7/Python-3.13.7.tar.xz", + "size": 22769492, + "sha256": "5462f9099dfd30e238def83c71d91897d8caa5ff6ebc7a50f14d4802cdaaa79a", + "version": "3.13.7", "licenses": ["Python-2.0", "CNRI-Python"], "license_file": "LICENSE.cpython.txt", "python_tag": "cp313", }, "cpython-3.14": { - "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0b2.tar.xz", - "size": 23579860, - "sha256": "7ac9e84844bbc0a5a8f1f79a37a68b3b8caf2a58b4aa5999c49227cb36e70ea6", - "version": "3.14.0b2", + "url": "https://www.python.org/ftp/python/3.14.0/Python-3.14.0rc2.tar.xz", + "size": 23566140, + "sha256": "bc62854cf232345bd22c9091a68464e01e056c6473a3fffa84572c8a342da656", + "version": "3.14.0rc2", "licenses": ["Python-2.0", "CNRI-Python"], "license_file": "LICENSE.cpython.txt", "python_tag": "cp314", @@ -172,6 +172,13 @@ "version": "14.0.3+20220508", }, # Remember to update LLVM_URL in src/release.rs whenever upgrading. + "llvm-20-aarch64-linux": { + "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-gnu_only-aarch64-unknown-linux-gnu.tar.zst", + "size": 255946687, + "sha256": "e70753f294b8f83fffbaf07af36857c27ceaef0291cb10f724ada6af11b0a5bc", + "version": "20.1.4+20250511", + }, + # Remember to update LLVM_URL in src/release.rs whenever upgrading. "llvm-20-x86_64-linux": { "url": "https://github.com/indygreg/toolchain-tools/releases/download/toolchain-bootstrap%2F20250511/llvm-20.1.4+20250511-gnu_only-x86_64-unknown-linux-gnu.tar.zst", "size": 299883811, @@ -288,11 +295,11 @@ }, # Remember to update verify_distribution.py when version changed. "sqlite": { - "url": "https://www.sqlite.org/2024/sqlite-autoconf-3470100.tar.gz", - "size": 3328564, - "sha256": "416a6f45bf2cacd494b208fdee1beda509abda951d5f47bc4f2792126f01b452", - "version": "3470100", - "actual_version": "3.47.1.0", + "url": "https://www.sqlite.org/2025/sqlite-autoconf-3500400.tar.gz", + "size": 3173050, + "sha256": "a3db587a1b92ee5ddac2f66b3edb41b26f9c867275782d46c3a088977d6a5b18", + "version": "3500400", + "actual_version": "3.50.4.0", "library_names": ["sqlite3"], "licenses": [], "license_file": "LICENSE.sqlite.txt", @@ -372,10 +379,10 @@ "license_file": "LICENSE.libuuid.txt", }, "x11-util-macros": { - "url": "https://www.x.org/archive/individual/util/util-macros-1.20.1.tar.gz", - "size": 105481, - "sha256": "b373f72887b1394ce2193180a60cb0d1fb8b17bc96ddd770cfd7a808cb489a15", - "version": "1.20.1", + "url": "https://www.x.org/archive/individual/util/util-macros-1.20.2.tar.gz", + "size": 105410, + "sha256": "f642f8964d81acdf06653fdf9dbc210c43ce4bd308bd644a8d573148d0ced76b", + "version": "1.20.2", }, "xcb-proto": { "url": "https://xcb.freedesktop.org/dist/xcb-proto-1.17.0.tar.xz", @@ -383,19 +390,17 @@ "sha256": "2c1bacd2110f4799f74de6ebb714b94cf6f80fb112316b1219480fd22562148c", "version": "1.17.0", }, - # Newer versions from at least 2023 have build failures for reasons we haven't - # fully investigated. "xorgproto": { - "url": "https://www.x.org/archive/individual/proto/xorgproto-2019.1.tar.gz", - "size": 1119813, - "sha256": "38ad1d8316515785d53c5162b4b7022918e03c11d72a5bd9df0a176607f42bca", - "version": "2019.1", + "url": "https://www.x.org/archive/individual/proto/xorgproto-2024.1.tar.gz", + "size": 1115486, + "sha256": "4f6b9b4faf91e5df8265b71843a91fc73dc895be6210c84117a996545df296ce", + "version": "2024.1", }, "xtrans": { - "url": "https://www.x.org/archive/individual/lib/xtrans-1.5.0.tar.gz", - "size": 230197, - "sha256": "a806f8a92f879dcd0146f3f1153fdffe845f2fc0df9b1a26c19312b7b0a29c86", - "version": "1.5.0", + "url": "https://www.x.org/archive/individual/lib/xtrans-1.6.0.tar.gz", + "size": 239113, + "sha256": "936b74c60b19c317c3f3cb1b114575032528dbdaf428740483200ea874c2ca0a", + "version": "1.6.0", }, # IMPORTANT: xz 5.6 has a backdoor. Be extremely cautious before taking any xz # upgrade since it isn't clear which versions are safe. diff --git a/pythonbuild/utils.py b/pythonbuild/utils.py index a8132ca..9e581c5 100644 --- a/pythonbuild/utils.py +++ b/pythonbuild/utils.py @@ -39,6 +39,8 @@ def current_host_platform() -> str: if sys.platform == "linux": if machine == "x86_64": return "linux_x86_64" + elif machine == "aarch64": + return "linux_aarch64" else: raise Exception(f"unsupported Linux host platform: {machine}") elif sys.platform == "darwin": @@ -57,6 +59,8 @@ def default_target_triple() -> str: host = current_host_platform() if host == "linux_x86_64": return "x86_64-unknown-linux-gnu" + elif host == "linux_aarch64": + return "aarch64-unknown-linux-gnu" elif host == "macos_arm64": return "aarch64-apple-darwin" elif host == "macos_x86_64": @@ -84,6 +88,8 @@ def supported_targets(yaml_path: pathlib.Path): for host_platform in settings["host_platforms"]: if sys.platform == "linux" and host_platform == "linux_x86_64": targets.add(target) + elif sys.platform == "linux" and host_platform == "linux_aarch64": + targets.add(target) elif sys.platform == "darwin" and host_platform.startswith("macos_"): targets.add(target) @@ -194,7 +200,13 @@ def write_triples_makefiles( image_suffix = settings.get("docker_image_suffix", "") + # On cross builds, we can just use the bare `gcc` image + gcc_image_suffix = ( + image_suffix if not image_suffix.startswith(".cross") else "" + ) + lines.append("DOCKER_IMAGE_BUILD := build%s\n" % image_suffix) + lines.append("DOCKER_IMAGE_GCC := gcc%s\n" % gcc_image_suffix) entry = clang_toolchain(host_platform, triple) lines.append( @@ -470,6 +482,8 @@ def clang_toolchain(host_platform: str, target_triple: str) -> str: return "llvm-14-x86_64-linux" else: return "llvm-20-x86_64-linux" + elif host_platform == "linux_aarch64": + return "llvm-20-aarch64-linux" elif host_platform == "macos_arm64": return "llvm-aarch64-macos" elif host_platform == "macos_x86_64": @@ -639,21 +653,22 @@ def validate_python_json(info, extension_modules): def release_download_statistics(mode="by_asset"): - with urllib.request.urlopen( - "https://api.github.com/repos/astral-sh/python-build-standalone/releases" - ) as fh: - data = json.load(fh) + import github by_tag = collections.Counter() by_build = collections.Counter() by_build_install_only = collections.Counter() - for release in data: - tag = release["tag_name"] + # Default paging settings time out. Reduce page size as a workaround. + gh = github.Github(per_page=5) + + repo = gh.get_repo("astral-sh/python-build-standalone") + for release in repo.get_releases(): + tag = release.tag_name - for asset in release["assets"]: - name = asset["name"] - count = asset["download_count"] + for asset in release.assets: + name = asset.name + count = asset.download_count by_tag[tag] += count diff --git a/requirements.dev.in b/requirements.dev.in index 2f64d57..b06a90a 100644 --- a/requirements.dev.in +++ b/requirements.dev.in @@ -2,6 +2,7 @@ ruff mypy +PyGithub types-jsonschema types-PyYAML types-jinja2 diff --git a/requirements.dev.txt b/requirements.dev.txt index 68171eb..3ab1146 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -13,6 +13,78 @@ certifi==2024.12.14 \ # via # -r requirements.txt # requests +cffi==1.17.1 \ + --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \ + --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ + --hash=sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1 \ + --hash=sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15 \ + --hash=sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36 \ + --hash=sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824 \ + --hash=sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8 \ + --hash=sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36 \ + --hash=sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17 \ + --hash=sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf \ + --hash=sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc \ + --hash=sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3 \ + --hash=sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed \ + --hash=sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702 \ + --hash=sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1 \ + --hash=sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8 \ + --hash=sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903 \ + --hash=sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6 \ + --hash=sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d \ + --hash=sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b \ + --hash=sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e \ + --hash=sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be \ + --hash=sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c \ + --hash=sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683 \ + --hash=sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9 \ + --hash=sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c \ + --hash=sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8 \ + --hash=sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1 \ + --hash=sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4 \ + --hash=sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655 \ + --hash=sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67 \ + --hash=sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595 \ + --hash=sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0 \ + --hash=sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65 \ + --hash=sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41 \ + --hash=sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6 \ + --hash=sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401 \ + --hash=sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6 \ + --hash=sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3 \ + --hash=sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16 \ + --hash=sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93 \ + --hash=sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e \ + --hash=sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4 \ + --hash=sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964 \ + --hash=sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c \ + --hash=sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576 \ + --hash=sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0 \ + --hash=sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3 \ + --hash=sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662 \ + --hash=sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3 \ + --hash=sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff \ + --hash=sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5 \ + --hash=sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd \ + --hash=sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f \ + --hash=sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5 \ + --hash=sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14 \ + --hash=sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d \ + --hash=sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9 \ + --hash=sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7 \ + --hash=sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382 \ + --hash=sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a \ + --hash=sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e \ + --hash=sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a \ + --hash=sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4 \ + --hash=sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99 \ + --hash=sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87 \ + --hash=sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b + # via + # -r requirements.txt + # cryptography + # pynacl charset-normalizer==3.4.1 \ --hash=sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537 \ --hash=sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa \ @@ -109,6 +181,53 @@ charset-normalizer==3.4.1 \ # via # -r requirements.txt # requests +cryptography==45.0.5 \ + --hash=sha256:0027d566d65a38497bc37e0dd7c2f8ceda73597d2ac9ba93810204f56f52ebc7 \ + --hash=sha256:101ee65078f6dd3e5a028d4f19c07ffa4dd22cce6a20eaa160f8b5219911e7d8 \ + --hash=sha256:12e55281d993a793b0e883066f590c1ae1e802e3acb67f8b442e721e475e6463 \ + --hash=sha256:14d96584701a887763384f3c47f0ca7c1cce322aa1c31172680eb596b890ec30 \ + --hash=sha256:1e1da5accc0c750056c556a93c3e9cb828970206c68867712ca5805e46dc806f \ + --hash=sha256:206210d03c1193f4e1ff681d22885181d47efa1ab3018766a7b32a7b3d6e6afd \ + --hash=sha256:2089cc8f70a6e454601525e5bf2779e665d7865af002a5dec8d14e561002e135 \ + --hash=sha256:3a264aae5f7fbb089dbc01e0242d3b67dffe3e6292e1f5182122bdf58e65215d \ + --hash=sha256:3af26738f2db354aafe492fb3869e955b12b2ef2e16908c8b9cb928128d42c57 \ + --hash=sha256:3fcfbefc4a7f332dece7272a88e410f611e79458fab97b5efe14e54fe476f4fd \ + --hash=sha256:460f8c39ba66af7db0545a8c6f2eabcbc5a5528fc1cf6c3fa9a1e44cec33385e \ + --hash=sha256:57c816dfbd1659a367831baca4b775b2a5b43c003daf52e9d57e1d30bc2e1b0e \ + --hash=sha256:5aa1e32983d4443e310f726ee4b071ab7569f58eedfdd65e9675484a4eb67bd1 \ + --hash=sha256:6ff8728d8d890b3dda5765276d1bc6fb099252915a2cd3aff960c4c195745dd0 \ + --hash=sha256:7259038202a47fdecee7e62e0fd0b0738b6daa335354396c6ddebdbe1206af2a \ + --hash=sha256:72e76caa004ab63accdf26023fccd1d087f6d90ec6048ff33ad0445abf7f605a \ + --hash=sha256:7760c1c2e1a7084153a0f68fab76e754083b126a47d0117c9ed15e69e2103492 \ + --hash=sha256:8c4a6ff8a30e9e3d38ac0539e9a9e02540ab3f827a3394f8852432f6b0ea152e \ + --hash=sha256:9024beb59aca9d31d36fcdc1604dd9bbeed0a55bface9f1908df19178e2f116e \ + --hash=sha256:90cb0a7bb35959f37e23303b7eed0a32280510030daba3f7fdfbb65defde6a97 \ + --hash=sha256:91098f02ca81579c85f66df8a588c78f331ca19089763d733e34ad359f474174 \ + --hash=sha256:926c3ea71a6043921050eaa639137e13dbe7b4ab25800932a8498364fc1abec9 \ + --hash=sha256:982518cd64c54fcada9d7e5cf28eabd3ee76bd03ab18e08a48cad7e8b6f31b18 \ + --hash=sha256:9b4cf6318915dccfe218e69bbec417fdd7c7185aa7aab139a2c0beb7468c89f0 \ + --hash=sha256:ad0caded895a00261a5b4aa9af828baede54638754b51955a0ac75576b831b27 \ + --hash=sha256:b85980d1e345fe769cfc57c57db2b59cff5464ee0c045d52c0df087e926fbe63 \ + --hash=sha256:b8fa8b0a35a9982a3c60ec79905ba5bb090fc0b9addcfd3dc2dd04267e45f25e \ + --hash=sha256:b9e38e0a83cd51e07f5a48ff9691cae95a79bea28fe4ded168a8e5c6c77e819d \ + --hash=sha256:bd4c45986472694e5121084c6ebbd112aa919a25e783b87eb95953c9573906d6 \ + --hash=sha256:be97d3a19c16a9be00edf79dca949c8fa7eff621763666a145f9f9535a5d7f42 \ + --hash=sha256:c648025b6840fe62e57107e0a25f604db740e728bd67da4f6f060f03017d5097 \ + --hash=sha256:d05a38884db2ba215218745f0781775806bde4f32e07b135348355fe8e4991d9 \ + --hash=sha256:dd420e577921c8c2d31289536c386aaa30140b473835e97f83bc71ea9d2baf2d \ + --hash=sha256:e357286c1b76403dd384d938f93c46b2b058ed4dfcdce64a770f0537ed3feb6f \ + --hash=sha256:e6c00130ed423201c5bc5544c23359141660b07999ad82e34e7bb8f882bb78e0 \ + --hash=sha256:e74d30ec9c7cb2f404af331d5b4099a9b322a8a6b25c4632755c8757345baac5 \ + --hash=sha256:f3562c2f23c612f2e4a6964a61d942f891d29ee320edb62ff48ffb99f3de9ae8 + # via + # -r requirements.txt + # pyjwt +deprecated==1.2.18 \ + --hash=sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d \ + --hash=sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec + # via + # -r requirements.txt + # pygithub docker==7.1.0 \ --hash=sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c \ --hash=sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0 @@ -198,39 +317,39 @@ markupsafe==3.0.2 \ # via # -r requirements.txt # jinja2 -mypy==1.16.0 \ - --hash=sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c \ - --hash=sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff \ - --hash=sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93 \ - --hash=sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0 \ - --hash=sha256:15486beea80be24ff067d7d0ede673b001d0d684d0095803b3e6e17a886a2a92 \ - --hash=sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031 \ - --hash=sha256:2e7e0ad35275e02797323a5aa1be0b14a4d03ffdb2e5f2b0489fa07b89c67b21 \ - --hash=sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777 \ - --hash=sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b \ - --hash=sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb \ - --hash=sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666 \ - --hash=sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c \ - --hash=sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2 \ - --hash=sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab \ - --hash=sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491 \ - --hash=sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab \ - --hash=sha256:a5fcfdb7318c6a8dd127b14b1052743b83e97a970f0edb6c913211507a255e20 \ - --hash=sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d \ - --hash=sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b \ - --hash=sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52 \ - --hash=sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8 \ - --hash=sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec \ - --hash=sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13 \ - --hash=sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b \ - --hash=sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1 \ - --hash=sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571 \ - --hash=sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730 \ - --hash=sha256:eb5fbc8063cb4fde7787e4c0406aa63094a34a2daf4673f359a1fb64050e9cb2 \ - --hash=sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090 \ - --hash=sha256:f2ed0e0847a80655afa2c121835b848ed101cc7b8d8d6ecc5205aedc732b1436 \ - --hash=sha256:f56236114c425620875c7cf71700e3d60004858da856c6fc78998ffe767b73d3 \ - --hash=sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b +mypy==1.17.0 \ + --hash=sha256:037bc0f0b124ce46bfde955c647f3e395c6174476a968c0f22c95a8d2f589bba \ + --hash=sha256:03ba330b76710f83d6ac500053f7727270b6b8553b0423348ffb3af6f2f7b889 \ + --hash=sha256:0e69db1fb65b3114f98c753e3930a00514f5b68794ba80590eb02090d54a5d4a \ + --hash=sha256:1051df7ec0886fa246a530ae917c473491e9a0ba6938cfd0ec2abc1076495c3e \ + --hash=sha256:15d9d0018237ab058e5de3d8fce61b6fa72cc59cc78fd91f1b474bce12abf496 \ + --hash=sha256:1619a485fd0e9c959b943c7b519ed26b712de3002d7de43154a489a2d0fd817d \ + --hash=sha256:24cfcc1179c4447854e9e406d3af0f77736d631ec87d31c6281ecd5025df625d \ + --hash=sha256:2c41aa59211e49d717d92b3bb1238c06d387c9325d3122085113c79118bebb06 \ + --hash=sha256:3204d773bab5ff4ebbd1f8efa11b498027cd57017c003ae970f310e5b96be8d8 \ + --hash=sha256:3c56f180ff6430e6373db7a1d569317675b0a451caf5fef6ce4ab365f5f2f6c3 \ + --hash=sha256:434ad499ad8dde8b2f6391ddfa982f41cb07ccda8e3c67781b1bfd4e5f9450a8 \ + --hash=sha256:51e455a54d199dd6e931cd7ea987d061c2afbaf0960f7f66deef47c90d1b304d \ + --hash=sha256:63e751f1b5ab51d6f3d219fe3a2fe4523eaa387d854ad06906c63883fde5b1ab \ + --hash=sha256:6ff25d151cc057fdddb1cb1881ef36e9c41fa2a5e78d8dd71bee6e4dcd2bc05b \ + --hash=sha256:73a0ff2dd10337ceb521c080d4147755ee302dcde6e1a913babd59473904615f \ + --hash=sha256:93468cf29aa9a132bceb103bd8475f78cacde2b1b9a94fd978d50d4bdf616c9a \ + --hash=sha256:98189382b310f16343151f65dd7e6867386d3e35f7878c45cfa11383d175d91f \ + --hash=sha256:9d4fe5c72fd262d9c2c91c1117d16aac555e05f5beb2bae6a755274c6eec42be \ + --hash=sha256:b72c34ce05ac3a1361ae2ebb50757fb6e3624032d91488d93544e9f82db0ed6c \ + --hash=sha256:ba06254a5a22729853209550d80f94e28690d5530c661f9416a68ac097b13fc4 \ + --hash=sha256:c004135a300ab06a045c1c0d8e3f10215e71d7b4f5bb9a42ab80236364429937 \ + --hash=sha256:c38876106cb6132259683632b287238858bd58de267d80defb6f418e9ee50658 \ + --hash=sha256:ce4a17920ec144647d448fc43725b5873548b1aae6c603225626747ededf582d \ + --hash=sha256:d30ba01c0f151998f367506fab31c2ac4527e6a7b2690107c7a7f9e3cb419a9c \ + --hash=sha256:d96b196e5c16f41b4f7736840e8455958e832871990c7ba26bf58175e357ed61 \ + --hash=sha256:e5d7ccc08ba089c06e2f5629c660388ef1fee708444f1dee0b9203fa031dee03 \ + --hash=sha256:eafaf8b9252734400f9b77df98b4eee3d2eecab16104680d51341c75702cad70 \ + --hash=sha256:f105f61a5eff52e137fd73bee32958b2add9d9f0a856f17314018646af838e97 \ + --hash=sha256:f773c6d14dcc108a5b141b4456b0871df638eb411a89cd1c0c001fc4a9d08fc8 \ + --hash=sha256:f7fb09d05e0f1c329a36dcd30e27564a3555717cde87301fae4fb542402ddfad \ + --hash=sha256:f8e08de6138043108b3b18f09d3f817a4783912e48828ab397ecf183135d84d6 \ + --hash=sha256:f986f1cab8dbec39ba6e0eaa42d4d3ac6686516a5d3dccd64be095db05ebc6bb # via -r requirements.dev.in mypy-extensions==1.0.0 \ --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ @@ -240,6 +359,38 @@ pathspec==0.12.1 \ --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \ --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712 # via mypy +pycparser==2.22 \ + --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ + --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc + # via + # -r requirements.txt + # cffi +pygithub==2.6.1 \ + --hash=sha256:6f2fa6d076ccae475f9fc392cc6cdbd54db985d4f69b8833a28397de75ed6ca3 \ + --hash=sha256:b5c035392991cca63959e9453286b41b54d83bf2de2daa7d7ff7e4312cebf3bf + # via + # -r requirements.dev.in + # -r requirements.txt +pyjwt==2.10.1 \ + --hash=sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953 \ + --hash=sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb + # via + # -r requirements.txt + # pygithub +pynacl==1.5.0 \ + --hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \ + --hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \ + --hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \ + --hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \ + --hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \ + --hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \ + --hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \ + --hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \ + --hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \ + --hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543 + # via + # -r requirements.txt + # pygithub pyyaml==6.0.2 \ --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ @@ -309,6 +460,7 @@ requests==2.32.3 \ # via # -r requirements.txt # docker + # pygithub rpds-py==0.22.3 \ --hash=sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518 \ --hash=sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059 \ @@ -417,25 +569,25 @@ rpds-py==0.22.3 \ # -r requirements.txt # jsonschema # referencing -ruff==0.11.13 \ - --hash=sha256:1808b3ed53e1a777c2ef733aca9051dc9bf7c99b26ece15cb59a0320fbdbd629 \ - --hash=sha256:26816a218ca6ef02142343fd24c70f7cd8c5aa6c203bca284407adf675984432 \ - --hash=sha256:26fa247dc68d1d4e72c179e08889a25ac0c7ba4d78aecfc835d49cbfd60bf514 \ - --hash=sha256:29c3189895a8a6a657b7af4e97d330c8a3afd2c9c8f46c81e2fc5a31866517e3 \ - --hash=sha256:4a9ddd3ec62a9a89578c85842b836e4ac832d4a2e0bfaad3b02243f930ceafcc \ - --hash=sha256:4bdfbf1240533f40042ec00c9e09a3aade6f8c10b6414cf11b519488d2635d46 \ - --hash=sha256:4ffbc82d70424b275b089166310448051afdc6e914fdab90e08df66c43bb5ca9 \ - --hash=sha256:51c3f95abd9331dc5b87c47ac7f376db5616041173826dfd556cfe3d4977f492 \ - --hash=sha256:53b15a9dfdce029c842e9a5aebc3855e9ab7771395979ff85b7c1dedb53ddc2b \ - --hash=sha256:55e4bc3a77842da33c16d55b32c6cac1ec5fb0fbec9c8c513bdce76c4f922165 \ - --hash=sha256:633bf2c6f35678c56ec73189ba6fa19ff1c5e4807a78bf60ef487b9dd272cc71 \ - --hash=sha256:6c51f93029d54a910d3d24f7dd0bb909e31b6cd989a5e4ac513f4eb41629f0dc \ - --hash=sha256:96c27935418e4e8e77a26bb05962817f28b8ef3843a6c6cc49d8783b5507f250 \ - --hash=sha256:ab153241400789138d13f362c43f7edecc0edfffce2afa6a68434000ecd8f69a \ - --hash=sha256:aef9c9ed1b5ca28bb15c7eac83b8670cf3b20b478195bd49c8d756ba0a36cf48 \ - --hash=sha256:b4385285e9179d608ff1d2fb9922062663c658605819a6876d8beef0c30b7f3b \ - --hash=sha256:d237a496e0778d719efb05058c64d28b757c77824e04ffe8796c7436e26712b7 \ - --hash=sha256:d28ce58b5ecf0f43c1b71edffabe6ed7f245d5336b17805803312ec9bc665933 +ruff==0.12.4 \ + --hash=sha256:0618ec4442a83ab545e5b71202a5c0ed7791e8471435b94e655b570a5031a98e \ + --hash=sha256:0fc426bec2e4e5f4c4f182b9d2ce6a75c85ba9bcdbe5c6f2a74fcb8df437df4b \ + --hash=sha256:13efa16df6c6eeb7d0f091abae50f58e9522f3843edb40d56ad52a5a4a4b6873 \ + --hash=sha256:2abc48f3d9667fdc74022380b5c745873499ff827393a636f7a59da1515e7c57 \ + --hash=sha256:2b2449dc0c138d877d629bea151bee8c0ae3b8e9c43f5fcaafcd0c0d0726b184 \ + --hash=sha256:478fccdb82ca148a98a9ff43658944f7ab5ec41c3c49d77cd99d44da019371a1 \ + --hash=sha256:4de27977827893cdfb1211d42d84bc180fceb7b72471104671c59be37041cf93 \ + --hash=sha256:55c0f4ca9769408d9b9bac530c30d3e66490bd2beb2d3dae3e4128a1f05c7442 \ + --hash=sha256:56e45bb11f625db55f9b70477062e6a1a04d53628eda7784dce6e0f55fd549eb \ + --hash=sha256:a7dea966bcb55d4ecc4cc3270bccb6f87a337326c9dcd3c07d5b97000dbff41c \ + --hash=sha256:a8224cc3722c9ad9044da7f89c4c1ec452aef2cfe3904365025dd2f51daeae0e \ + --hash=sha256:afcfa3ab5ab5dd0e1c39bf286d829e042a15e966b3726eea79528e2e24d8371a \ + --hash=sha256:be0593c69df9ad1465e8a2d10e3defd111fdb62dcd5be23ae2c06da77e8fcffb \ + --hash=sha256:c057ce464b1413c926cdb203a0f858cd52f3e73dcb3270a3318d1630f6395bb3 \ + --hash=sha256:cb0d261dac457ab939aeb247e804125a5d521b21adf27e721895b0d3f83a0d0a \ + --hash=sha256:e64b90d1122dc2713330350626b10d60818930819623abbb56535c6466cce045 \ + --hash=sha256:e9949d01d64fa3672449a51ddb5d7548b33e130240ad418884ee6efa7a229586 \ + --hash=sha256:fe0b9e9eb23736b453143d72d2ceca5db323963330d5b7859d60d101147d461a # via -r requirements.dev.in six==1.17.0 \ --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ @@ -474,16 +626,14 @@ tomli==2.2.1 \ --hash=sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272 \ --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \ --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7 - # via - # -r requirements.txt - # mypy + # via -r requirements.txt types-jinja2==2.11.9 \ --hash=sha256:60a1e21e8296979db32f9374d8a239af4cb541ff66447bb915d8ad398f9c63b2 \ --hash=sha256:dbdc74a40aba7aed520b7e4d89e8f0fe4286518494208b35123bcf084d4b8c81 # via -r requirements.dev.in -types-jsonschema==4.24.0.20250528 \ - --hash=sha256:6a906b5ff73ac11c8d1e0b6c30a9693e1e4e1ab56c56c932b3a7e081b86d187b \ - --hash=sha256:7e28c64e0ae7980eeb158105b20663fc6a6b8f81d5f86ea6614aa0014417bd1e +types-jsonschema==4.25.0.20250720 \ + --hash=sha256:765a3b6144798fe3161fd8cbe570a756ed3e8c0e5adb7c09693eb49faad39dbd \ + --hash=sha256:7d7897c715310d8bf9ae27a2cedba78bbb09e4cad83ce06d2aa79b73a88941df # via -r requirements.dev.in types-markupsafe==1.1.10 \ --hash=sha256:85b3a872683d02aea3a5ac2a8ef590193c344092032f58457287fbf8e06711b1 \ @@ -493,17 +643,104 @@ types-pyyaml==6.0.12.20250516 \ --hash=sha256:8478208feaeb53a34cb5d970c56a7cd76b72659442e733e268a94dc72b2d0530 \ --hash=sha256:9f21a70216fc0fa1b216a8176db5f9e0af6eb35d2f2932acb87689d03a5bf6ba # via -r requirements.dev.in -typing-extensions==4.9.0 \ - --hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \ - --hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd - # via mypy +typing-extensions==4.14.1 \ + --hash=sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36 \ + --hash=sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76 + # via + # -r requirements.txt + # mypy + # pygithub urllib3==2.3.0 \ --hash=sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df \ --hash=sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d # via # -r requirements.txt # docker + # pygithub # requests +wrapt==1.17.2 \ + --hash=sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f \ + --hash=sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c \ + --hash=sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a \ + --hash=sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b \ + --hash=sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555 \ + --hash=sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c \ + --hash=sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b \ + --hash=sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6 \ + --hash=sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8 \ + --hash=sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662 \ + --hash=sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061 \ + --hash=sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998 \ + --hash=sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb \ + --hash=sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62 \ + --hash=sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984 \ + --hash=sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392 \ + --hash=sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2 \ + --hash=sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306 \ + --hash=sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7 \ + --hash=sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3 \ + --hash=sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9 \ + --hash=sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6 \ + --hash=sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192 \ + --hash=sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317 \ + --hash=sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f \ + --hash=sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda \ + --hash=sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563 \ + --hash=sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a \ + --hash=sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f \ + --hash=sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d \ + --hash=sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9 \ + --hash=sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8 \ + --hash=sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82 \ + --hash=sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9 \ + --hash=sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845 \ + --hash=sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82 \ + --hash=sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125 \ + --hash=sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504 \ + --hash=sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b \ + --hash=sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7 \ + --hash=sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc \ + --hash=sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6 \ + --hash=sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40 \ + --hash=sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a \ + --hash=sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3 \ + --hash=sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a \ + --hash=sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72 \ + --hash=sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681 \ + --hash=sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438 \ + --hash=sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae \ + --hash=sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2 \ + --hash=sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb \ + --hash=sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5 \ + --hash=sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a \ + --hash=sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3 \ + --hash=sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8 \ + --hash=sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2 \ + --hash=sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22 \ + --hash=sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72 \ + --hash=sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061 \ + --hash=sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f \ + --hash=sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9 \ + --hash=sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04 \ + --hash=sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98 \ + --hash=sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9 \ + --hash=sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f \ + --hash=sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b \ + --hash=sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925 \ + --hash=sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6 \ + --hash=sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0 \ + --hash=sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9 \ + --hash=sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c \ + --hash=sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991 \ + --hash=sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6 \ + --hash=sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000 \ + --hash=sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb \ + --hash=sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119 \ + --hash=sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b \ + --hash=sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58 + # via + # -r requirements.txt + # deprecated zstandard==0.23.0 \ --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \ --hash=sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916 \ diff --git a/requirements.in b/requirements.in index 0e9ae39..e9159b6 100644 --- a/requirements.in +++ b/requirements.in @@ -1,6 +1,9 @@ docker jinja2 jsonschema +# This does not built on the aarch64-windows runners yet, and is only needed for +# development so we'll just skip it for now. +PyGithub; sys_platform != "win32" or platform_machine != "aarch64" PyYAML # Undeclared dependency in docker 5.0 package. six diff --git a/requirements.txt b/requirements.txt index 2baa344..9ad29ed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,77 @@ certifi==2024.12.14 \ --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \ --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db # via requests +cffi==1.17.1 \ + --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \ + --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ + --hash=sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1 \ + --hash=sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15 \ + --hash=sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36 \ + --hash=sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824 \ + --hash=sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8 \ + --hash=sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36 \ + --hash=sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17 \ + --hash=sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf \ + --hash=sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc \ + --hash=sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3 \ + --hash=sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed \ + --hash=sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702 \ + --hash=sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1 \ + --hash=sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8 \ + --hash=sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903 \ + --hash=sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6 \ + --hash=sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d \ + --hash=sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b \ + --hash=sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e \ + --hash=sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be \ + --hash=sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c \ + --hash=sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683 \ + --hash=sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9 \ + --hash=sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c \ + --hash=sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8 \ + --hash=sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1 \ + --hash=sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4 \ + --hash=sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655 \ + --hash=sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67 \ + --hash=sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595 \ + --hash=sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0 \ + --hash=sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65 \ + --hash=sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41 \ + --hash=sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6 \ + --hash=sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401 \ + --hash=sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6 \ + --hash=sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3 \ + --hash=sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16 \ + --hash=sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93 \ + --hash=sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e \ + --hash=sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4 \ + --hash=sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964 \ + --hash=sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c \ + --hash=sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576 \ + --hash=sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0 \ + --hash=sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3 \ + --hash=sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662 \ + --hash=sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3 \ + --hash=sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff \ + --hash=sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5 \ + --hash=sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd \ + --hash=sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f \ + --hash=sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5 \ + --hash=sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14 \ + --hash=sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d \ + --hash=sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9 \ + --hash=sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7 \ + --hash=sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382 \ + --hash=sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a \ + --hash=sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e \ + --hash=sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a \ + --hash=sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4 \ + --hash=sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99 \ + --hash=sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87 \ + --hash=sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b + # via + # cryptography + # pynacl charset-normalizer==3.4.1 \ --hash=sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537 \ --hash=sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa \ @@ -104,6 +175,49 @@ charset-normalizer==3.4.1 \ --hash=sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00 \ --hash=sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616 # via requests +cryptography==45.0.5 \ + --hash=sha256:0027d566d65a38497bc37e0dd7c2f8ceda73597d2ac9ba93810204f56f52ebc7 \ + --hash=sha256:101ee65078f6dd3e5a028d4f19c07ffa4dd22cce6a20eaa160f8b5219911e7d8 \ + --hash=sha256:12e55281d993a793b0e883066f590c1ae1e802e3acb67f8b442e721e475e6463 \ + --hash=sha256:14d96584701a887763384f3c47f0ca7c1cce322aa1c31172680eb596b890ec30 \ + --hash=sha256:1e1da5accc0c750056c556a93c3e9cb828970206c68867712ca5805e46dc806f \ + --hash=sha256:206210d03c1193f4e1ff681d22885181d47efa1ab3018766a7b32a7b3d6e6afd \ + --hash=sha256:2089cc8f70a6e454601525e5bf2779e665d7865af002a5dec8d14e561002e135 \ + --hash=sha256:3a264aae5f7fbb089dbc01e0242d3b67dffe3e6292e1f5182122bdf58e65215d \ + --hash=sha256:3af26738f2db354aafe492fb3869e955b12b2ef2e16908c8b9cb928128d42c57 \ + --hash=sha256:3fcfbefc4a7f332dece7272a88e410f611e79458fab97b5efe14e54fe476f4fd \ + --hash=sha256:460f8c39ba66af7db0545a8c6f2eabcbc5a5528fc1cf6c3fa9a1e44cec33385e \ + --hash=sha256:57c816dfbd1659a367831baca4b775b2a5b43c003daf52e9d57e1d30bc2e1b0e \ + --hash=sha256:5aa1e32983d4443e310f726ee4b071ab7569f58eedfdd65e9675484a4eb67bd1 \ + --hash=sha256:6ff8728d8d890b3dda5765276d1bc6fb099252915a2cd3aff960c4c195745dd0 \ + --hash=sha256:7259038202a47fdecee7e62e0fd0b0738b6daa335354396c6ddebdbe1206af2a \ + --hash=sha256:72e76caa004ab63accdf26023fccd1d087f6d90ec6048ff33ad0445abf7f605a \ + --hash=sha256:7760c1c2e1a7084153a0f68fab76e754083b126a47d0117c9ed15e69e2103492 \ + --hash=sha256:8c4a6ff8a30e9e3d38ac0539e9a9e02540ab3f827a3394f8852432f6b0ea152e \ + --hash=sha256:9024beb59aca9d31d36fcdc1604dd9bbeed0a55bface9f1908df19178e2f116e \ + --hash=sha256:90cb0a7bb35959f37e23303b7eed0a32280510030daba3f7fdfbb65defde6a97 \ + --hash=sha256:91098f02ca81579c85f66df8a588c78f331ca19089763d733e34ad359f474174 \ + --hash=sha256:926c3ea71a6043921050eaa639137e13dbe7b4ab25800932a8498364fc1abec9 \ + --hash=sha256:982518cd64c54fcada9d7e5cf28eabd3ee76bd03ab18e08a48cad7e8b6f31b18 \ + --hash=sha256:9b4cf6318915dccfe218e69bbec417fdd7c7185aa7aab139a2c0beb7468c89f0 \ + --hash=sha256:ad0caded895a00261a5b4aa9af828baede54638754b51955a0ac75576b831b27 \ + --hash=sha256:b85980d1e345fe769cfc57c57db2b59cff5464ee0c045d52c0df087e926fbe63 \ + --hash=sha256:b8fa8b0a35a9982a3c60ec79905ba5bb090fc0b9addcfd3dc2dd04267e45f25e \ + --hash=sha256:b9e38e0a83cd51e07f5a48ff9691cae95a79bea28fe4ded168a8e5c6c77e819d \ + --hash=sha256:bd4c45986472694e5121084c6ebbd112aa919a25e783b87eb95953c9573906d6 \ + --hash=sha256:be97d3a19c16a9be00edf79dca949c8fa7eff621763666a145f9f9535a5d7f42 \ + --hash=sha256:c648025b6840fe62e57107e0a25f604db740e728bd67da4f6f060f03017d5097 \ + --hash=sha256:d05a38884db2ba215218745f0781775806bde4f32e07b135348355fe8e4991d9 \ + --hash=sha256:dd420e577921c8c2d31289536c386aaa30140b473835e97f83bc71ea9d2baf2d \ + --hash=sha256:e357286c1b76403dd384d938f93c46b2b058ed4dfcdce64a770f0537ed3feb6f \ + --hash=sha256:e6c00130ed423201c5bc5544c23359141660b07999ad82e34e7bb8f882bb78e0 \ + --hash=sha256:e74d30ec9c7cb2f404af331d5b4099a9b322a8a6b25c4632755c8757345baac5 \ + --hash=sha256:f3562c2f23c612f2e4a6964a61d942f891d29ee320edb62ff48ffb99f3de9ae8 + # via pyjwt +deprecated==1.2.18 \ + --hash=sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d \ + --hash=sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec + # via pygithub docker==7.1.0 \ --hash=sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c \ --hash=sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0 @@ -187,6 +301,30 @@ markupsafe==3.0.2 \ --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \ --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50 # via jinja2 +pycparser==2.22 \ + --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ + --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc + # via cffi +pygithub==2.6.1 \ + --hash=sha256:6f2fa6d076ccae475f9fc392cc6cdbd54db985d4f69b8833a28397de75ed6ca3 \ + --hash=sha256:b5c035392991cca63959e9453286b41b54d83bf2de2daa7d7ff7e4312cebf3bf + # via -r requirements.in +pyjwt==2.10.1 \ + --hash=sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953 \ + --hash=sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb + # via pygithub +pynacl==1.5.0 \ + --hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \ + --hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \ + --hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \ + --hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \ + --hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \ + --hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \ + --hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \ + --hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \ + --hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \ + --hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543 + # via pygithub pyyaml==6.0.2 \ --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ @@ -251,7 +389,9 @@ referencing==0.35.1 \ requests==2.32.3 \ --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 - # via docker + # via + # docker + # pygithub rpds-py==0.22.3 \ --hash=sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518 \ --hash=sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059 \ @@ -397,12 +537,100 @@ tomli==2.2.1 \ --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \ --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7 # via -r requirements.in +typing-extensions==4.14.1 \ + --hash=sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36 \ + --hash=sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76 + # via + # -r requirements.in + # pygithub urllib3==2.3.0 \ --hash=sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df \ --hash=sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d # via # docker + # pygithub # requests +wrapt==1.17.2 \ + --hash=sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f \ + --hash=sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c \ + --hash=sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a \ + --hash=sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b \ + --hash=sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555 \ + --hash=sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c \ + --hash=sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b \ + --hash=sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6 \ + --hash=sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8 \ + --hash=sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662 \ + --hash=sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061 \ + --hash=sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998 \ + --hash=sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb \ + --hash=sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62 \ + --hash=sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984 \ + --hash=sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392 \ + --hash=sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2 \ + --hash=sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306 \ + --hash=sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7 \ + --hash=sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3 \ + --hash=sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9 \ + --hash=sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6 \ + --hash=sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192 \ + --hash=sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317 \ + --hash=sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f \ + --hash=sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda \ + --hash=sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563 \ + --hash=sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a \ + --hash=sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f \ + --hash=sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d \ + --hash=sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9 \ + --hash=sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8 \ + --hash=sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82 \ + --hash=sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9 \ + --hash=sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845 \ + --hash=sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82 \ + --hash=sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125 \ + --hash=sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504 \ + --hash=sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b \ + --hash=sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7 \ + --hash=sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc \ + --hash=sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6 \ + --hash=sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40 \ + --hash=sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a \ + --hash=sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3 \ + --hash=sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a \ + --hash=sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72 \ + --hash=sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681 \ + --hash=sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438 \ + --hash=sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae \ + --hash=sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2 \ + --hash=sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb \ + --hash=sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5 \ + --hash=sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a \ + --hash=sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3 \ + --hash=sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8 \ + --hash=sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2 \ + --hash=sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22 \ + --hash=sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72 \ + --hash=sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061 \ + --hash=sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f \ + --hash=sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9 \ + --hash=sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04 \ + --hash=sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98 \ + --hash=sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9 \ + --hash=sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f \ + --hash=sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b \ + --hash=sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925 \ + --hash=sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6 \ + --hash=sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0 \ + --hash=sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9 \ + --hash=sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c \ + --hash=sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991 \ + --hash=sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6 \ + --hash=sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000 \ + --hash=sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb \ + --hash=sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119 \ + --hash=sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b \ + --hash=sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58 + # via deprecated zstandard==0.23.0 \ --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \ --hash=sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916 \ diff --git a/requirements.win-arm64.txt b/requirements.win-arm64.txt new file mode 100644 index 0000000..11b0502 --- /dev/null +++ b/requirements.win-arm64.txt @@ -0,0 +1,571 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile --python-platform aarch64-pc-windows-msvc --generate-hashes requirements.in -o requirements.win-arm64.txt +attrs==25.3.0 \ + --hash=sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3 \ + --hash=sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b + # via + # jsonschema + # referencing +certifi==2025.8.3 \ + --hash=sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407 \ + --hash=sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5 + # via requests +charset-normalizer==3.4.3 \ + --hash=sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91 \ + --hash=sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0 \ + --hash=sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154 \ + --hash=sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601 \ + --hash=sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884 \ + --hash=sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07 \ + --hash=sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c \ + --hash=sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64 \ + --hash=sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe \ + --hash=sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f \ + --hash=sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432 \ + --hash=sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc \ + --hash=sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa \ + --hash=sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9 \ + --hash=sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae \ + --hash=sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19 \ + --hash=sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d \ + --hash=sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e \ + --hash=sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4 \ + --hash=sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7 \ + --hash=sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312 \ + --hash=sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92 \ + --hash=sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31 \ + --hash=sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c \ + --hash=sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f \ + --hash=sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99 \ + --hash=sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b \ + --hash=sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15 \ + --hash=sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392 \ + --hash=sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f \ + --hash=sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8 \ + --hash=sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491 \ + --hash=sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0 \ + --hash=sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc \ + --hash=sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0 \ + --hash=sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f \ + --hash=sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a \ + --hash=sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40 \ + --hash=sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927 \ + --hash=sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849 \ + --hash=sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce \ + --hash=sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14 \ + --hash=sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05 \ + --hash=sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c \ + --hash=sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c \ + --hash=sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a \ + --hash=sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc \ + --hash=sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34 \ + --hash=sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9 \ + --hash=sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096 \ + --hash=sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14 \ + --hash=sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30 \ + --hash=sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b \ + --hash=sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b \ + --hash=sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942 \ + --hash=sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db \ + --hash=sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5 \ + --hash=sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b \ + --hash=sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce \ + --hash=sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669 \ + --hash=sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0 \ + --hash=sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018 \ + --hash=sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93 \ + --hash=sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe \ + --hash=sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049 \ + --hash=sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a \ + --hash=sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef \ + --hash=sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2 \ + --hash=sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca \ + --hash=sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16 \ + --hash=sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f \ + --hash=sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb \ + --hash=sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1 \ + --hash=sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557 \ + --hash=sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37 \ + --hash=sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7 \ + --hash=sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72 \ + --hash=sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c \ + --hash=sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9 + # via requests +docker==7.1.0 \ + --hash=sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c \ + --hash=sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0 + # via -r requirements.in +idna==3.10 \ + --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ + --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 + # via requests +jinja2==3.1.6 \ + --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ + --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + # via -r requirements.in +jsonschema==4.25.0 \ + --hash=sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716 \ + --hash=sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f + # via -r requirements.in +jsonschema-specifications==2025.4.1 \ + --hash=sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af \ + --hash=sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608 + # via jsonschema +markupsafe==3.0.2 \ + --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \ + --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \ + --hash=sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0 \ + --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \ + --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \ + --hash=sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13 \ + --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \ + --hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \ + --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \ + --hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \ + --hash=sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0 \ + --hash=sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b \ + --hash=sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579 \ + --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \ + --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \ + --hash=sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff \ + --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \ + --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \ + --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \ + --hash=sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb \ + --hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \ + --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \ + --hash=sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a \ + --hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \ + --hash=sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a \ + --hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \ + --hash=sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8 \ + --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \ + --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \ + --hash=sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144 \ + --hash=sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f \ + --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \ + --hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \ + --hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \ + --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \ + --hash=sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158 \ + --hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \ + --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \ + --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \ + --hash=sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171 \ + --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \ + --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \ + --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \ + --hash=sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d \ + --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \ + --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \ + --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \ + --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \ + --hash=sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29 \ + --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \ + --hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \ + --hash=sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c \ + --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \ + --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \ + --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \ + --hash=sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a \ + --hash=sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178 \ + --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \ + --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \ + --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \ + --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50 + # via jinja2 +pywin32==311 \ + --hash=sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b \ + --hash=sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151 \ + --hash=sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87 \ + --hash=sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503 \ + --hash=sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d \ + --hash=sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c \ + --hash=sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d \ + --hash=sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31 \ + --hash=sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b \ + --hash=sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a \ + --hash=sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42 \ + --hash=sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2 \ + --hash=sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b \ + --hash=sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee \ + --hash=sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067 \ + --hash=sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd \ + --hash=sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3 \ + --hash=sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91 \ + --hash=sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852 \ + --hash=sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d + # via docker +pyyaml==6.0.2 \ + --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ + --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ + --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \ + --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \ + --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ + --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \ + --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ + --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \ + --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ + --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \ + --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \ + --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \ + --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \ + --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \ + --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \ + --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \ + --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ + --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \ + --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ + --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \ + --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \ + --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \ + --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \ + --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ + --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ + --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \ + --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \ + --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ + --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ + --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \ + --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ + --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \ + --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ + --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \ + --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \ + --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ + --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \ + --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \ + --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \ + --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ + --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ + --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \ + --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ + --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ + --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \ + --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \ + --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \ + --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \ + --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \ + --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ + --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \ + --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \ + --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4 + # via -r requirements.in +referencing==0.36.2 \ + --hash=sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa \ + --hash=sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0 + # via + # jsonschema + # jsonschema-specifications +requests==2.32.4 \ + --hash=sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c \ + --hash=sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422 + # via docker +rpds-py==0.27.0 \ + --hash=sha256:010c4843a3b92b54373e3d2291a7447d6c3fc29f591772cc2ea0e9f5c1da434b \ + --hash=sha256:05284439ebe7d9f5f5a668d4d8a0a1d851d16f7d47c78e1fab968c8ad30cab04 \ + --hash=sha256:0665be515767dc727ffa5f74bd2ef60b0ff85dad6bb8f50d91eaa6b5fb226f51 \ + --hash=sha256:069e0384a54f427bd65d7fda83b68a90606a3835901aaff42185fcd94f5a9295 \ + --hash=sha256:08680820d23df1df0a0260f714d12966bc6c42d02e8055a91d61e03f0c47dda0 \ + --hash=sha256:0954e3a92e1d62e83a54ea7b3fdc9efa5d61acef8488a8a3d31fdafbfb00460d \ + --hash=sha256:09965b314091829b378b60607022048953e25f0b396c2b70e7c4c81bcecf932e \ + --hash=sha256:0c431bfb91478d7cbe368d0a699978050d3b112d7f1d440a41e90faa325557fd \ + --hash=sha256:0f401c369186a5743694dd9fc08cba66cf70908757552e1f714bfc5219c655b5 \ + --hash=sha256:0f4f69d7a4300fbf91efb1fb4916421bd57804c01ab938ab50ac9c4aa2212f03 \ + --hash=sha256:11e8e28c0ba0373d052818b600474cfee2fafa6c9f36c8587d217b13ee28ca7d \ + --hash=sha256:130c1ffa5039a333f5926b09e346ab335f0d4ec393b030a18549a7c7e7c2cea4 \ + --hash=sha256:1321bce595ad70e80f97f998db37356b2e22cf98094eba6fe91782e626da2f71 \ + --hash=sha256:13bbc4846ae4c993f07c93feb21a24d8ec637573d567a924b1001e81c8ae80f9 \ + --hash=sha256:14f028eb47f59e9169bfdf9f7ceafd29dd64902141840633683d0bad5b04ff34 \ + --hash=sha256:15ea4d2e182345dd1b4286593601d766411b43f868924afe297570658c31a62b \ + --hash=sha256:181bc29e59e5e5e6e9d63b143ff4d5191224d355e246b5a48c88ce6b35c4e466 \ + --hash=sha256:183f5e221ba3e283cd36fdfbe311d95cd87699a083330b4f792543987167eff1 \ + --hash=sha256:184f0d7b342967f6cda94a07d0e1fae177d11d0b8f17d73e06e36ac02889f303 \ + --hash=sha256:190d7285cd3bb6d31d37a0534d7359c1ee191eb194c511c301f32a4afa5a1dd4 \ + --hash=sha256:19c990fdf5acecbf0623e906ae2e09ce1c58947197f9bced6bbd7482662231c4 \ + --hash=sha256:1d66f45b9399036e890fb9c04e9f70c33857fd8f58ac8db9f3278cfa835440c3 \ + --hash=sha256:203f581accef67300a942e49a37d74c12ceeef4514874c7cede21b012613ca2c \ + --hash=sha256:20e222a44ae9f507d0f2678ee3dd0c45ec1e930f6875d99b8459631c24058aec \ + --hash=sha256:2406d034635d1497c596c40c85f86ecf2bf9611c1df73d14078af8444fe48031 \ + --hash=sha256:249ab91ceaa6b41abc5f19513cb95b45c6f956f6b89f1fe3d99c81255a849f9e \ + --hash=sha256:25a4aebf8ca02bbb90a9b3e7a463bbf3bee02ab1c446840ca07b1695a68ce424 \ + --hash=sha256:27bac29bbbf39601b2aab474daf99dbc8e7176ca3389237a23944b17f8913d97 \ + --hash=sha256:299a245537e697f28a7511d01038c310ac74e8ea213c0019e1fc65f52c0dcb23 \ + --hash=sha256:2cff9bdd6c7b906cc562a505c04a57d92e82d37200027e8d362518df427f96cd \ + --hash=sha256:2e307cb5f66c59ede95c00e93cd84190a5b7f3533d7953690b2036780622ba81 \ + --hash=sha256:2e39169ac6aae06dd79c07c8a69d9da867cef6a6d7883a0186b46bb46ccfb0c3 \ + --hash=sha256:2fe6e18e5c8581f0361b35ae575043c7029d0a92cb3429e6e596c2cdde251432 \ + --hash=sha256:3001013dae10f806380ba739d40dee11db1ecb91684febb8406a87c2ded23dae \ + --hash=sha256:32196b5a99821476537b3f7732432d64d93a58d680a52c5e12a190ee0135d8b5 \ + --hash=sha256:33ba649a6e55ae3808e4c39e01580dc9a9b0d5b02e77b66bb86ef117922b1264 \ + --hash=sha256:341d8acb6724c0c17bdf714319c393bb27f6d23d39bc74f94221b3e59fc31828 \ + --hash=sha256:343cf24de9ed6c728abefc5d5c851d5de06497caa7ac37e5e65dd572921ed1b5 \ + --hash=sha256:36184b44bf60a480863e51021c26aca3dfe8dd2f5eeabb33622b132b9d8b8b54 \ + --hash=sha256:3841f66c1ffdc6cebce8aed64e36db71466f1dc23c0d9a5592e2a782a3042c79 \ + --hash=sha256:4045e2fc4b37ec4b48e8907a5819bdd3380708c139d7cc358f03a3653abedb89 \ + --hash=sha256:419dd9c98bcc9fb0242be89e0c6e922df333b975d4268faa90d58499fd9c9ebe \ + --hash=sha256:42894616da0fc0dcb2ec08a77896c3f56e9cb2f4b66acd76fc8992c3557ceb1c \ + --hash=sha256:42ccc57ff99166a55a59d8c7d14f1a357b7749f9ed3584df74053fd098243451 \ + --hash=sha256:4300e15e7d03660f04be84a125d1bdd0e6b2f674bc0723bc0fd0122f1a4585dc \ + --hash=sha256:443d239d02d9ae55b74015234f2cd8eb09e59fbba30bf60baeb3123ad4c6d5ff \ + --hash=sha256:44524b96481a4c9b8e6c46d6afe43fa1fb485c261e359fbe32b63ff60e3884d8 \ + --hash=sha256:45d04a73c54b6a5fd2bab91a4b5bc8b426949586e61340e212a8484919183859 \ + --hash=sha256:46f48482c1a4748ab2773f75fffbdd1951eb59794e32788834b945da857c47a8 \ + --hash=sha256:4790c9d5dd565ddb3e9f656092f57268951398cef52e364c405ed3112dc7c7c1 \ + --hash=sha256:4bc262ace5a1a7dc3e2eac2fa97b8257ae795389f688b5adf22c5db1e2431c43 \ + --hash=sha256:4c3f8a0d4802df34fcdbeb3dfe3a4d8c9a530baea8fafdf80816fcaac5379d83 \ + --hash=sha256:5355527adaa713ab693cbce7c1e0ec71682f599f61b128cf19d07e5c13c9b1f1 \ + --hash=sha256:555ed147cbe8c8f76e72a4c6cd3b7b761cbf9987891b9448808148204aed74a5 \ + --hash=sha256:55d42a0ef2bdf6bc81e1cc2d49d12460f63c6ae1423c4f4851b828e454ccf6f1 \ + --hash=sha256:59195dc244fc183209cf8a93406889cadde47dfd2f0a6b137783aa9c56d67c85 \ + --hash=sha256:59714ab0a5af25d723d8e9816638faf7f4254234decb7d212715c1aa71eee7be \ + --hash=sha256:5b3a5c8089eed498a3af23ce87a80805ff98f6ef8f7bdb70bd1b7dae5105f6ac \ + --hash=sha256:5d6790ff400254137b81b8053b34417e2c46921e302d655181d55ea46df58cf7 \ + --hash=sha256:5df559e9e7644d9042f626f2c3997b555f347d7a855a15f170b253f6c5bfe358 \ + --hash=sha256:5fa01b3d5e3b7d97efab65bd3d88f164e289ec323a8c033c5c38e53ee25c007e \ + --hash=sha256:61490d57e82e23b45c66f96184237994bfafa914433b8cd1a9bb57fecfced59d \ + --hash=sha256:6168af0be75bba990a39f9431cdfae5f0ad501f4af32ae62e8856307200517b8 \ + --hash=sha256:64a0fe3f334a40b989812de70160de6b0ec7e3c9e4a04c0bbc48d97c5d3600ae \ + --hash=sha256:64f689ab822f9b5eb6dfc69893b4b9366db1d2420f7db1f6a2adf2a9ca15ad64 \ + --hash=sha256:699c346abc73993962cac7bb4f02f58e438840fa5458a048d3a178a7a670ba86 \ + --hash=sha256:6b96b0b784fe5fd03beffff2b1533dc0d85e92bab8d1b2c24ef3a5dc8fac5669 \ + --hash=sha256:6bde37765564cd22a676dd8101b657839a1854cfaa9c382c5abf6ff7accfd4ae \ + --hash=sha256:6c135708e987f46053e0a1246a206f53717f9fadfba27174a9769ad4befba5c3 \ + --hash=sha256:6c27a7054b5224710fcfb1a626ec3ff4f28bcb89b899148c72873b18210e446b \ + --hash=sha256:6de6a7f622860af0146cb9ee148682ff4d0cea0b8fd3ad51ce4d40efb2f061d0 \ + --hash=sha256:737005088449ddd3b3df5a95476ee1c2c5c669f5c30eed909548a92939c0e12d \ + --hash=sha256:7451ede3560086abe1aa27dcdcf55cd15c96b56f543fb12e5826eee6f721f858 \ + --hash=sha256:7873b65686a6471c0037139aa000d23fe94628e0daaa27b6e40607c90e3f5ec4 \ + --hash=sha256:79af163a4b40bbd8cfd7ca86ec8b54b81121d3b213b4435ea27d6568bcba3e9d \ + --hash=sha256:7aed8118ae20515974650d08eb724150dc2e20c2814bcc307089569995e88a14 \ + --hash=sha256:7cf9bc4508efb18d8dff6934b602324eb9f8c6644749627ce001d6f38a490889 \ + --hash=sha256:7e57906e38583a2cba67046a09c2637e23297618dc1f3caddbc493f2be97c93f \ + --hash=sha256:7ec85994f96a58cf7ed288caa344b7fe31fd1d503bdf13d7331ead5f70ab60d5 \ + --hash=sha256:81f81bbd7cdb4bdc418c09a73809abeda8f263a6bf8f9c7f93ed98b5597af39d \ + --hash=sha256:86aca1616922b40d8ac1b3073a1ead4255a2f13405e5700c01f7c8d29a03972d \ + --hash=sha256:88051c3b7d5325409f433c5a40328fcb0685fc04e5db49ff936e910901d10114 \ + --hash=sha256:887ab1f12b0d227e9260558a4a2320024b20102207ada65c43e1ffc4546df72e \ + --hash=sha256:8a06aa1197ec0281eb1d7daf6073e199eb832fe591ffa329b88bae28f25f5fe5 \ + --hash=sha256:8a1dca5507fa1337f75dcd5070218b20bc68cf8844271c923c1b79dfcbc20391 \ + --hash=sha256:8b23cf252f180cda89220b378d917180f29d313cd6a07b2431c0d3b776aae86f \ + --hash=sha256:8d0e09cf4863c74106b5265c2c310f36146e2b445ff7b3018a56799f28f39f6f \ + --hash=sha256:8de567dec6d451649a781633d36f5c7501711adee329d76c095be2178855b042 \ + --hash=sha256:90fb790138c1a89a2e58c9282fe1089638401f2f3b8dddd758499041bc6e0774 \ + --hash=sha256:92f3b3ec3e6008a1fe00b7c0946a170f161ac00645cde35e3c9a68c2475e8156 \ + --hash=sha256:935afcdea4751b0ac918047a2df3f720212892347767aea28f5b3bf7be4f27c0 \ + --hash=sha256:9a0ff7ee28583ab30a52f371b40f54e7138c52ca67f8ca17ccb7ccf0b383cb5f \ + --hash=sha256:9ad08547995a57e74fea6abaf5940d399447935faebbd2612b3b0ca6f987946b \ + --hash=sha256:9b2a4e17bfd68536c3b801800941c95a1d4a06e3cada11c146093ba939d9638d \ + --hash=sha256:9b78430703cfcf5f5e86eb74027a1ed03a93509273d7c705babb547f03e60016 \ + --hash=sha256:9d0f92b78cfc3b74a42239fdd8c1266f4715b573204c234d2f9fc3fc7a24f185 \ + --hash=sha256:9da162b718b12c4219eeeeb68a5b7552fbc7aadedf2efee440f88b9c0e54b45d \ + --hash=sha256:a00c91104c173c9043bc46f7b30ee5e6d2f6b1149f11f545580f5d6fdff42c0b \ + --hash=sha256:a029be818059870664157194e46ce0e995082ac49926f1423c1f058534d2aaa9 \ + --hash=sha256:a1b3db5fae5cbce2131b7420a3f83553d4d89514c03d67804ced36161fe8b6b2 \ + --hash=sha256:a4cf32a26fa744101b67bfd28c55d992cd19438aff611a46cac7f066afca8fd4 \ + --hash=sha256:aa0bf113d15e8abdfee92aa4db86761b709a09954083afcb5bf0f952d6065fdb \ + --hash=sha256:ab47fe727c13c09d0e6f508e3a49e545008e23bf762a245b020391b621f5b726 \ + --hash=sha256:af22763a0a1eff106426a6e1f13c4582e0d0ad89c1493ab6c058236174cd6c6a \ + --hash=sha256:af9d4fd79ee1cc8e7caf693ee02737daabfc0fcf2773ca0a4735b356c8ad6f7c \ + --hash=sha256:b1fef1f13c842a39a03409e30ca0bf87b39a1e2a305a9924deadb75a43105d23 \ + --hash=sha256:b2eff8ee57c5996b0d2a07c3601fb4ce5fbc37547344a26945dd9e5cbd1ed27a \ + --hash=sha256:b4c4fbbcff474e1e5f38be1bf04511c03d492d42eec0babda5d03af3b5589374 \ + --hash=sha256:b8a4131698b6992b2a56015f51646711ec5d893a0b314a4b985477868e240c87 \ + --hash=sha256:b8a7acf04fda1f30f1007f3cc96d29d8cf0a53e626e4e1655fdf4eabc082d367 \ + --hash=sha256:ba783541be46f27c8faea5a6645e193943c17ea2f0ffe593639d906a327a9bcc \ + --hash=sha256:be0744661afbc4099fef7f4e604e7f1ea1be1dd7284f357924af12a705cc7d5c \ + --hash=sha256:be3964f7312ea05ed283b20f87cb533fdc555b2e428cc7be64612c0b2124f08c \ + --hash=sha256:be806e2961cd390a89d6c3ce8c2ae34271cfcd05660f716257838bb560f1c3b6 \ + --hash=sha256:bec77545d188f8bdd29d42bccb9191682a46fb2e655e3d1fb446d47c55ac3b8d \ + --hash=sha256:c10d92fb6d7fd827e44055fcd932ad93dac6a11e832d51534d77b97d1d85400f \ + --hash=sha256:c3782fb753aa825b4ccabc04292e07897e2fd941448eabf666856c5530277626 \ + --hash=sha256:c9ce7a9e967afc0a2af7caa0d15a3e9c1054815f73d6a8cb9225b61921b419bd \ + --hash=sha256:cb0702c12983be3b2fab98ead349ac63a98216d28dda6f518f52da5498a27a1b \ + --hash=sha256:cbc619e84a5e3ab2d452de831c88bdcad824414e9c2d28cd101f94dbdf26329c \ + --hash=sha256:ce4ed8e0c7dbc5b19352b9c2c6131dd23b95fa8698b5cdd076307a33626b72dc \ + --hash=sha256:ce96ab0bdfcef1b8c371ada2100767ace6804ea35aacce0aef3aeb4f3f499ca8 \ + --hash=sha256:cf824aceaeffff029ccfba0da637d432ca71ab21f13e7f6f5179cd88ebc77a8a \ + --hash=sha256:d2a81bdcfde4245468f7030a75a37d50400ac2455c3a4819d9d550c937f90ab5 \ + --hash=sha256:d2cc2b34f9e1d31ce255174da82902ad75bd7c0d88a33df54a77a22f2ef421ee \ + --hash=sha256:d2f184336bc1d6abfaaa1262ed42739c3789b1e3a65a29916a615307d22ffd2e \ + --hash=sha256:d3c622c39f04d5751408f5b801ecb527e6e0a471b367f420a877f7a660d583f6 \ + --hash=sha256:d7cf5e726b6fa977e428a61880fb108a62f28b6d0c7ef675b117eaff7076df49 \ + --hash=sha256:d85d784c619370d9329bbd670f41ff5f2ae62ea4519761b679d0f57f0f0ee267 \ + --hash=sha256:d93ebdb82363d2e7bec64eecdc3632b59e84bd270d74fe5be1659f7787052f9b \ + --hash=sha256:db8a6313dbac934193fc17fe7610f70cd8181c542a91382531bef5ed785e5615 \ + --hash=sha256:dbc2ab5d10544eb485baa76c63c501303b716a5c405ff2469a1d8ceffaabf622 \ + --hash=sha256:dbd749cff1defbde270ca346b69b3baf5f1297213ef322254bf2a28537f0b046 \ + --hash=sha256:dc662bc9375a6a394b62dfd331874c434819f10ee3902123200dbcf116963f89 \ + --hash=sha256:dc6b0d5a1ea0318ef2def2b6a55dccf1dcaf77d605672347271ed7b829860765 \ + --hash=sha256:dc79d192fb76fc0c84f2c58672c17bbbc383fd26c3cdc29daae16ce3d927e8b2 \ + --hash=sha256:dd2c1d27ebfe6a015cfa2005b7fe8c52d5019f7bbdd801bc6f7499aab9ae739e \ + --hash=sha256:dea0808153f1fbbad772669d906cddd92100277533a03845de6893cadeffc8be \ + --hash=sha256:e0d7151a1bd5d0a203a5008fc4ae51a159a610cb82ab0a9b2c4d80241745582e \ + --hash=sha256:e14aab02258cb776a108107bd15f5b5e4a1bbaa61ef33b36693dfab6f89d54f9 \ + --hash=sha256:e24d8031a2c62f34853756d9208eeafa6b940a1efcbfe36e8f57d99d52bb7261 \ + --hash=sha256:e36c80c49853b3ffda7aa1831bf175c13356b210c73128c861f3aa93c3cc4015 \ + --hash=sha256:e377e4cf8795cdbdff75b8f0223d7b6c68ff4fef36799d88ccf3a995a91c0112 \ + --hash=sha256:e3acb9c16530362aeaef4e84d57db357002dc5cbfac9a23414c3e73c08301ab2 \ + --hash=sha256:e3dc8d4ede2dbae6c0fc2b6c958bf51ce9fd7e9b40c0f5b8835c3fde44f5807d \ + --hash=sha256:e6491658dd2569f05860bad645569145c8626ac231877b0fb2d5f9bcb7054089 \ + --hash=sha256:eb91d252b35004a84670dfeafadb042528b19842a0080d8b53e5ec1128e8f433 \ + --hash=sha256:f0396e894bd1e66c74ecbc08b4f6a03dc331140942c4b1d345dd131b68574a60 \ + --hash=sha256:f09c9d4c26fa79c1bad927efb05aca2391350b8e61c38cbc0d7d3c814e463124 \ + --hash=sha256:f3cd110e02c5bf17d8fb562f6c9df5c20e73029d587cf8602a2da6c5ef1e32cb \ + --hash=sha256:f7a37dd208f0d658e0487522078b1ed68cd6bce20ef4b5a915d2809b9094b410 \ + --hash=sha256:fae4a01ef8c4cb2bbe92ef2063149596907dc4a881a8d26743b3f6b304713171 \ + --hash=sha256:fc327f4497b7087d06204235199daf208fd01c82d80465dc5efa4ec9df1c5b4e \ + --hash=sha256:fcc01c57ce6e70b728af02b2401c5bc853a9e14eb07deda30624374f0aebfe42 \ + --hash=sha256:fde355b02934cc6b07200cc3b27ab0c15870a757d1a72fd401aa92e2ea3c6bfe + # via + # jsonschema + # referencing +six==1.17.0 \ + --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ + --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 + # via -r requirements.in +tomli==2.2.1 \ + --hash=sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6 \ + --hash=sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd \ + --hash=sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c \ + --hash=sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b \ + --hash=sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8 \ + --hash=sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6 \ + --hash=sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77 \ + --hash=sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff \ + --hash=sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea \ + --hash=sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192 \ + --hash=sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249 \ + --hash=sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee \ + --hash=sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4 \ + --hash=sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98 \ + --hash=sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8 \ + --hash=sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4 \ + --hash=sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281 \ + --hash=sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744 \ + --hash=sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69 \ + --hash=sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13 \ + --hash=sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140 \ + --hash=sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e \ + --hash=sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e \ + --hash=sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc \ + --hash=sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff \ + --hash=sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec \ + --hash=sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2 \ + --hash=sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222 \ + --hash=sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106 \ + --hash=sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272 \ + --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \ + --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7 + # via -r requirements.in +typing-extensions==4.14.1 \ + --hash=sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36 \ + --hash=sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76 + # via -r requirements.in +urllib3==2.5.0 \ + --hash=sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760 \ + --hash=sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc + # via + # docker + # requests +zstandard==0.24.0 \ + --hash=sha256:0101f835da7de08375f380192ff75135527e46e3f79bef224e3c49cb640fef6a \ + --hash=sha256:010302face38c9a909b8934e3bf6038266d6afc69523f3efa023c5cb5d38271b \ + --hash=sha256:05d27c953f2e0a3ecc8edbe91d6827736acc4c04d0479672e0400ccdb23d818c \ + --hash=sha256:09887301001e7a81a3618156bc1759e48588de24bddfdd5b7a4364da9a8fbc20 \ + --hash=sha256:0a416814608610abf5488889c74e43ffa0343ca6cf43957c6b6ec526212422da \ + --hash=sha256:0a9e95ceb180ccd12a8b3437bac7e8a8a089c9094e39522900a8917745542184 \ + --hash=sha256:0c9c3cba57f5792532a3df3f895980d47d78eda94b0e5b800651b53e96e0b604 \ + --hash=sha256:0d66da2649bb0af4471699aeb7a83d6f59ae30236fb9f6b5d20fb618ef6c6777 \ + --hash=sha256:0dc5654586613aebe5405c1ba180e67b3f29e7d98cf3187c79efdcc172f39457 \ + --hash=sha256:0ed8345b504df1cab280af923ef69ec0d7d52f7b22f78ec7982fde7c33a43c4f \ + --hash=sha256:0f6d9a146e07458cb41423ca2d783aefe3a3a97fe72838973c13b8f1ecc7343a \ + --hash=sha256:10e284748a7e7fbe2815ca62a9d6e84497d34cfdd0143fa9e8e208efa808d7c4 \ + --hash=sha256:13fc548e214df08d896ee5f29e1f91ee35db14f733fef8eabea8dca6e451d1e2 \ + --hash=sha256:1b14bc92af065d0534856bf1b30fc48753163ea673da98857ea4932be62079b1 \ + --hash=sha256:1bda8a85e5b9d5e73af2e61b23609a8cc1598c1b3b2473969912979205a1ff25 \ + --hash=sha256:1e133a9dd51ac0bcd5fd547ba7da45a58346dbc63def883f999857b0d0c003c4 \ + --hash=sha256:1f578fab202f4df67a955145c3e3ca60ccaaaf66c97808545b2625efeecdef10 \ + --hash=sha256:27b6fa72b57824a3f7901fc9cc4ce1c1c834b28f3a43d1d4254c64c8f11149d4 \ + --hash=sha256:2825a3951f945fb2613ded0f517d402b1e5a68e87e0ee65f5bd224a8333a9a46 \ + --hash=sha256:2fc67eb15ed573950bc6436a04b3faea6c36c7db98d2db030d48391c6736a0dc \ + --hash=sha256:337572a7340e1d92fd7fb5248c8300d0e91071002d92e0b8cabe8d9ae7b58159 \ + --hash=sha256:35f13501a8accf834457d8e40e744568287a215818778bc4d79337af2f3f0d97 \ + --hash=sha256:388aad2d693707f4a0f6cc687eb457b33303d6b57ecf212c8ff4468c34426892 \ + --hash=sha256:3aa3b4344b206941385a425ea25e6dd63e5cb0f535a4b88d56e3f8902086be9e \ + --hash=sha256:3adb4b5414febf074800d264ddf69ecade8c658837a83a19e8ab820e924c9933 \ + --hash=sha256:3b95fc06489aa9388400d1aab01a83652bc040c9c087bd732eb214909d7fb0dd \ + --hash=sha256:3f2fe35ec84908dddf0fbf66b35d7c2878dbe349552dd52e005c755d3493d61c \ + --hash=sha256:3f96a9130171e01dbb6c3d4d9925d604e2131a97f540e223b88ba45daf56d6fb \ + --hash=sha256:444633b487a711e34f4bccc46a0c5dfbe1aee82c1a511e58cdc16f6bd66f187c \ + --hash=sha256:498f88f5109666c19531f0243a90d2fdd2252839cd6c8cc6e9213a3446670fa8 \ + --hash=sha256:51a86bd963de3f36688553926a84e550d45d7f9745bd1947d79472eca27fcc75 \ + --hash=sha256:52788e7c489069e317fde641de41b757fa0ddc150e06488f153dd5daebac7192 \ + --hash=sha256:52cd7d9fa0a115c9446abb79b06a47171b7d916c35c10e0c3aa6f01d57561382 \ + --hash=sha256:55872e818598319f065e8192ebefecd6ac05f62a43f055ed71884b0a26218f41 \ + --hash=sha256:561123d05681197c0e24eb8ab3cfdaf299e2b59c293d19dad96e1610ccd8fbc6 \ + --hash=sha256:57be3abb4313e0dd625596376bbb607f40059d801d51c1a1da94d7477e63b255 \ + --hash=sha256:5e941654cef13a1d53634ec30933722eda11f44f99e1d0bc62bbce3387580d50 \ + --hash=sha256:622e1e04bd8a085994e02313ba06fbcf4f9ed9a488c6a77a8dbc0692abab6a38 \ + --hash=sha256:6324fde5cf5120fbf6541d5ff3c86011ec056e8d0f915d8e7822926a5377193a \ + --hash=sha256:6374feaf347e6b83ec13cc5dcfa70076f06d8f7ecd46cc71d58fac798ff08b76 \ + --hash=sha256:63d39b161000aeeaa06a1cb77c9806e939bfe460dfd593e4cbf24e6bc717ae94 \ + --hash=sha256:656ed895b28c7e42dd5b40dfcea3217cfc166b6b7eef88c3da2f5fc62484035b \ + --hash=sha256:663848a8bac4fdbba27feea2926049fdf7b55ec545d5b9aea096ef21e7f0b079 \ + --hash=sha256:6885ae4b33aee8835dbdb4249d3dfec09af55e705d74d9b660bfb9da51baaa8b \ + --hash=sha256:6b005bcee4be9c3984b355336283afe77b2defa76ed6b89332eced7b6fa68b68 \ + --hash=sha256:76cdfe7f920738ea871f035568f82bad3328cbc8d98f1f6988264096b5264efd \ + --hash=sha256:77b8b7b98893eaf47da03d262816f01f251c2aa059c063ed8a45c50eada123a5 \ + --hash=sha256:7ac6e4d727521d86d20ec291a3f4e64a478e8a73eaee80af8f38ec403e77a409 \ + --hash=sha256:7de5869e616d426b56809be7dc6dba4d37b95b90411ccd3de47f421a42d4d42c \ + --hash=sha256:869bf13f66b124b13be37dd6e08e4b728948ff9735308694e0b0479119e08ea7 \ + --hash=sha256:87ae1684bc3c02d5c35884b3726525eda85307073dbefe68c3c779e104a59036 \ + --hash=sha256:8ecd3b1f7a601f79e0cd20c26057d770219c0dc2f572ea07390248da2def79a4 \ + --hash=sha256:92be52ca4e6e604f03d5daa079caec9e04ab4cbf6972b995aaebb877d3d24e13 \ + --hash=sha256:92ea7855d5bcfb386c34557516c73753435fb2d4a014e2c9343b5f5ba148b5d8 \ + --hash=sha256:962ea3aecedcc944f8034812e23d7200d52c6e32765b8da396eeb8b8ffca71ce \ + --hash=sha256:98ca91dc9602cf351497d5600aa66e6d011a38c085a8237b370433fcb53e3409 \ + --hash=sha256:9b84c6c210684286e504022d11ec294d2b7922d66c823e87575d8b23eba7c81f \ + --hash=sha256:a0f6fc2ea6e07e20df48752e7700e02e1892c61f9a6bfbacaf2c5b24d5ad504b \ + --hash=sha256:a2bda8f2790add22773ee7a4e43c90ea05598bffc94c21c40ae0a9000b0133c3 \ + --hash=sha256:aa705beb74ab116563f4ce784fa94771f230c05d09ab5de9c397793e725bb1db \ + --hash=sha256:aadf32c389bb7f02b8ec5c243c38302b92c006da565e120dfcb7bf0378f4f848 \ + --hash=sha256:ab2357353894a5ec084bb8508ff892aa43fb7fe8a69ad310eac58221ee7f72aa \ + --hash=sha256:ad9fd176ff6800a0cf52bcf59c71e5de4fa25bf3ba62b58800e0f84885344d34 \ + --hash=sha256:addfc23e3bd5f4b6787b9ca95b2d09a1a67ad5a3c318daaa783ff90b2d3a366e \ + --hash=sha256:af1394c2c5febc44e0bbf0fc6428263fa928b50d1b1982ce1d870dc793a8e5f4 \ + --hash=sha256:b04c94718f7a8ed7cdd01b162b6caa1954b3c9d486f00ecbbd300f149d2b2606 \ + --hash=sha256:b4f20417a4f511c656762b001ec827500cbee54d1810253c6ca2df2c0a307a5f \ + --hash=sha256:b7a8c30d9bf4bd5e4dcfe26900bef0fcd9749acde45cdf0b3c89e2052fda9a13 \ + --hash=sha256:b7fa260dd2731afd0dfa47881c30239f422d00faee4b8b341d3e597cface1483 \ + --hash=sha256:b91380aefa9c7ac831b011368daf378d3277e0bdeb6bad9535e21251e26dd55a \ + --hash=sha256:bb2446a55b3a0fd8aa02aa7194bd64740015464a2daaf160d2025204e1d7c282 \ + --hash=sha256:bc05f8a875eb651d1cc62e12a4a0e6afa5cd0cc231381adb830d2e9c196ea895 \ + --hash=sha256:bcf69e0bcddbf2adcfafc1a7e864edcc204dd8171756d3a8f3340f6f6cc87b7b \ + --hash=sha256:bf02f915fa7934ea5dfc8d96757729c99a8868b7c340b97704795d6413cf5fe6 \ + --hash=sha256:c39d2b6161f3c5c5d12e9207ecf1006bb661a647a97a6573656b09aaea3f00ef \ + --hash=sha256:c59740682a686bf835a1a4d8d0ed1eefe31ac07f1c5a7ed5f2e72cf577692b00 \ + --hash=sha256:cc76de75300f65b8eb574d855c12518dc25a075dadb41dd18f6322bda3fe15d5 \ + --hash=sha256:cd0d3d16e63873253bad22b413ec679cf6586e51b5772eb10733899832efec42 \ + --hash=sha256:cda61c46343809ecda43dc620d1333dd7433a25d0a252f2dcc7667f6331c7b61 \ + --hash=sha256:cf7fbb4e54136e9a03c7ed7691843c4df6d2ecc854a2541f840665f4f2bb2edd \ + --hash=sha256:d2b3b4bda1a025b10fe0269369475f420177f2cb06e0f9d32c95b4873c9f80b8 \ + --hash=sha256:d5e3b9310fd7f0d12edc75532cd9a56da6293840c84da90070d692e0bb15f186 \ + --hash=sha256:d64899cc0f33a8f446f1e60bffc21fa88b99f0e8208750d9144ea717610a80ce \ + --hash=sha256:d6975f2d903bc354916a17b91a7aaac7299603f9ecdb788145060dde6e573a16 \ + --hash=sha256:d82ac87017b734f2fb70ff93818c66f0ad2c3810f61040f077ed38d924e19980 \ + --hash=sha256:dd91b0134a32dfcd8be504e8e46de44ad0045a569efc25101f2a12ccd41b5759 \ + --hash=sha256:df4be1cf6e8f0f2bbe2a3eabfff163ef592c84a40e1a20a8d7db7f27cfe08fc2 \ + --hash=sha256:e05d66239d14a04b4717998b736a25494372b1b2409339b04bf42aa4663bf251 \ + --hash=sha256:e40cd0fc734aa1d4bd0e7ad102fd2a1aefa50ce9ef570005ffc2273c5442ddc3 \ + --hash=sha256:e46eb6702691b24ddb3e31e88b4a499e31506991db3d3724a85bd1c5fc3cfe4e \ + --hash=sha256:e4ebb000c0fe24a6d0f3534b6256844d9dbf042fdf003efe5cf40690cf4e0f3e \ + --hash=sha256:e69f8e534b4e254f523e2f9d4732cf9c169c327ca1ce0922682aac9a5ee01155 \ + --hash=sha256:e91a4e5d62da7cb3f53e04fe254f1aa41009af578801ee6477fe56e7bef74ee2 \ + --hash=sha256:ec194197e90ca063f5ecb935d6c10063d84208cac5423c07d0f1a09d1c2ea42b \ + --hash=sha256:f6ae9fc67e636fc0fa9adee39db87dfbdeabfa8420bc0e678a1ac8441e01b22b \ + --hash=sha256:f7d3fe9e1483171e9183ffdb1fab07c5fef80a9c3840374a38ec2ab869ebae20 \ + --hash=sha256:fdc7a52a4cdaf7293e10813fd6a3abc0c7753660db12a3b864ab1fb5a0c60c16 \ + --hash=sha256:fe3198b81c00032326342d973e526803f183f97aa9e9a98e3f897ebafe21178f \ + --hash=sha256:ff19efaa33e7f136fe95f9bbcc90ab7fb60648453b03f95d1de3ab6997de0f32 + # via -r requirements.in diff --git a/requirements.win.txt b/requirements.win.txt index d37a96f..899a4c5 100644 --- a/requirements.win.txt +++ b/requirements.win.txt @@ -6,10 +6,81 @@ attrs==25.3.0 \ # via # jsonschema # referencing -certifi==2025.4.26 \ - --hash=sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6 \ - --hash=sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3 +certifi==2025.7.14 \ + --hash=sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2 \ + --hash=sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995 # via requests +cffi==1.17.1 \ + --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \ + --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ + --hash=sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1 \ + --hash=sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15 \ + --hash=sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36 \ + --hash=sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824 \ + --hash=sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8 \ + --hash=sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36 \ + --hash=sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17 \ + --hash=sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf \ + --hash=sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc \ + --hash=sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3 \ + --hash=sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed \ + --hash=sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702 \ + --hash=sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1 \ + --hash=sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8 \ + --hash=sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903 \ + --hash=sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6 \ + --hash=sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d \ + --hash=sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b \ + --hash=sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e \ + --hash=sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be \ + --hash=sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c \ + --hash=sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683 \ + --hash=sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9 \ + --hash=sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c \ + --hash=sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8 \ + --hash=sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1 \ + --hash=sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4 \ + --hash=sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655 \ + --hash=sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67 \ + --hash=sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595 \ + --hash=sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0 \ + --hash=sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65 \ + --hash=sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41 \ + --hash=sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6 \ + --hash=sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401 \ + --hash=sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6 \ + --hash=sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3 \ + --hash=sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16 \ + --hash=sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93 \ + --hash=sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e \ + --hash=sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4 \ + --hash=sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964 \ + --hash=sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c \ + --hash=sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576 \ + --hash=sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0 \ + --hash=sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3 \ + --hash=sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662 \ + --hash=sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3 \ + --hash=sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff \ + --hash=sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5 \ + --hash=sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd \ + --hash=sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f \ + --hash=sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5 \ + --hash=sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14 \ + --hash=sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d \ + --hash=sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9 \ + --hash=sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7 \ + --hash=sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382 \ + --hash=sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a \ + --hash=sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e \ + --hash=sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a \ + --hash=sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4 \ + --hash=sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99 \ + --hash=sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87 \ + --hash=sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b + # via + # cryptography + # pynacl charset-normalizer==3.4.2 \ --hash=sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4 \ --hash=sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45 \ @@ -104,6 +175,49 @@ charset-normalizer==3.4.2 \ --hash=sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a \ --hash=sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f # via requests +cryptography==45.0.5 \ + --hash=sha256:0027d566d65a38497bc37e0dd7c2f8ceda73597d2ac9ba93810204f56f52ebc7 \ + --hash=sha256:101ee65078f6dd3e5a028d4f19c07ffa4dd22cce6a20eaa160f8b5219911e7d8 \ + --hash=sha256:12e55281d993a793b0e883066f590c1ae1e802e3acb67f8b442e721e475e6463 \ + --hash=sha256:14d96584701a887763384f3c47f0ca7c1cce322aa1c31172680eb596b890ec30 \ + --hash=sha256:1e1da5accc0c750056c556a93c3e9cb828970206c68867712ca5805e46dc806f \ + --hash=sha256:206210d03c1193f4e1ff681d22885181d47efa1ab3018766a7b32a7b3d6e6afd \ + --hash=sha256:2089cc8f70a6e454601525e5bf2779e665d7865af002a5dec8d14e561002e135 \ + --hash=sha256:3a264aae5f7fbb089dbc01e0242d3b67dffe3e6292e1f5182122bdf58e65215d \ + --hash=sha256:3af26738f2db354aafe492fb3869e955b12b2ef2e16908c8b9cb928128d42c57 \ + --hash=sha256:3fcfbefc4a7f332dece7272a88e410f611e79458fab97b5efe14e54fe476f4fd \ + --hash=sha256:460f8c39ba66af7db0545a8c6f2eabcbc5a5528fc1cf6c3fa9a1e44cec33385e \ + --hash=sha256:57c816dfbd1659a367831baca4b775b2a5b43c003daf52e9d57e1d30bc2e1b0e \ + --hash=sha256:5aa1e32983d4443e310f726ee4b071ab7569f58eedfdd65e9675484a4eb67bd1 \ + --hash=sha256:6ff8728d8d890b3dda5765276d1bc6fb099252915a2cd3aff960c4c195745dd0 \ + --hash=sha256:7259038202a47fdecee7e62e0fd0b0738b6daa335354396c6ddebdbe1206af2a \ + --hash=sha256:72e76caa004ab63accdf26023fccd1d087f6d90ec6048ff33ad0445abf7f605a \ + --hash=sha256:7760c1c2e1a7084153a0f68fab76e754083b126a47d0117c9ed15e69e2103492 \ + --hash=sha256:8c4a6ff8a30e9e3d38ac0539e9a9e02540ab3f827a3394f8852432f6b0ea152e \ + --hash=sha256:9024beb59aca9d31d36fcdc1604dd9bbeed0a55bface9f1908df19178e2f116e \ + --hash=sha256:90cb0a7bb35959f37e23303b7eed0a32280510030daba3f7fdfbb65defde6a97 \ + --hash=sha256:91098f02ca81579c85f66df8a588c78f331ca19089763d733e34ad359f474174 \ + --hash=sha256:926c3ea71a6043921050eaa639137e13dbe7b4ab25800932a8498364fc1abec9 \ + --hash=sha256:982518cd64c54fcada9d7e5cf28eabd3ee76bd03ab18e08a48cad7e8b6f31b18 \ + --hash=sha256:9b4cf6318915dccfe218e69bbec417fdd7c7185aa7aab139a2c0beb7468c89f0 \ + --hash=sha256:ad0caded895a00261a5b4aa9af828baede54638754b51955a0ac75576b831b27 \ + --hash=sha256:b85980d1e345fe769cfc57c57db2b59cff5464ee0c045d52c0df087e926fbe63 \ + --hash=sha256:b8fa8b0a35a9982a3c60ec79905ba5bb090fc0b9addcfd3dc2dd04267e45f25e \ + --hash=sha256:b9e38e0a83cd51e07f5a48ff9691cae95a79bea28fe4ded168a8e5c6c77e819d \ + --hash=sha256:bd4c45986472694e5121084c6ebbd112aa919a25e783b87eb95953c9573906d6 \ + --hash=sha256:be97d3a19c16a9be00edf79dca949c8fa7eff621763666a145f9f9535a5d7f42 \ + --hash=sha256:c648025b6840fe62e57107e0a25f604db740e728bd67da4f6f060f03017d5097 \ + --hash=sha256:d05a38884db2ba215218745f0781775806bde4f32e07b135348355fe8e4991d9 \ + --hash=sha256:dd420e577921c8c2d31289536c386aaa30140b473835e97f83bc71ea9d2baf2d \ + --hash=sha256:e357286c1b76403dd384d938f93c46b2b058ed4dfcdce64a770f0537ed3feb6f \ + --hash=sha256:e6c00130ed423201c5bc5544c23359141660b07999ad82e34e7bb8f882bb78e0 \ + --hash=sha256:e74d30ec9c7cb2f404af331d5b4099a9b322a8a6b25c4632755c8757345baac5 \ + --hash=sha256:f3562c2f23c612f2e4a6964a61d942f891d29ee320edb62ff48ffb99f3de9ae8 + # via pyjwt +deprecated==1.2.18 \ + --hash=sha256:422b6f6d859da6f2ef57857761bfb392480502a64c3028ca9bbe86085d72115d \ + --hash=sha256:bd5011788200372a32418f888e326a09ff80d0214bd961147cfed01b5c018eec + # via pygithub docker==7.1.0 \ --hash=sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c \ --hash=sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0 @@ -116,9 +230,9 @@ jinja2==3.1.6 \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 # via -r requirements.in -jsonschema==4.24.0 \ - --hash=sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196 \ - --hash=sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d +jsonschema==4.25.0 \ + --hash=sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716 \ + --hash=sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f # via -r requirements.in jsonschema-specifications==2025.4.1 \ --hash=sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af \ @@ -187,6 +301,30 @@ markupsafe==3.0.2 \ --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \ --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50 # via jinja2 +pycparser==2.22 \ + --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ + --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc + # via cffi +pygithub==2.6.1 \ + --hash=sha256:6f2fa6d076ccae475f9fc392cc6cdbd54db985d4f69b8833a28397de75ed6ca3 \ + --hash=sha256:b5c035392991cca63959e9453286b41b54d83bf2de2daa7d7ff7e4312cebf3bf + # via -r requirements.in +pyjwt==2.10.1 \ + --hash=sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953 \ + --hash=sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb + # via pygithub +pynacl==1.5.0 \ + --hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \ + --hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \ + --hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \ + --hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \ + --hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \ + --hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \ + --hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \ + --hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \ + --hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \ + --hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543 + # via pygithub pywin32==310 \ --hash=sha256:0867beb8addefa2e3979d4084352e4ac6e991ca45373390775f7084cc0209b9c \ --hash=sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c \ @@ -205,58 +343,60 @@ pywin32==310 \ --hash=sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d \ --hash=sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33 # via docker -pyyaml==6.0.1 \ - --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ - --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ - --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ - --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ - --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ - --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ - --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ - --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ - --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ - --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ - --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ - --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ - --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ - --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ - --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ - --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ - --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ - --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ - --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ - --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ - --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ - --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ - --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ - --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ - --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ - --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ - --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ - --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ - --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ - --hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \ - --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ - --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ - --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ - --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ - --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ - --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ - --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ - --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ - --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ - --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ - --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ - --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ - --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ - --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ - --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ - --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ - --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ - --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ - --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ - --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ - --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f +pyyaml==6.0.2 \ + --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ + --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ + --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \ + --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \ + --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ + --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \ + --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ + --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \ + --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ + --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \ + --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \ + --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \ + --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \ + --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \ + --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \ + --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \ + --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ + --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \ + --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ + --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \ + --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \ + --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \ + --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \ + --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ + --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ + --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \ + --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \ + --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ + --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ + --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \ + --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ + --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \ + --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ + --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \ + --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \ + --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ + --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \ + --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \ + --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \ + --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ + --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ + --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \ + --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ + --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ + --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \ + --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \ + --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \ + --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \ + --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \ + --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ + --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \ + --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \ + --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4 # via -r requirements.in referencing==0.36.2 \ --hash=sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa \ @@ -267,125 +407,154 @@ referencing==0.36.2 \ requests==2.32.4 \ --hash=sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c \ --hash=sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422 - # via docker -rpds-py==0.25.1 \ - --hash=sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d \ - --hash=sha256:036ded36bedb727beeabc16dc1dad7cb154b3fa444e936a03b67a86dc6a5066e \ - --hash=sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f \ - --hash=sha256:0701942049095741a8aeb298a31b203e735d1c61f4423511d2b1a41dcd8a16da \ - --hash=sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c \ - --hash=sha256:09eab132f41bf792c7a0ea1578e55df3f3e7f61888e340779b06050a9a3f16e9 \ - --hash=sha256:0e6a327af8ebf6baba1c10fadd04964c1965d375d318f4435d5f3f9651550f4a \ - --hash=sha256:0eb90e94f43e5085623932b68840b6f379f26db7b5c2e6bcef3179bd83c9330f \ - --hash=sha256:114a07e85f32b125404f28f2ed0ba431685151c037a26032b213c882f26eb908 \ - --hash=sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b \ - --hash=sha256:140f61d9bed7839446bdd44852e30195c8e520f81329b4201ceead4d64eb3a9f \ - --hash=sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd \ - --hash=sha256:1c0c434a53714358532d13539272db75a5ed9df75a4a090a753ac7173ec14e11 \ - --hash=sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf \ - --hash=sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65 \ - --hash=sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0 \ - --hash=sha256:245550f5a1ac98504147cba96ffec8fabc22b610742e9150138e5d60774686d7 \ - --hash=sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9 \ - --hash=sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea \ - --hash=sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523 \ - --hash=sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692 \ - --hash=sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda \ - --hash=sha256:35a8d1a24b5936b35c5003313bc177403d8bdef0f8b24f28b1c4a255f94ea992 \ - --hash=sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b \ - --hash=sha256:3bcce0edc1488906c2d4c75c94c70a0417e83920dd4c88fec1078c94843a6ce9 \ - --hash=sha256:3c5b317ecbd8226887994852e85de562f7177add602514d4ac40f87de3ae45a8 \ - --hash=sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40 \ - --hash=sha256:3ebd879ab996537fc510a2be58c59915b5dd63bccb06d1ef514fee787e05984a \ - --hash=sha256:3f0b1798cae2bbbc9b9db44ee068c556d4737911ad53a4e5093d09d04b3bbc24 \ - --hash=sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763 \ - --hash=sha256:454601988aab2c6e8fd49e7634c65476b2b919647626208e376afcd22019eeb8 \ - --hash=sha256:4593c4eae9b27d22df41cde518b4b9e4464d139e4322e2127daa9b5b981b76be \ - --hash=sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd \ - --hash=sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65 \ - --hash=sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255 \ - --hash=sha256:4fd52d3455a0aa997734f3835cbc4c9f32571345143960e7d7ebfe7b5fbfa3b2 \ - --hash=sha256:50f2c501a89c9a5f4e454b126193c5495b9fb441a75b298c60591d8a2eb92e1b \ - --hash=sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66 \ - --hash=sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4 \ - --hash=sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79 \ - --hash=sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31 \ - --hash=sha256:5d9e40f32745db28c1ef7aad23f6fc458dc1e29945bd6781060f0d15628b8ddf \ - --hash=sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d \ - --hash=sha256:605ffe7769e24b1800b4d024d24034405d9404f0bc2f55b6db3362cd34145a6f \ - --hash=sha256:6099263f526efff9cf3883dfef505518730f7a7a93049b1d90d42e50a22b4793 \ - --hash=sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559 \ - --hash=sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9 \ - --hash=sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1 \ - --hash=sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34 \ - --hash=sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728 \ - --hash=sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b \ - --hash=sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038 \ - --hash=sha256:796ad874c89127c91970652a4ee8b00d56368b7e00d3477f4415fe78164c8000 \ - --hash=sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98 \ - --hash=sha256:7c9409b47ba0650544b0bb3c188243b83654dfe55dcc173a86832314e1a6a35d \ - --hash=sha256:7d779b325cc8238227c47fbc53964c8cc9a941d5dbae87aa007a1f08f2f77b23 \ - --hash=sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb \ - --hash=sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e \ - --hash=sha256:85608eb70a659bf4c1142b2781083d4b7c0c4e2c90eff11856a9754e965b2540 \ - --hash=sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1 \ - --hash=sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd \ - --hash=sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3 \ - --hash=sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f \ - --hash=sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba \ - --hash=sha256:8c742af695f7525e559c16f1562cf2323db0e3f0fbdcabdf6865b095256b2d40 \ - --hash=sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72 \ - --hash=sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78 \ - --hash=sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5 \ - --hash=sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe \ - --hash=sha256:9c006f3aadeda131b438c3092124bd196b66312f0caa5823ef09585a669cf449 \ - --hash=sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b \ - --hash=sha256:9e5fc7484fa7dce57e25063b0ec9638ff02a908304f861d81ea49273e43838c1 \ - --hash=sha256:9f2f48ab00181600ee266a095fe815134eb456163f7d6699f525dee471f312cf \ - --hash=sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c \ - --hash=sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325 \ - --hash=sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129 \ - --hash=sha256:a61d0b2c7c9a0ae45732a77844917b427ff16ad5464b4d4f5e4adb955f582890 \ - --hash=sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa \ - --hash=sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500 \ - --hash=sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb \ - --hash=sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762 \ - --hash=sha256:b24bf3cd93d5b6ecfbedec73b15f143596c88ee249fa98cefa9a9dc9d92c6f28 \ - --hash=sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c \ - --hash=sha256:bc120d1132cff853ff617754196d0ac0ae63befe7c8498bd67731ba368abe451 \ - --hash=sha256:bd035756830c712b64725a76327ce80e82ed12ebab361d3a1cdc0f51ea21acb0 \ - --hash=sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042 \ - --hash=sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7 \ - --hash=sha256:c4feb9211d15d9160bc85fa72fed46432cdc143eb9cf6d5ca377335a921ac37b \ - --hash=sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6 \ - --hash=sha256:c98f126c4fc697b84c423e387337d5b07e4a61e9feac494362a59fd7a2d9ed80 \ - --hash=sha256:ccc6f3ddef93243538be76f8e47045b4aad7a66a212cd3a0f23e34469473d36b \ - --hash=sha256:ccfa689b9246c48947d31dd9d8b16d89a0ecc8e0e26ea5253068efb6c542b76e \ - --hash=sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc \ - --hash=sha256:ce4c8e485a3c59593f1a6f683cf0ea5ab1c1dc94d11eea5619e4fb5228b40fbd \ - --hash=sha256:d3c10228d6cf6fe2b63d2e7985e94f6916fa46940df46b70449e9ff9297bd3d1 \ - --hash=sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2 \ - --hash=sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309 \ - --hash=sha256:d50e4864498a9ab639d6d8854b25e80642bd362ff104312d9770b05d66e5fb13 \ - --hash=sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295 \ - --hash=sha256:d8222acdb51a22929c3b2ddb236b69c59c72af4019d2cba961e2f9add9b6e634 \ - --hash=sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192 \ - --hash=sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4 \ - --hash=sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5 \ - --hash=sha256:dec21e02e6cc932538b5203d3a8bd6aa1480c98c4914cb88eea064ecdbc6396a \ - --hash=sha256:e1dafef8df605fdb46edcc0bf1573dea0d6d7b01ba87f85cd04dc855b2b4479e \ - --hash=sha256:e2f6a2347d3440ae789505693a02836383426249d5293541cd712e07e7aecf54 \ - --hash=sha256:e37caa8cdb3b7cf24786451a0bdb853f6347b8b92005eeb64225ae1db54d1c2b \ - --hash=sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72 \ - --hash=sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe \ - --hash=sha256:e87798852ae0b37c88babb7f7bbbb3e3fecc562a1c340195b44c7e24d403e380 \ - --hash=sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954 \ - --hash=sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d \ - --hash=sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194 \ - --hash=sha256:f4ad628b5174d5315761b67f212774a32f5bad5e61396d38108bd801c0a8f5d9 \ - --hash=sha256:f70316f760174ca04492b5ab01be631a8ae30cadab1d1081035136ba12738cfa \ - --hash=sha256:f73ce1512e04fbe2bc97836e89830d6b4314c171587a99688082d090f934d20a \ - --hash=sha256:ff7c23ba0a88cb7b104281a99476cccadf29de2a0ef5ce864959a52675b1ca83 + # via + # docker + # pygithub +rpds-py==0.26.0 \ + --hash=sha256:0919f38f5542c0a87e7b4afcafab6fd2c15386632d249e9a087498571250abe3 \ + --hash=sha256:093d63b4b0f52d98ebae33b8c50900d3d67e0666094b1be7a12fffd7f65de74b \ + --hash=sha256:0a0b60701f2300c81b2ac88a5fb893ccfa408e1c4a555a77f908a2596eb875a5 \ + --hash=sha256:0c71c2f6bf36e61ee5c47b2b9b5d47e4d1baad6426bfed9eea3e858fc6ee8806 \ + --hash=sha256:0dc23bbb3e06ec1ea72d515fb572c1fea59695aefbffb106501138762e1e915e \ + --hash=sha256:0dfa6115c6def37905344d56fb54c03afc49104e2ca473d5dedec0f6606913b4 \ + --hash=sha256:12bff2ad9447188377f1b2794772f91fe68bb4bbfa5a39d7941fbebdbf8c500f \ + --hash=sha256:1533b7eb683fb5f38c1d68a3c78f5fdd8f1412fa6b9bf03b40f450785a0ab915 \ + --hash=sha256:1766b5724c3f779317d5321664a343c07773c8c5fd1532e4039e6cc7d1a815be \ + --hash=sha256:181ef9b6bbf9845a264f9aa45c31836e9f3c1f13be565d0d010e964c661d1e2b \ + --hash=sha256:183f857a53bcf4b1b42ef0f57ca553ab56bdd170e49d8091e96c51c3d69ca696 \ + --hash=sha256:191aa858f7d4902e975d4cf2f2d9243816c91e9605070aeb09c0a800d187e323 \ + --hash=sha256:1a8b0dd8648709b62d9372fc00a57466f5fdeefed666afe3fea5a6c9539a0331 \ + --hash=sha256:1c962145c7473723df9722ba4c058de12eb5ebedcb4e27e7d902920aa3831ee8 \ + --hash=sha256:1cc81d14ddfa53d7f3906694d35d54d9d3f850ef8e4e99ee68bc0d1e5fed9a9c \ + --hash=sha256:1d815d48b1804ed7867b539236b6dd62997850ca1c91cad187f2ddb1b7bbef19 \ + --hash=sha256:1e6c15d2080a63aaed876e228efe4f814bc7889c63b1e112ad46fdc8b368b9e1 \ + --hash=sha256:20ab1ae4fa534f73647aad289003f1104092890849e0266271351922ed5574f8 \ + --hash=sha256:20dae58a859b0906f0685642e591056f1e787f3a8b39c8e8749a45dc7d26bdb0 \ + --hash=sha256:238e8c8610cb7c29460e37184f6799547f7e09e6a9bdbdab4e8edb90986a2318 \ + --hash=sha256:24a4146ccb15be237fdef10f331c568e1b0e505f8c8c9ed5d67759dac58ac246 \ + --hash=sha256:257d011919f133a4746958257f2c75238e3ff54255acd5e3e11f3ff41fd14256 \ + --hash=sha256:2a343f91b17097c546b93f7999976fd6c9d5900617aa848c81d794e062ab302b \ + --hash=sha256:2abe21d8ba64cded53a2a677e149ceb76dcf44284202d737178afe7ba540c1eb \ + --hash=sha256:2c03c9b0c64afd0320ae57de4c982801271c0c211aa2d37f3003ff5feb75bb04 \ + --hash=sha256:2c9c1b92b774b2e68d11193dc39620d62fd8ab33f0a3c77ecdabe19c179cdbc1 \ + --hash=sha256:3021933c2cb7def39d927b9862292e0f4c75a13d7de70eb0ab06efed4c508c19 \ + --hash=sha256:3100b3090269f3a7ea727b06a6080d4eb7439dca4c0e91a07c5d133bb1727ea7 \ + --hash=sha256:313cfcd6af1a55a286a3c9a25f64af6d0e46cf60bc5798f1db152d97a216ff6f \ + --hash=sha256:35e9a70a0f335371275cdcd08bc5b8051ac494dd58bff3bbfb421038220dc871 \ + --hash=sha256:38721d4c9edd3eb6670437d8d5e2070063f305bfa2d5aa4278c51cedcd508a84 \ + --hash=sha256:390e3170babf42462739a93321e657444f0862c6d722a291accc46f9d21ed04e \ + --hash=sha256:39bfea47c375f379d8e87ab4bb9eb2c836e4f2069f0f65731d85e55d74666387 \ + --hash=sha256:3ac51b65e8dc76cf4949419c54c5528adb24fc721df722fd452e5fbc236f5c40 \ + --hash=sha256:3c0909c5234543ada2515c05dc08595b08d621ba919629e94427e8e03539c958 \ + --hash=sha256:3da5852aad63fa0c6f836f3359647870e21ea96cf433eb393ffa45263a170d44 \ + --hash=sha256:3e1157659470aa42a75448b6e943c895be8c70531c43cb78b9ba990778955582 \ + --hash=sha256:4019a9d473c708cf2f16415688ef0b4639e07abaa569d72f74745bbeffafa2c7 \ + --hash=sha256:43f10b007033f359bc3fa9cd5e6c1e76723f056ffa9a6b5c117cc35720a80292 \ + --hash=sha256:49028aa684c144ea502a8e847d23aed5e4c2ef7cadfa7d5eaafcb40864844b7a \ + --hash=sha256:4916dc96489616a6f9667e7526af8fa693c0fdb4f3acb0e5d9f4400eb06a47ba \ + --hash=sha256:4a59e5bc386de021f56337f757301b337d7ab58baa40174fb150accd480bc953 \ + --hash=sha256:4b1f66eb81eab2e0ff5775a3a312e5e2e16bf758f7b06be82fb0d04078c7ac51 \ + --hash=sha256:4c5fe114a6dd480a510b6d3661d09d67d1622c4bf20660a474507aaee7eeeee9 \ + --hash=sha256:4c70c70f9169692b36307a95f3d8c0a9fcd79f7b4a383aad5eaa0e9718b79b37 \ + --hash=sha256:4d11382bcaf12f80b51d790dee295c56a159633a8e81e6323b16e55d81ae37e9 \ + --hash=sha256:4f01a5d6444a3258b00dc07b6ea4733e26f8072b788bef750baa37b370266137 \ + --hash=sha256:4f789e32fa1fb6a7bf890e0124e7b42d1e60d28ebff57fe806719abb75f0e9a3 \ + --hash=sha256:4feb7511c29f8442cbbc28149a92093d32e815a28aa2c50d333826ad2a20fdf0 \ + --hash=sha256:511d15193cbe013619dd05414c35a7dedf2088fcee93c6bbb7c77859765bd4e8 \ + --hash=sha256:519067e29f67b5c90e64fb1a6b6e9d2ec0ba28705c51956637bac23a2f4ddae1 \ + --hash=sha256:521ccf56f45bb3a791182dc6b88ae5f8fa079dd705ee42138c76deb1238e554e \ + --hash=sha256:529c8156d7506fba5740e05da8795688f87119cce330c244519cf706a4a3d618 \ + --hash=sha256:582462833ba7cee52e968b0341b85e392ae53d44c0f9af6a5927c80e539a8b67 \ + --hash=sha256:5963b72ccd199ade6ee493723d18a3f21ba7d5b957017607f815788cef50eaf1 \ + --hash=sha256:59b2093224a18c6508d95cfdeba8db9cbfd6f3494e94793b58972933fcee4c6d \ + --hash=sha256:5afaddaa8e8c7f1f7b4c5c725c0070b6eed0228f705b90a1732a48e84350f4e9 \ + --hash=sha256:5afea17ab3a126006dc2f293b14ffc7ef3c85336cf451564a0515ed7648033da \ + --hash=sha256:5e09330b21d98adc8ccb2dbb9fc6cb434e8908d4c119aeaa772cb1caab5440a0 \ + --hash=sha256:6188de70e190847bb6db3dc3981cbadff87d27d6fe9b4f0e18726d55795cee9b \ + --hash=sha256:68ffcf982715f5b5b7686bdd349ff75d422e8f22551000c24b30eaa1b7f7ae84 \ + --hash=sha256:696764a5be111b036256c0b18cd29783fab22154690fc698062fc1b0084b511d \ + --hash=sha256:69a607203441e07e9a8a529cff1d5b73f6a160f22db1097211e6212a68567d11 \ + --hash=sha256:69b312fecc1d017b5327afa81d4da1480f51c68810963a7336d92203dbb3d4f1 \ + --hash=sha256:69f0c0a3df7fd3a7eec50a00396104bb9a843ea6d45fcc31c2d5243446ffd7a7 \ + --hash=sha256:6a1cb5d6ce81379401bbb7f6dbe3d56de537fb8235979843f0d53bc2e9815a79 \ + --hash=sha256:6d3498ad0df07d81112aa6ec6c95a7e7b1ae00929fb73e7ebee0f3faaeabad2f \ + --hash=sha256:72a8d9564a717ee291f554eeb4bfeafe2309d5ec0aa6c475170bdab0f9ee8e88 \ + --hash=sha256:777c62479d12395bfb932944e61e915741e364c843afc3196b694db3d669fcd0 \ + --hash=sha256:77a7711fa562ba2da1aa757e11024ad6d93bad6ad7ede5afb9af144623e5f76a \ + --hash=sha256:79061ba1a11b6a12743a2b0f72a46aa2758613d454aa6ba4f5a265cc48850158 \ + --hash=sha256:7a48af25d9b3c15684059d0d1fc0bc30e8eee5ca521030e2bffddcab5be40226 \ + --hash=sha256:7ab504c4d654e4a29558eaa5bb8cea5fdc1703ea60a8099ffd9c758472cf913f \ + --hash=sha256:7bdb17009696214c3b66bb3590c6d62e14ac5935e53e929bcdbc5a495987a84f \ + --hash=sha256:7da84c2c74c0f5bc97d853d9e17bb83e2dcafcff0dc48286916001cc114379a1 \ + --hash=sha256:801a71f70f9813e82d2513c9a96532551fce1e278ec0c64610992c49c04c2dad \ + --hash=sha256:824e6d3503ab990d7090768e4dfd9e840837bae057f212ff9f4f05ec6d1975e7 \ + --hash=sha256:82b165b07f416bdccf5c84546a484cc8f15137ca38325403864bfdf2b5b72f6a \ + --hash=sha256:84cfbd4d4d2cdeb2be61a057a258d26b22877266dd905809e94172dff01a42ae \ + --hash=sha256:84d142d2d6cf9b31c12aa4878d82ed3b2324226270b89b676ac62ccd7df52d08 \ + --hash=sha256:87a5531de9f71aceb8af041d72fc4cab4943648d91875ed56d2e629bef6d4c03 \ + --hash=sha256:893b022bfbdf26d7bedb083efeea624e8550ca6eb98bf7fea30211ce95b9201a \ + --hash=sha256:894514d47e012e794f1350f076c427d2347ebf82f9b958d554d12819849a369d \ + --hash=sha256:8a7898b6ca3b7d6659e55cdac825a2e58c638cbf335cde41f4619e290dd0ad11 \ + --hash=sha256:8ad7fd2258228bf288f2331f0a6148ad0186b2e3643055ed0db30990e59817a6 \ + --hash=sha256:92c8db839367ef16a662478f0a2fe13e15f2227da3c1430a782ad0f6ee009ec9 \ + --hash=sha256:941c1cfdf4799d623cf3aa1d326a6b4fdb7a5799ee2687f3516738216d2262fb \ + --hash=sha256:9bc596b30f86dc6f0929499c9e574601679d0341a0108c25b9b358a042f51bca \ + --hash=sha256:9c55b0a669976cf258afd718de3d9ad1b7d1fe0a91cd1ab36f38b03d4d4aeaaf \ + --hash=sha256:9da4e873860ad5bab3291438525cae80169daecbfafe5657f7f5fb4d6b3f96b9 \ + --hash=sha256:9def736773fd56b305c0eef698be5192c77bfa30d55a0e5885f80126c4831a15 \ + --hash=sha256:9dfbe56b299cf5875b68eb6f0ebaadc9cac520a1989cac0db0765abfb3709c19 \ + --hash=sha256:9e851920caab2dbcae311fd28f4313c6953993893eb5c1bb367ec69d9a39e7ed \ + --hash=sha256:9e8cb77286025bdb21be2941d64ac6ca016130bfdcd228739e8ab137eb4406ed \ + --hash=sha256:a547e21c5610b7e9093d870be50682a6a6cf180d6da0f42c47c306073bfdbbf6 \ + --hash=sha256:a90a13408a7a856b87be8a9f008fff53c5080eea4e4180f6c2e546e4a972fb5d \ + --hash=sha256:a9a63785467b2d73635957d32a4f6e73d5e4df497a16a6392fa066b753e87387 \ + --hash=sha256:aa81873e2c8c5aa616ab8e017a481a96742fdf9313c40f14338ca7dbf50cb55f \ + --hash=sha256:ac64f4b2bdb4ea622175c9ab7cf09444e412e22c0e02e906978b3b488af5fde8 \ + --hash=sha256:aea1f9741b603a8d8fedb0ed5502c2bc0accbc51f43e2ad1337fe7259c2b77a5 \ + --hash=sha256:b0afb8cdd034150d4d9f53926226ed27ad15b7f465e93d7468caaf5eafae0d37 \ + --hash=sha256:b37a04d9f52cb76b6b78f35109b513f6519efb481d8ca4c321f6a3b9580b3f45 \ + --hash=sha256:b5f7a446ddaf6ca0fad9a5535b56fbfc29998bf0e0b450d174bbec0d600e1d72 \ + --hash=sha256:b6d9e5a2ed9c4988c8f9b28b3bc0e3e5b1aaa10c28d210a594ff3a8c02742daf \ + --hash=sha256:b6e2c12160c72aeda9d1283e612f68804621f448145a210f1bf1d79151c47090 \ + --hash=sha256:b818a592bd69bfe437ee8368603d4a2d928c34cffcdf77c2e761a759ffd17d20 \ + --hash=sha256:c1851f429b822831bd2edcbe0cfd12ee9ea77868f8d3daf267b189371671c80e \ + --hash=sha256:c1fb0cda2abcc0ac62f64e2ea4b4e64c57dfd6b885e693095460c61bde7bb18e \ + --hash=sha256:c5ab0ee51f560d179b057555b4f601b7df909ed31312d301b99f8b9fc6028284 \ + --hash=sha256:c70d9ec912802ecfd6cd390dadb34a9578b04f9bcb8e863d0a7598ba5e9e7ccc \ + --hash=sha256:c741107203954f6fc34d3066d213d0a0c40f7bb5aafd698fb39888af277c70d8 \ + --hash=sha256:ca3f059f4ba485d90c8dc75cb5ca897e15325e4e609812ce57f896607c1c0867 \ + --hash=sha256:caf51943715b12af827696ec395bfa68f090a4c1a1d2509eb4e2cb69abbbdb33 \ + --hash=sha256:cb28c1f569f8d33b2b5dcd05d0e6ef7005d8639c54c2f0be824f05aedf715255 \ + --hash=sha256:cdad4ea3b4513b475e027be79e5a0ceac8ee1c113a1a11e5edc3c30c29f964d8 \ + --hash=sha256:cf47cfdabc2194a669dcf7a8dbba62e37a04c5041d2125fae0233b720da6f05c \ + --hash=sha256:d04cab0a54b9dba4d278fe955a1390da3cf71f57feb78ddc7cb67cbe0bd30323 \ + --hash=sha256:d422b945683e409000c888e384546dbab9009bb92f7c0b456e217988cf316107 \ + --hash=sha256:d80bf832ac7b1920ee29a426cdca335f96a2b5caa839811803e999b41ba9030d \ + --hash=sha256:da619979df60a940cd434084355c514c25cf8eb4cf9a508510682f6c851a4f7a \ + --hash=sha256:dafd4c44b74aa4bed4b250f1aed165b8ef5de743bcca3b88fc9619b6087093d2 \ + --hash=sha256:dca83c498b4650a91efcf7b88d669b170256bf8017a5db6f3e06c2bf031f57e0 \ + --hash=sha256:de2713f48c1ad57f89ac25b3cb7daed2156d8e822cf0eca9b96a6f990718cc41 \ + --hash=sha256:de4ed93a8c91debfd5a047be327b7cc8b0cc6afe32a716bbbc4aedca9e2a83af \ + --hash=sha256:df52098cde6d5e02fa75c1f6244f07971773adb4a26625edd5c18fee906fa84d \ + --hash=sha256:dfbf280da5f876d0b00c81f26bedce274e72a678c28845453885a9b3c22ae632 \ + --hash=sha256:e3730a48e5622e598293eee0762b09cff34dd3f271530f47b0894891281f051d \ + --hash=sha256:e5162afc9e0d1f9cae3b577d9c29ddbab3505ab39012cb794d94a005825bde21 \ + --hash=sha256:e5d524d68a474a9688336045bbf76cb0def88549c1b2ad9dbfec1fb7cfbe9170 \ + --hash=sha256:e99685fc95d386da368013e7fb4269dd39c30d99f812a8372d62f244f662709c \ + --hash=sha256:ea89a2458a1a75f87caabefe789c87539ea4e43b40f18cff526052e35bbb4fdf \ + --hash=sha256:ec671691e72dff75817386aa02d81e708b5a7ec0dec6669ec05213ff6b77e1bd \ + --hash=sha256:eed5ac260dd545fbc20da5f4f15e7efe36a55e0e7cf706e4ec005b491a9546a0 \ + --hash=sha256:f14440b9573a6f76b4ee4770c13f0b5921f71dde3b6fcb8dabbefd13b7fe05d7 \ + --hash=sha256:f405c93675d8d4c5ac87364bb38d06c988e11028a64b52a47158a355079661f3 \ + --hash=sha256:f53ec51f9d24e9638a40cabb95078ade8c99251945dad8d57bf4aabe86ecee35 \ + --hash=sha256:f61a9326f80ca59214d1cceb0a09bb2ece5b2563d4e0cd37bfd5515c28510674 \ + --hash=sha256:f7bf2496fa563c046d05e4d232d7b7fd61346e2402052064b773e5c378bf6f73 \ + --hash=sha256:fbaa70553ca116c77717f513e08815aec458e6b69a028d4028d403b3bc84ff37 \ + --hash=sha256:fc3e55a7db08dc9a6ed5fb7103019d2c1a38a349ac41901f9f66d7f95750942f \ + --hash=sha256:fc921b96fa95a097add244da36a1d9e4f3039160d1d30f1b35837bf108c21136 \ + --hash=sha256:fd0641abca296bc1a00183fe44f7fced8807ed49d501f188faa642d0e4975b83 \ + --hash=sha256:feac1045b3327a45944e7dcbeb57530339f6b17baff154df51ef8b0da34c8c12 \ + --hash=sha256:ff110acded3c22c033e637dd8896e411c7d3a11289b2edf041f86663dbc791e9 # via # jsonschema # referencing @@ -427,16 +596,100 @@ tomli==2.2.1 \ --hash=sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a \ --hash=sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7 # via -r requirements.in -typing-extensions==4.13.2 \ - --hash=sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c \ - --hash=sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef - # via -r requirements.in -urllib3==2.4.0 \ - --hash=sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466 \ - --hash=sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813 +typing-extensions==4.14.1 \ + --hash=sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36 \ + --hash=sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76 + # via + # -r requirements.in + # pygithub +urllib3==2.5.0 \ + --hash=sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760 \ + --hash=sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc # via # docker + # pygithub # requests +wrapt==1.17.2 \ + --hash=sha256:08e7ce672e35efa54c5024936e559469436f8b8096253404faeb54d2a878416f \ + --hash=sha256:0a6e821770cf99cc586d33833b2ff32faebdbe886bd6322395606cf55153246c \ + --hash=sha256:0b929ac182f5ace000d459c59c2c9c33047e20e935f8e39371fa6e3b85d56f4a \ + --hash=sha256:129a150f5c445165ff941fc02ee27df65940fcb8a22a61828b1853c98763a64b \ + --hash=sha256:13e6afb7fe71fe7485a4550a8844cc9ffbe263c0f1a1eea569bc7091d4898555 \ + --hash=sha256:1473400e5b2733e58b396a04eb7f35f541e1fb976d0c0724d0223dd607e0f74c \ + --hash=sha256:18983c537e04d11cf027fbb60a1e8dfd5190e2b60cc27bc0808e653e7b218d1b \ + --hash=sha256:1a7ed2d9d039bd41e889f6fb9364554052ca21ce823580f6a07c4ec245c1f5d6 \ + --hash=sha256:1e1fe0e6ab7775fd842bc39e86f6dcfc4507ab0ffe206093e76d61cde37225c8 \ + --hash=sha256:1fb5699e4464afe5c7e65fa51d4f99e0b2eadcc176e4aa33600a3df7801d6662 \ + --hash=sha256:2696993ee1eebd20b8e4ee4356483c4cb696066ddc24bd70bcbb80fa56ff9061 \ + --hash=sha256:35621ae4c00e056adb0009f8e86e28eb4a41a4bfa8f9bfa9fca7d343fe94f998 \ + --hash=sha256:36ccae62f64235cf8ddb682073a60519426fdd4725524ae38874adf72b5f2aeb \ + --hash=sha256:3cedbfa9c940fdad3e6e941db7138e26ce8aad38ab5fe9dcfadfed9db7a54e62 \ + --hash=sha256:3d57c572081fed831ad2d26fd430d565b76aa277ed1d30ff4d40670b1c0dd984 \ + --hash=sha256:3fc7cb4c1c744f8c05cd5f9438a3caa6ab94ce8344e952d7c45a8ed59dd88392 \ + --hash=sha256:4011d137b9955791f9084749cba9a367c68d50ab8d11d64c50ba1688c9b457f2 \ + --hash=sha256:40d615e4fe22f4ad3528448c193b218e077656ca9ccb22ce2cb20db730f8d306 \ + --hash=sha256:410a92fefd2e0e10d26210e1dfb4a876ddaf8439ef60d6434f21ef8d87efc5b7 \ + --hash=sha256:41388e9d4d1522446fe79d3213196bd9e3b301a336965b9e27ca2788ebd122f3 \ + --hash=sha256:468090021f391fe0056ad3e807e3d9034e0fd01adcd3bdfba977b6fdf4213ea9 \ + --hash=sha256:49703ce2ddc220df165bd2962f8e03b84c89fee2d65e1c24a7defff6f988f4d6 \ + --hash=sha256:4a721d3c943dae44f8e243b380cb645a709ba5bd35d3ad27bc2ed947e9c68192 \ + --hash=sha256:4afd5814270fdf6380616b321fd31435a462019d834f83c8611a0ce7484c7317 \ + --hash=sha256:4c82b8785d98cdd9fed4cac84d765d234ed3251bd6afe34cb7ac523cb93e8b4f \ + --hash=sha256:4db983e7bca53819efdbd64590ee96c9213894272c776966ca6306b73e4affda \ + --hash=sha256:582530701bff1dec6779efa00c516496968edd851fba224fbd86e46cc6b73563 \ + --hash=sha256:58455b79ec2661c3600e65c0a716955adc2410f7383755d537584b0de41b1d8a \ + --hash=sha256:58705da316756681ad3c9c73fd15499aa4d8c69f9fd38dc8a35e06c12468582f \ + --hash=sha256:5bb1d0dbf99411f3d871deb6faa9aabb9d4e744d67dcaaa05399af89d847a91d \ + --hash=sha256:5c803c401ea1c1c18de70a06a6f79fcc9c5acfc79133e9869e730ad7f8ad8ef9 \ + --hash=sha256:5cbabee4f083b6b4cd282f5b817a867cf0b1028c54d445b7ec7cfe6505057cf8 \ + --hash=sha256:612dff5db80beef9e649c6d803a8d50c409082f1fedc9dbcdfde2983b2025b82 \ + --hash=sha256:62c2caa1585c82b3f7a7ab56afef7b3602021d6da34fbc1cf234ff139fed3cd9 \ + --hash=sha256:69606d7bb691b50a4240ce6b22ebb319c1cfb164e5f6569835058196e0f3a845 \ + --hash=sha256:6d9187b01bebc3875bac9b087948a2bccefe464a7d8f627cf6e48b1bbae30f82 \ + --hash=sha256:6ed6ffac43aecfe6d86ec5b74b06a5be33d5bb9243d055141e8cabb12aa08125 \ + --hash=sha256:703919b1633412ab54bcf920ab388735832fdcb9f9a00ae49387f0fe67dad504 \ + --hash=sha256:766d8bbefcb9e00c3ac3b000d9acc51f1b399513f44d77dfe0eb026ad7c9a19b \ + --hash=sha256:80dd7db6a7cb57ffbc279c4394246414ec99537ae81ffd702443335a61dbf3a7 \ + --hash=sha256:8112e52c5822fc4253f3901b676c55ddf288614dc7011634e2719718eaa187dc \ + --hash=sha256:8c8b293cd65ad716d13d8dd3624e42e5a19cc2a2f1acc74b30c2c13f15cb61a6 \ + --hash=sha256:8fdbdb757d5390f7c675e558fd3186d590973244fab0c5fe63d373ade3e99d40 \ + --hash=sha256:91bd7d1773e64019f9288b7a5101f3ae50d3d8e6b1de7edee9c2ccc1d32f0c0a \ + --hash=sha256:95c658736ec15602da0ed73f312d410117723914a5c91a14ee4cdd72f1d790b3 \ + --hash=sha256:99039fa9e6306880572915728d7f6c24a86ec57b0a83f6b2491e1d8ab0235b9a \ + --hash=sha256:9a2bce789a5ea90e51a02dfcc39e31b7f1e662bc3317979aa7e5538e3a034f72 \ + --hash=sha256:9a7d15bbd2bc99e92e39f49a04653062ee6085c0e18b3b7512a4f2fe91f2d681 \ + --hash=sha256:9abc77a4ce4c6f2a3168ff34b1da9b0f311a8f1cfd694ec96b0603dff1c79438 \ + --hash=sha256:9e8659775f1adf02eb1e6f109751268e493c73716ca5761f8acb695e52a756ae \ + --hash=sha256:9fee687dce376205d9a494e9c121e27183b2a3df18037f89d69bd7b35bcf59e2 \ + --hash=sha256:a5aaeff38654462bc4b09023918b7f21790efb807f54c000a39d41d69cf552cb \ + --hash=sha256:a604bf7a053f8362d27eb9fefd2097f82600b856d5abe996d623babd067b1ab5 \ + --hash=sha256:abbb9e76177c35d4e8568e58650aa6926040d6a9f6f03435b7a522bf1c487f9a \ + --hash=sha256:acc130bc0375999da18e3d19e5a86403667ac0c4042a094fefb7eec8ebac7cf3 \ + --hash=sha256:b18f2d1533a71f069c7f82d524a52599053d4c7166e9dd374ae2136b7f40f7c8 \ + --hash=sha256:b4e42a40a5e164cbfdb7b386c966a588b1047558a990981ace551ed7e12ca9c2 \ + --hash=sha256:b5e251054542ae57ac7f3fba5d10bfff615b6c2fb09abeb37d2f1463f841ae22 \ + --hash=sha256:b60fb58b90c6d63779cb0c0c54eeb38941bae3ecf7a73c764c52c88c2dcb9d72 \ + --hash=sha256:b870b5df5b71d8c3359d21be8f0d6c485fa0ebdb6477dda51a1ea54a9b558061 \ + --hash=sha256:ba0f0eb61ef00ea10e00eb53a9129501f52385c44853dbd6c4ad3f403603083f \ + --hash=sha256:bb87745b2e6dc56361bfde481d5a378dc314b252a98d7dd19a651a3fa58f24a9 \ + --hash=sha256:bb90fb8bda722a1b9d48ac1e6c38f923ea757b3baf8ebd0c82e09c5c1a0e7a04 \ + --hash=sha256:bc570b5f14a79734437cb7b0500376b6b791153314986074486e0b0fa8d71d98 \ + --hash=sha256:c86563182421896d73858e08e1db93afdd2b947a70064b813d515d66549e15f9 \ + --hash=sha256:c958bcfd59bacc2d0249dcfe575e71da54f9dcf4a8bdf89c4cb9a68a1170d73f \ + --hash=sha256:d18a4865f46b8579d44e4fe1e2bcbc6472ad83d98e22a26c963d46e4c125ef0b \ + --hash=sha256:d5e2439eecc762cd85e7bd37161d4714aa03a33c5ba884e26c81559817ca0925 \ + --hash=sha256:e3890b508a23299083e065f435a492b5435eba6e304a7114d2f919d400888cc6 \ + --hash=sha256:e496a8ce2c256da1eb98bd15803a79bee00fc351f5dfb9ea82594a3f058309e0 \ + --hash=sha256:e8b2816ebef96d83657b56306152a93909a83f23994f4b30ad4573b00bd11bb9 \ + --hash=sha256:eaf675418ed6b3b31c7a989fd007fa7c3be66ce14e5c3b27336383604c9da85c \ + --hash=sha256:ec89ed91f2fa8e3f52ae53cd3cf640d6feff92ba90d62236a81e4e563ac0e991 \ + --hash=sha256:ecc840861360ba9d176d413a5489b9a0aff6d6303d7e733e2c4623cfa26904a6 \ + --hash=sha256:f09b286faeff3c750a879d336fb6d8713206fc97af3adc14def0cdd349df6000 \ + --hash=sha256:f393cda562f79828f38a819f4788641ac7c4085f30f1ce1a68672baa686482bb \ + --hash=sha256:f917c1180fdb8623c2b75a99192f4025e412597c50b2ac870f156de8fb101119 \ + --hash=sha256:fc78a84e2dfbc27afe4b2bd7c80c8db9bca75cc5b85df52bfe634596a1da846b \ + --hash=sha256:ff04ef6eec3eee8a5efef2401495967a916feaa353643defcc03fc74fe213b58 + # via deprecated zstandard==0.23.0 \ --hash=sha256:034b88913ecc1b097f528e42b539453fa82c3557e414b3de9d5632c80439a473 \ --hash=sha256:0a7f0804bb3799414af278e9ad51be25edf67f78f916e08afdb983e74161b916 \ diff --git a/src/github.rs b/src/github.rs index 0d3bc97..a90b961 100644 --- a/src/github.rs +++ b/src/github.rs @@ -17,10 +17,9 @@ use { }, rayon::prelude::*, reqwest::{Client, StatusCode}, - reqwest_middleware::{self, ClientWithMiddleware}, reqwest_retry::{ - default_on_request_failure, policies::ExponentialBackoff, RetryTransientMiddleware, - Retryable, RetryableStrategy, + default_on_request_failure, policies::ExponentialBackoff, RetryPolicy, Retryable, + RetryableStrategy, }, sha2::{Digest, Sha256}, std::{ @@ -28,6 +27,7 @@ use { io::Read, path::PathBuf, str::FromStr, + time::{Duration, SystemTime}, }, url::Url, zip::ZipArchive, @@ -65,12 +65,19 @@ async fn fetch_artifact( Ok(res) } +enum UploadSource { + Filename(PathBuf), + Data(Bytes), +} + async fn upload_release_artifact( - client: &ClientWithMiddleware, + client: &Client, + retry_policy: &impl RetryPolicy, + retryable_strategy: &impl RetryableStrategy, auth_token: String, release: &Release, filename: String, - data: Bytes, + body: UploadSource, dry_run: bool, ) -> Result<()> { if release.assets.iter().any(|asset| asset.name == filename) { @@ -93,17 +100,52 @@ async fn upload_release_artifact( return Ok(()); } - // Octocrab doesn't yet support release artifact upload. And the low-level HTTP API - // forces the use of strings on us. So we have to make our own HTTP client. - - let response = client - .put(url) - .header("Authorization", format!("Bearer {auth_token}")) - .header("Content-Length", data.len()) - .header("Content-Type", "application/x-tar") - .body(data) - .send() - .await?; + // Octocrab's high-level API for uploading release artifacts doesn't yet support streaming + // bodies, and their low-level API isn't more helpful than using our own HTTP client. + // + // Because we are streaming the body, we can't use the standard retry middleware for reqwest + // (see e.g. https://github.com/seanmonstar/reqwest/issues/2416), so we have to recreate the + // request on each retry and handle the retry logic ourself. This logic is inspired by + // uv/crates/uv-publish/src/lib.rs (which has the same problem), which in turn is inspired by + // reqwest-middleware/reqwest-retry/src/middleware.rs. + // + // (While Octocrab's API would work fine for the non-streaming case, we just use this function + // for both cases so that we can make a homogeneous Vec later in the file.) + + let mut n_past_retries = 0; + let start_time = SystemTime::now(); + let response = loop { + let request = client + .put(url.clone()) + .timeout(Duration::from_secs(60)) + .header("Authorization", format!("Bearer {auth_token}")) + .header("Content-Type", "application/octet-stream"); + let request = match body { + UploadSource::Filename(ref path) => { + let file = tokio::fs::File::open(&path).await?; + let len = file.metadata().await?.len(); + request.header("Content-Length", len).body(file) + } + UploadSource::Data(ref bytes) => request + .header("Content-Length", bytes.len()) + .body(bytes.clone()), + }; + let result = request.send().await.map_err(|e| e.into()); + + if retryable_strategy.handle(&result) == Some(Retryable::Transient) { + let retry_decision = retry_policy.should_retry(start_time, n_past_retries); + if let reqwest_retry::RetryDecision::Retry { execute_after } = retry_decision { + println!("retrying upload to {url} after {result:?}"); + let duration = execute_after + .duration_since(SystemTime::now()) + .unwrap_or_else(|_| Duration::default()); + tokio::time::sleep(duration).await; + n_past_retries += 1; + continue; + } + } + break result?; + }; if !response.status().is_success() { return Err(anyhow!("HTTP {}", response.status())); @@ -112,6 +154,20 @@ async fn upload_release_artifact( Ok(()) } +fn new_github_client(args: &ArgMatches) -> Result<(Octocrab, String)> { + let token = args + .get_one::("token") + .expect("token should be specified") + .to_string(); + let github_uri = args.get_one::("github-uri"); + + let mut builder = OctocrabBuilder::new().personal_token(token.clone()); + if let Some(github_uri) = github_uri { + builder = builder.base_uri(github_uri.clone())?; + } + Ok((builder.build()?, token)) +} + pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<()> { let dest_dir = args .get_one::("dest") @@ -121,13 +177,7 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<() .expect("organization should be set"); let repo = args.get_one::("repo").expect("repo should be set"); - let client = OctocrabBuilder::new() - .personal_token( - args.get_one::("token") - .expect("token should be required argument") - .to_string(), - ) - .build()?; + let (client, _) = new_github_client(args)?; let release_version_range = pep440_rs::VersionSpecifier::from_str(">=3.9")?; @@ -145,7 +195,6 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<() wf.path.as_str(), ".github/workflows/macos.yml" | ".github/workflows/linux.yml" - | ".github/workflows/windows.yml" ) { workflow_names.insert(wf.id, wf.name); @@ -176,6 +225,7 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<() workflows .list_runs(format!("{workflow_id}")) .event("push") + .event("pull_request") .status("success") .send() .await? @@ -207,10 +257,11 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches) -> Result<() .await?; for artifact in artifacts { - if matches!( - artifact.name.as_str(), - "pythonbuild" | "toolchain" - ) || artifact.name.contains("install-only") + if matches!(artifact.name.as_str(), "pythonbuild" | "toolchain") + || artifact.name.contains("install-only") + || artifact.name.contains("dockerbuild") + || artifact.name.contains("crate-") + || artifact.name.contains("image-") { continue; } @@ -358,10 +409,6 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<( .get_one::("tag") .expect("tag should be specified"); let ignore_missing = args.get_flag("ignore_missing"); - let token = args - .get_one::("token") - .expect("token should be specified") - .to_string(); let organization = args .get_one::("organization") .expect("organization should be specified"); @@ -451,9 +498,7 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<( return Err(anyhow!("missing {} release artifacts", missing.len())); } - let client = OctocrabBuilder::new() - .personal_token(token.clone()) - .build()?; + let (client, token) = new_github_client(args)?; let repo_handler = client.repos(organization, repo); let releases = repo_handler.releases(); @@ -473,12 +518,7 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<( let mut digests = BTreeMap::new(); let retry_policy = ExponentialBackoff::builder().build_with_max_retries(5); - let raw_client = reqwest_middleware::ClientBuilder::new(Client::new()) - .with(RetryTransientMiddleware::new_with_policy_and_strategy( - retry_policy, - GitHubUploadRetryStrategy, - )) - .build(); + let raw_client = Client::new(); { let mut fs = vec![]; @@ -488,31 +528,31 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<( continue; } - let file_data = Bytes::copy_from_slice(&std::fs::read(dist_dir.join(&source))?); - - let mut digest = Sha256::new(); - digest.update(&file_data); - - let digest = hex::encode(digest.finalize()); - - digests.insert(dest.clone(), digest.clone()); - + let local_filename = dist_dir.join(&source); fs.push(upload_release_artifact( &raw_client, + &retry_policy, + &GitHubUploadRetryStrategy, token.clone(), &release, dest.clone(), - file_data, - dry_run, - )); - fs.push(upload_release_artifact( - &raw_client, - token.clone(), - &release, - format!("{}.sha256", dest), - Bytes::copy_from_slice(format!("{}\n", digest).as_bytes()), + UploadSource::Filename(local_filename.clone()), dry_run, )); + + // reqwest wants to take ownership of the body, so it's hard for us to do anything + // clever with reading the file once and calculating the sha256sum while we read. + // So we open and read the file again. + let digest = { + let file = tokio::fs::File::open(local_filename).await?; + let mut stream = tokio_util::io::ReaderStream::with_capacity(file, 1048576); + let mut hasher = Sha256::new(); + while let Some(chunk) = stream.next().await { + hasher.update(&chunk?); + } + hex::encode(hasher.finalize()) + }; + digests.insert(dest.clone(), digest.clone()); } let mut buffered = futures::stream::iter(fs).buffer_unordered(16); @@ -532,10 +572,12 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<( upload_release_artifact( &raw_client, + &retry_policy, + &GitHubUploadRetryStrategy, token.clone(), &release, "SHA256SUMS".to_string(), - Bytes::copy_from_slice(shasums.as_bytes()), + UploadSource::Data(Bytes::copy_from_slice(shasums.as_bytes())), dry_run, ) .await?; @@ -559,8 +601,8 @@ pub async fn command_upload_release_distributions(args: &ArgMatches) -> Result<( let mut stream = client .repos(organization, repo) - .releases() - .stream_asset(shasums_asset.id) + .release_assets() + .stream(shasums_asset.id.into_inner()) .await?; let mut asset_bytes = Vec::::new(); diff --git a/src/github_api_tester.py b/src/github_api_tester.py new file mode 100755 index 0000000..9ff4bc0 --- /dev/null +++ b/src/github_api_tester.py @@ -0,0 +1,340 @@ +#!/usr/bin/env -S uv run +# +# A fake GitHub API server for testing upload-release-distributions's +# behavior in the presence of API failures. +# +# Call with no arguments or with pytest CLI arguments to run the tests +# at the bottom which invoke `cargo run`. +# +# Call with one argument "serve" to start an HTTP server on 0.0.0.0. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +# /// script +# requires-python = ">=3.13" +# dependencies = [ +# "quart>=0.20.0", +# "quart-trio>=0.12.0", +# # Pinned because we mess with hypercorn internals, see below. +# "hypercorn==0.17.3", +# "pytest", +# "pytest-trio", +# ] +# /// + +import dataclasses +import hashlib +import logging +import os +import sys +from collections.abc import Callable + +import hypercorn +import pytest +import quart +import trio +from quart import request +from quart_trio import QuartTrio + +app = QuartTrio(__name__) +app.config["MAX_CONTENT_LENGTH"] = None + + +async def drop_connection(): + """Drop the (HTTP/1.1) connection belonging to the current Quart request.""" + # We need to do two things: + # - Convince hypercorn (specifically, around HTTPStream.app_send()) + # that it doesn't need to send a 500 and can just close the socket. + # - Convince h11's state machine that it's okay to close the socket + # without sending a response. + # We can't do this at the ASGI layer: hypercorn will insert the 500 + # for protocol compliance if the ASGI app doesn't provide a + # response. We need to modify the actual HTTP server, either with a + # pull request or by digging into its internals as follows: + # - Grab the HTTPStream whose bound method app_send was passed into + # the Quart request + # - Grab the H11Protocol whose bound method stream_send was passed + # into the HTTPStream's constructor + # - Tell the H11Protocol's underlying h11 state machine to act as if + # the remote side errored, so it thinks dropping the connection is + # the appropriate next step and not misbehavior on our end + # - Tell the HTTPStream to move the state machine forward with no + # further send on our side, which will drop the connection (and + # not consider it for keepalive) + import hypercorn.protocol as hp + + http_stream: hp.http_stream.HTTPStream = request._send_push_promise.args[0].__self__ + protocol: hp.h11.H11Protocol = http_stream.send.__self__ + protocol.connection._process_error(protocol.connection.their_role) + await http_stream.send(hp.events.EndBody(stream_id=http_stream.stream_id)) + await http_stream.app_send(None) + + # Some other things I tried, kept for reference: + # http_stream.state = hypercorn.protocol.http_stream.ASGIHTTPState.RESPONSE + # await http_stream._send_closed() + # http_stream.state = hypercorn.protocol.http_stream.ASGIHTTPState.CLOSED + + +# The following GitHub API datatypes are complete enough to satisfy +# octocrab's deserialization. + + +@dataclasses.dataclass +class Asset: + name: str + label: str | None + sha256: str + contents: bytes | None + + _ASSETS = [] + + def __post_init__(self): + self.id = len(self._ASSETS) + self._ASSETS.append(self) + + def render(self) -> dict: + return { + "url": quart.url_for("get_asset", id=self.id, _external=True), + "browser_download_url": "https://github.invalid/unneeded", + "id": self.id, + "node_id": "fakenode", + "name": self.name, + "label": self.label, + "state": "uploaded", + "content_type": "application/octet-stream", + "size": 1000, + "download_count": 1000, + "created_at": "2020-01-01T00:00:00Z", + "updated_at": "2020-01-01T00:00:00Z", + "uploader": None, + } + + +@dataclasses.dataclass +class Upload: + name: str + label: str | None + + def __post_init__(self): + self.hasher = hashlib.sha256() + if self.name == "SHA256SUMS": + self.contents = b"" + else: + self.contents = None + + def update(self, chunk: bytes) -> None: + self.hasher.update(chunk) + if self.contents is not None: + self.contents += chunk + + def to_asset(self) -> Asset: + return Asset(self.name, self.label, self.hasher.hexdigest(), self.contents) + + +@dataclasses.dataclass +class Release: + release_id: int + tag_name: str + assets: list = dataclasses.field(default_factory=list) + # fault0 and fault1 are called before and after receiving the first + # chunk of a PUT request, respectively. Each is called once per + # release - the first upload that hits it will disarm it. + fault0: Callable[[], None] | None = None + fault1: Callable[[], None] | None = None + + def render(self) -> dict: + upload_asset = quart.url_for( + "upload_asset", release=self.release_id, _external=True + ) + return { + "url": request.url, + "html_url": "https://github.invalid/unneeded", + "assets_url": "https://github.invalid/unneeded", + "upload_url": upload_asset + "{?name,label}", + "id": self.release_id, + "node_id": "fakenode", + "tag_name": self.tag_name, + "target_commitish": "main", + "draft": False, + "prerelease": True, + "assets": [i.render() for i in self.assets], + } + + +releases = [ + Release(1, "basic"), + Release(11, "early-drop", fault0=drop_connection), + Release(12, "late-drop", fault1=drop_connection), + Release(4011, "early-401", fault0=lambda: quart.abort(401)), + Release(4012, "late-401", fault1=lambda: quart.abort(401)), + Release(4031, "early-403", fault0=lambda: quart.abort(403)), + Release(4032, "late-403", fault1=lambda: quart.abort(403)), + Release(5001, "early-500", fault0=lambda: quart.abort(500)), + Release(5002, "late-500", fault1=lambda: quart.abort(500)), +] + + +def get_release(*, tag=None, release=None) -> Release: + if tag is not None: + condition = lambda r: r.tag_name == tag + elif release is not None: + condition = lambda r: r.release_id == release + else: + raise TypeError("tag or release must be set") + + for r in releases: + if condition(r): + return r + quart.abort(404, response=quart.jsonify({"message": "Not Found", "status": "404"})) + + +# GitHub API functions + + +@app.route("/repos///releases/tags/") +async def get_release_by_tag(org, repo, tag): + return get_release(tag=tag).render() + + +@app.route("/repos///releases/") +async def get_release_by_id(org, repo, release): + return get_release(release=release).render() + + +@app.put("/upload//assets") +async def upload_asset(release): + filename = request.args["name"] + release = get_release(release=release) + + if (fault := release.fault0) is not None: + logging.info(f"{filename}: injecting fault0") + release.fault0 = None + return await fault() + + logging.info(f"{filename}: upload begin") + upload = Upload(filename, request.args.get("label")) + async for chunk in request.body: + logging.debug(f"{filename}: {len(chunk)=}") + upload.update(chunk) + if (fault := release.fault1) is not None: + if "SHA256" not in filename: + logging.info(f"{filename}: injecting fault1") + release.fault1 = None + return await fault() + + asset = upload.to_asset() + logging.info(f"{filename}: upload complete, {asset.sha256=}") + release.assets.append(asset) + return asset.render() + + +@app.route("/get_asset/") +@app.route("/repos///releases/assets/") +async def get_asset(id, org=None, repo=None): + try: + asset = Asset._ASSETS[id] + except IndexError: + quart.abort( + 404, response=quart.jsonify({"message": "Not Found", "status": "404"}) + ) + + if "application/octet-stream" in request.accept_mimetypes: + if asset.contents is None: + print( + f"USAGE ERROR: Received request for contents of {asset.filename=} which was not stored" + ) + return "Did not store contents", 410 + return asset.contents + else: + return asset.render() + + +# Generic upload function, useful for testing clients in isolation + + +@app.put("/file/") +async def upload_file(path): + logging.info(f"{path}: upload begin") + s = hashlib.sha256() + async for chunk in request.body: + logging.debug(f"{path}: {len(chunk)=}") + if "drop" in request.args: + await drop_connection() + s.update(chunk) + digest = s.hexdigest() + logging.info(f"{path}: {digest=}") + return f"{digest} {path}\n", 500 + + +# Test cases + + +@pytest.fixture +async def server(nursery): + await nursery.start(app.run_task) + + +FILENAME = "cpython-3.0.0-x86_64-unknown-linux-gnu-install_only-19700101T1234.tar.gz" +SHA256_20MEG = "9e21c61969cd3e077a1b2b58ddb583b175e13c6479d2d83912eaddc23c0cdd52" + + +@pytest.fixture(scope="session") +def upload_release_distributions(tmp_path_factory): + dist = tmp_path_factory.mktemp("dist") + filename = dist / FILENAME + filename.touch() + os.truncate(filename, 20_000_000) + + async def upload_release_distributions(*args): + return await trio.run_process( + [ + "cargo", + "run", + "--", + "upload-release-distributions", + "--github-uri", + "http://localhost:5000", + "--token", + "no-token-needed", + "--dist", + dist, + "--datetime", + "19700101T1234", + "--ignore-missing", + ] + + list(args) + ) + + return upload_release_distributions + + +# TODO: test all of [r.tag_name for r in releases] +TAGS_TO_TEST = ["basic", "early-drop", "late-drop", "early-403", "late-403"] + + +@pytest.mark.parametrize("tag", TAGS_TO_TEST) +async def test_upload(server, upload_release_distributions, tag): + with trio.fail_after(300): + await upload_release_distributions("--tag", tag) + release = get_release(tag=tag) + assets = sorted(release.assets, key=lambda a: a.name) + assert len(assets) == 2 + assert assets[0].name == "SHA256SUMS" + filename = FILENAME.replace("3.0.0", f"3.0.0+{tag}").replace("-19700101T1234", "") + assert assets[1].name == filename + assert assets[1].sha256 == SHA256_20MEG + assert assets[0].contents == f"{SHA256_20MEG} {filename}\n".encode() + + +# Work around https://github.com/pgjones/hypercorn/issues/238 not being in a release +# Without it, test failures are unnecessarily noisy +hypercorn.trio.lifespan.LifespanFailureError = trio.Cancelled + +if __name__ == "__main__": + if len(sys.argv) > 1 and sys.argv[1] == "serve": + logging.basicConfig(level=logging.INFO) + app.run("0.0.0.0") + else: + pytest.main(["-o", "trio_mode=true", __file__] + sys.argv[1:]) diff --git a/src/main.rs b/src/main.rs index df441e1..c8d422e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,6 +70,12 @@ fn main_impl() -> Result<()> { .action(ArgAction::Set) .default_value("python-build-standalone") .help("GitHub repository name"), + ) + .arg( + Arg::new("github-uri") + .long("github-uri") + .action(ArgAction::Set) + .help("Alternative GitHub URI"), ), ); @@ -154,6 +160,12 @@ fn main_impl() -> Result<()> { .action(ArgAction::Set) .default_value("python-build-standalone") .help("GitHub repository name"), + ) + .arg( + Arg::new("github-uri") + .long("github-uri") + .action(ArgAction::Set) + .help("Alternative GitHub URI"), ), ); diff --git a/src/release.rs b/src/release.rs index 60e46c9..d427c3b 100644 --- a/src/release.rs +++ b/src/release.rs @@ -104,132 +104,24 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: }, ); - // Windows. - h.insert( - "i686-pc-windows-msvc", - TripleRelease { - suffixes: vec!["pgo"], - install_only_suffix: "pgo", - python_version_requirement: None, - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: vec!["freethreaded+pgo"], - }], - }, - ); - h.insert( - "x86_64-pc-windows-msvc", - TripleRelease { - suffixes: vec!["pgo"], - install_only_suffix: "pgo", - python_version_requirement: None, - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: vec!["freethreaded+pgo"], - }], - }, - ); // Linux. let linux_suffixes_pgo = vec!["debug", "pgo+lto"]; - let linux_suffixes_nopgo = vec!["debug", "lto", "noopt"]; - let linux_suffixes_musl = vec![ - "debug", - "lto", - "noopt", - "debug+static", - "lto+static", - "noopt+static", - ]; - let linux_suffixes_musl_freethreaded = vec![ - "freethreaded+debug", - "freethreaded+lto", - "freethreaded+noopt", - ]; let linux_suffixes_pgo_freethreaded = vec!["freethreaded+debug", "freethreaded+pgo+lto"]; - let linux_suffixes_nopgo_freethreaded = vec![ - "freethreaded+debug", - "freethreaded+lto", - "freethreaded+noopt", - ]; h.insert( "aarch64-unknown-linux-gnu", TripleRelease { - suffixes: linux_suffixes_nopgo.clone(), - install_only_suffix: "lto", + suffixes: linux_suffixes_pgo.clone(), + install_only_suffix: "pgo+lto", python_version_requirement: None, conditional_suffixes: vec![ConditionalSuffixes { python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_nopgo_freethreaded.clone(), - }], - }, - ); - - h.insert( - "ppc64le-unknown-linux-gnu", - TripleRelease { - suffixes: linux_suffixes_nopgo.clone(), - install_only_suffix: "lto", - python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()), - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_nopgo_freethreaded.clone(), - }], - }, - ); - - h.insert( - "riscv64-unknown-linux-gnu", - TripleRelease { - suffixes: linux_suffixes_nopgo.clone(), - install_only_suffix: "lto", - python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()), - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_nopgo_freethreaded.clone(), - }], - }, - ); - - h.insert( - "s390x-unknown-linux-gnu", - TripleRelease { - suffixes: linux_suffixes_nopgo.clone(), - install_only_suffix: "lto", - python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()), - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_nopgo_freethreaded.clone(), - }], - }, - ); - - h.insert( - "armv7-unknown-linux-gnueabi", - TripleRelease { - suffixes: linux_suffixes_nopgo.clone(), - install_only_suffix: "lto", - python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()), - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_nopgo_freethreaded.clone(), + suffixes: linux_suffixes_pgo_freethreaded.clone(), }], }, ); - h.insert( - "armv7-unknown-linux-gnueabihf", - TripleRelease { - suffixes: linux_suffixes_nopgo.clone(), - install_only_suffix: "lto", - python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()), - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_nopgo_freethreaded.clone(), - }], - }, - ); h.insert( "x86_64-unknown-linux-gnu", @@ -243,90 +135,6 @@ pub static RELEASE_TRIPLES: Lazy> = Lazy:: }], }, ); - h.insert( - "x86_64_v2-unknown-linux-gnu", - TripleRelease { - suffixes: linux_suffixes_pgo.clone(), - install_only_suffix: "pgo+lto", - python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()), - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_pgo_freethreaded.clone(), - }], - }, - ); - h.insert( - "x86_64_v3-unknown-linux-gnu", - TripleRelease { - suffixes: linux_suffixes_pgo.clone(), - install_only_suffix: "pgo+lto", - python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()), - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_pgo_freethreaded.clone(), - }], - }, - ); - h.insert( - "x86_64_v4-unknown-linux-gnu", - TripleRelease { - suffixes: linux_suffixes_pgo.clone(), - install_only_suffix: "pgo+lto", - python_version_requirement: Some(VersionSpecifier::from_str(">=3.9").unwrap()), - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_pgo_freethreaded.clone(), - }], - }, - ); - h.insert( - "x86_64-unknown-linux-musl", - TripleRelease { - suffixes: linux_suffixes_musl.clone(), - install_only_suffix: "lto", - python_version_requirement: None, - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_musl_freethreaded.clone(), - }], - }, - ); - h.insert( - "x86_64_v2-unknown-linux-musl", - TripleRelease { - suffixes: linux_suffixes_musl.clone(), - install_only_suffix: "lto", - python_version_requirement: None, - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_musl_freethreaded.clone(), - }], - }, - ); - h.insert( - "x86_64_v3-unknown-linux-musl", - TripleRelease { - suffixes: linux_suffixes_musl.clone(), - install_only_suffix: "lto", - python_version_requirement: None, - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_musl_freethreaded.clone(), - }], - }, - ); - h.insert( - "x86_64_v4-unknown-linux-musl", - TripleRelease { - suffixes: linux_suffixes_musl.clone(), - install_only_suffix: "lto", - python_version_requirement: None, - conditional_suffixes: vec![ConditionalSuffixes { - python_version_requirement: VersionSpecifier::from_str(">=3.13").unwrap(), - suffixes: linux_suffixes_musl_freethreaded.clone(), - }], - }, - ); h }); diff --git a/src/validation.rs b/src/validation.rs index 19aace0..8a06bf8 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -9,16 +9,16 @@ use { normalize_path::NormalizePath, object::{ elf::{ - FileHeader32, FileHeader64, ET_DYN, ET_EXEC, STB_GLOBAL, STB_WEAK, STV_DEFAULT, + FileHeader32, FileHeader64, ET_DYN, ET_EXEC, SHN_UNDEF, STB_GLOBAL, STB_WEAK, STV_DEFAULT, STV_HIDDEN, }, - macho::{MachHeader32, MachHeader64, MH_OBJECT, MH_TWOLEVEL}, + macho::{LC_CODE_SIGNATURE, MH_OBJECT, MH_TWOLEVEL, MachHeader32, MachHeader64}, read::{ elf::{Dyn, FileHeader, SectionHeader, Sym}, - macho::{LoadCommandVariant, MachHeader, Nlist}, + macho::{LoadCommandVariant, MachHeader, Nlist, Section, Segment}, pe::{ImageNtHeaders, PeFile, PeFile32, PeFile64}, }, - Endianness, FileKind, Object, SectionIndex, SymbolScope, + Architecture, Endianness, FileKind, Object, SectionIndex, SymbolScope, }, once_cell::sync::Lazy, std::{ @@ -33,7 +33,9 @@ use { const RECOGNIZED_TRIPLES: &[&str] = &[ "aarch64-apple-darwin", "aarch64-apple-ios", + "aarch64-pc-windows-msvc", "aarch64-unknown-linux-gnu", + "aarch64-unknown-linux-musl", "armv7-unknown-linux-gnueabi", "armv7-unknown-linux-gnueabihf", "arm64-apple-tvos", @@ -117,11 +119,13 @@ const PE_ALLOWED_LIBRARIES: &[&str] = &[ "libcrypto-1_1.dll", "libcrypto-1_1-x64.dll", "libcrypto-3.dll", + "libcrypto-3-arm64.dll", "libcrypto-3-x64.dll", "libffi-8.dll", "libssl-1_1.dll", "libssl-1_1-x64.dll", "libssl-3.dll", + "libssl-3-arm64.dll", "libssl-3-x64.dll", "python3.dll", "python39.dll", @@ -137,8 +141,14 @@ const PE_ALLOWED_LIBRARIES: &[&str] = &[ "tk86t.dll", ]; -// CPython 3.14 uses tcl/tk 8.6.14+ which includes a bundled zlib and dynamically links to msvcrt. -const PE_ALLOWED_LIBRARIES_314: &[&str] = &["msvcrt.dll", "zlib1.dll"]; +// CPython 3.14 and ARM64 use a newer version of tcl/tk (8.6.14+) which includes a bundled zlib that +// dynamically links some system libraries +const PE_ALLOWED_LIBRARIES_314: &[&str] = &[ + "zlib1.dll", + "api-ms-win-crt-private-l1-1-0.dll", // zlib loads this library on arm64, 3.14+ + "msvcrt.dll", // zlib loads this library +]; +const PE_ALLOWED_LIBRARIES_ARM64: &[&str] = &["msvcrt.dll", "zlib1.dll"]; static GLIBC_MAX_VERSION_BY_TRIPLE: Lazy>> = Lazy::new(|| { @@ -202,6 +212,10 @@ static GLIBC_MAX_VERSION_BY_TRIPLE: Lazy>> = + Lazy::new(|| { + [ + ( + // libcrypt is provided by the system, but only on older distros. + "_crypt", + vec!["libcrypt.so.1"], + ), + ( + // libtcl and libtk are shipped in our distribution. + "_tkinter", + vec!["libtcl8.6.so", "libtk8.6.so"], + ), + ] + .iter() + .cloned() + .collect() + }); + static DARWIN_ALLOWED_DYLIBS: Lazy> = Lazy::new(|| { [ MachOAllowedDylib { @@ -492,11 +525,36 @@ static IOS_ALLOWED_DYLIBS: Lazy> = Lazy::new(|| { .to_vec() }); +static ALLOWED_DYLIBS_BY_MODULE: Lazy>> = + Lazy::new(|| { + [( + // libtcl and libtk are shipped in our distribution. + "_tkinter", + vec![ + MachOAllowedDylib { + name: "@rpath/libtcl8.6.dylib".to_string(), + max_compatibility_version: "8.6.0".try_into().unwrap(), + required: true, + }, + MachOAllowedDylib { + name: "@rpath/libtk8.6.dylib".to_string(), + max_compatibility_version: "8.6.0".try_into().unwrap(), + required: true, + }, + ], + )] + .iter() + .cloned() + .collect() + }); + static PLATFORM_TAG_BY_TRIPLE: Lazy> = Lazy::new(|| { [ ("aarch64-apple-darwin", "macosx-11.0-arm64"), ("aarch64-apple-ios", "iOS-aarch64"), + ("aarch64-pc-windows-msvc", "win-arm64"), ("aarch64-unknown-linux-gnu", "linux-aarch64"), + ("aarch64-unknown-linux-musl", "linux-aarch64"), ("armv7-unknown-linux-gnueabi", "linux-arm"), ("armv7-unknown-linux-gnueabihf", "linux-arm"), ("i686-pc-windows-msvc", "win32"), @@ -534,9 +592,12 @@ const ELF_BANNED_SYMBOLS: &[&str] = &[ /// We use this list to spot test behavior of symbols belonging to dependency packages. /// The list is obviously not complete. const DEPENDENCY_PACKAGE_SYMBOLS: &[&str] = &[ - // libX11 - "XClearWindow", - "XFlush", + /* TODO(geofft): Tk provides these as no-op stubs on macOS, make it + * stop doing that so we can re-enable the check + * // libX11 + * "XClearWindow", + * "XFlush", + */ // OpenSSL "BIO_ADDR_new", "BN_new", @@ -581,6 +642,11 @@ const DEPENDENCY_PACKAGE_SYMBOLS: &[&str] = &[ // liblzma "lzma_index_init", "lzma_stream_encoder", +]; + +// TODO(geofft): Conditionally prohibit these exported symbols +// everywhere except libtcl and libtk. This should be a hashmap +const _DEPENDENCY_PACKAGE_SYMBOLS_BUNDLED: &[&str] = &[ // tcl "Tcl_Alloc", "Tcl_ChannelName", @@ -589,6 +655,10 @@ const DEPENDENCY_PACKAGE_SYMBOLS: &[&str] = &[ "TkBindInit", "TkCreateFrame", "Tk_FreeGC", + // _ctypes_test module + "my_free", + "mystrdup", + "top", ]; const PYTHON_EXPORTED_SYMBOLS: &[&str] = &[ @@ -768,6 +838,7 @@ const GLOBAL_EXTENSIONS_PYTHON_3_14: &[&str] = &[ "_zoneinfo", "_hmac", "_types", + "_zstd", ]; const GLOBAL_EXTENSIONS_MACOS: &[&str] = &["_scproxy"]; @@ -803,8 +874,7 @@ const GLOBAL_EXTENSIONS_WINDOWS: &[&str] = &[ "winsound", ]; -// TODO(zanieb): Move `_zstd` to non-Windows specific once we add support on Unix. -const GLOBAL_EXTENSIONS_WINDOWS_3_14: &[&str] = &["_wmi", "_zstd"]; +const GLOBAL_EXTENSIONS_WINDOWS_3_14: &[&str] = &["_wmi"]; const GLOBAL_EXTENSIONS_WINDOWS_PRE_3_13: &[&str] = &["_msi"]; @@ -812,7 +882,7 @@ const GLOBAL_EXTENSIONS_WINDOWS_PRE_3_13: &[&str] = &["_msi"]; const GLOBAL_EXTENSIONS_WINDOWS_NO_STATIC: &[&str] = &["_testinternalcapi", "_tkinter"]; /// Extension modules that should be built as shared libraries. -const SHARED_LIBRARY_EXTENSIONS: &[&str] = &["_crypt"]; +const SHARED_LIBRARY_EXTENSIONS: &[&str] = &["_crypt", "_ctypes_test", "_tkinter"]; const PYTHON_VERIFICATIONS: &str = include_str!("verify_distribution.py"); @@ -885,6 +955,7 @@ fn validate_elf>( let wanted_cpu_type = match target_triple { "aarch64-unknown-linux-gnu" => object::elf::EM_AARCH64, + "aarch64-unknown-linux-musl" => object::elf::EM_AARCH64, "armv7-unknown-linux-gnueabi" => object::elf::EM_ARM, "armv7-unknown-linux-gnueabihf" => object::elf::EM_ARM, "i686-unknown-linux-gnu" => object::elf::EM_386, @@ -957,11 +1028,13 @@ fn validate_elf>( allowed_libraries.push("libc.so".to_string()); } - // Allow the _crypt extension module - and only it - to link against libcrypt, - // which is no longer universally present in Linux distros. + // Allow certain extension modules to link against shared libraries + // (either from the system or from our distribution). if let Some(filename) = path.file_name() { - if filename.to_string_lossy().starts_with("_crypt") { - allowed_libraries.push("libcrypt.so.1".to_string()); + if let Some((module, _)) = filename.to_string_lossy().split_once(".cpython-") { + if let Some(extra) = ELF_ALLOWED_LIBRARIES_BY_MODULE.get(module) { + allowed_libraries.extend(extra.iter().map(|x| x.to_string())); + } } } @@ -1041,7 +1114,7 @@ fn validate_elf>( { let strings = symbols.strings(); - for (symbol_index, symbol) in symbols.iter().enumerate() { + for (symbol_index, symbol) in symbols.enumerate() { let name = String::from_utf8_lossy(symbol.name(endian, strings)?); // If symbol versions are defined and we're in the .dynsym section, there should @@ -1099,6 +1172,7 @@ fn validate_elf>( // to prevent them from being exported. if DEPENDENCY_PACKAGE_SYMBOLS.contains(&name.as_ref()) && matches!(symbol.st_bind(), STB_GLOBAL | STB_WEAK) + && symbol.st_shndx(endian) != SHN_UNDEF && symbol.st_visibility() != STV_HIDDEN { context.errors.push(format!( @@ -1114,6 +1188,7 @@ fn validate_elf>( if filename.starts_with("libpython") && filename.ends_with(".so.1.0") && matches!(symbol.st_bind(), STB_GLOBAL | STB_WEAK) + && symbol.st_shndx(endian) != SHN_UNDEF && symbol.st_visibility() == STV_DEFAULT { context.libpython_exported_symbols.insert(name.to_string()); @@ -1189,6 +1264,8 @@ fn validate_macho>( let mut undefined_symbols = vec![]; let mut target_version = None; let mut sdk_version = None; + let mut has_code_signature = false; + let mut lowest_file_offset = u64::MAX; while let Some(load_command) = load_commands.next()? { match load_command.variant()? { @@ -1215,7 +1292,16 @@ fn validate_macho>( dylib_names.push(lib.clone()); - let allowed = allowed_dylibs_for_triple(target_triple); + let mut allowed = allowed_dylibs_for_triple(target_triple); + // Allow certain extension modules to link against shared libraries + // (either from the system or from our distribution). + if let Some(filename) = path.file_name() { + if let Some((module, _)) = filename.to_string_lossy().split_once(".cpython-") { + if let Some(extra) = ALLOWED_DYLIBS_BY_MODULE.get(module) { + allowed.extend(extra.clone()); + } + } + } if let Some(entry) = allowed.iter().find(|l| l.name == lib) { let load_version = @@ -1302,10 +1388,38 @@ fn validate_macho>( } } } + LoadCommandVariant::Segment32(segment, segment_data) => { + for section in segment.sections(endian, segment_data)? { + if let Some((offset, _)) = section.file_range(endian) { + lowest_file_offset = lowest_file_offset.min(offset); + } + } + } + LoadCommandVariant::Segment64(segment, segment_data) => { + for section in segment.sections(endian, segment_data)? { + if let Some((offset, _)) = section.file_range(endian) { + lowest_file_offset = lowest_file_offset.min(offset); + } + } + } + LoadCommandVariant::LinkeditData(c) if c.cmd.get(endian) == LC_CODE_SIGNATURE => { + has_code_signature = true; + } _ => {} } } + let end_of_load_commands = + std::mem::size_of_val(header) as u64 + header.sizeofcmds(endian) as u64; + if header.filetype(endian) != MH_OBJECT + && end_of_load_commands + if has_code_signature { 0 } else { 16 } > lowest_file_offset + { + context.errors.push(format!( + "{}: Insufficient headerpad between end of load commands {end_of_load_commands:#x} and beginning of code {lowest_file_offset:#x}", + path.display(), + )); + } + if let Some(actual_target_version) = target_version { if actual_target_version != advertised_target_version { context.errors.push(format!( @@ -1375,15 +1489,17 @@ fn validate_pe<'data, Pe: ImageNtHeaders>( let lib = String::from_utf8(lib.to_vec())?; match python_major_minor { - "3.9" | "3.10" | "3.11" | "3.12" | "3.13" => {} + "3.11" | "3.12" | "3.13" if pe.architecture() == Architecture::Aarch64 => { + if PE_ALLOWED_LIBRARIES_ARM64.contains(&lib.as_str()) { + continue; + } + } "3.14" => { if PE_ALLOWED_LIBRARIES_314.contains(&lib.as_str()) { continue; } } - _ => { - panic!("unhandled Python version: {}", python_major_minor); - } + _ => {} } if !PE_ALLOWED_LIBRARIES.contains(&lib.as_str()) { @@ -1783,6 +1899,12 @@ fn validate_distribution( let mut entry = entry.map_err(|e| anyhow!("failed to iterate over archive: {}", e))?; let path = entry.path()?.to_path_buf(); + if let Some(file_name) = path.file_name() { + if file_name == "fips.dylib" || file_name == "fips.so" { + continue + } + } + seen_paths.insert(path.clone()); if let Some(link_name) = entry.link_name()? { diff --git a/src/verify_distribution.py b/src/verify_distribution.py index 2131d7a..62d58f9 100644 --- a/src/verify_distribution.py +++ b/src/verify_distribution.py @@ -114,7 +114,7 @@ def test_hashlib(self): def test_sqlite(self): import sqlite3 - self.assertEqual(sqlite3.sqlite_version_info, (3, 47, 1)) + self.assertEqual(sqlite3.sqlite_version_info, (3, 50, 4)) # Optional SQLite3 features are enabled. conn = sqlite3.connect(":memory:") @@ -122,6 +122,22 @@ def test_sqlite(self): self.assertTrue(hasattr(conn, "enable_load_extension")) # Backup feature requires modern SQLite, which we always have. self.assertTrue(hasattr(conn, "backup")) + # Ensure that various extensions are present. These will raise if they are not. Note that + # CPython upstream carries configuration flags for the Windows build, so geopoly is missing + # on all versions and rtree is missing in 3.9. On non-Windows platforms, we configure + # SQLite ourselves. We might want to patch the build to enable these on Windows, see #666. + extensions = ["fts3", "fts4", "fts5"] + if os.name != "nt": + extensions.append("geopoly") + if os.name != "nt" or sys.version_info[0:2] > (3, 9): + extensions.append("rtree") + cursor = conn.cursor() + for extension in extensions: + with self.subTest(extension=extension): + cursor.execute( + f"CREATE VIRTUAL TABLE test{extension} USING {extension}(a, b, c);" + ) + conn.close() def test_ssl(self): import ssl @@ -156,6 +172,18 @@ def test_gil_disabled(self): self.assertEqual(sysconfig.get_config_var("Py_GIL_DISABLED"), wanted) + @unittest.skipIf( + sys.version_info[:2] < (3, 14), + "zstd is only available in 3.14+", + ) + def test_zstd_multithreaded(self): + from compression import zstd + + max_threads = zstd.CompressionParameter.nb_workers.bounds()[1] + assert max_threads > 0, ( + "Expected multithreading to be enabled but max threads is zero" + ) + @unittest.skipIf("TCL_LIBRARY" not in os.environ, "TCL_LIBRARY not set") @unittest.skipIf("DISPLAY" not in os.environ, "DISPLAY not set") def test_tkinter(self):