Showing preview only (523K chars total). Download the full file or copy to clipboard to get everything.
Repository: python/release-tools
Branch: main
Commit: e7515f5ae838
Files: 83
Total size: 496.9 KB
Directory structure:
gitextract_8g54ntzm/
├── .coveragerc
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── build-release.yml
│ ├── lint.yml
│ └── test.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .ruff.toml
├── LICENSE.txt
├── README.md
├── add_to_pydotorg.py
├── buildbotapi.py
├── dev-requirements.in
├── dev-requirements.txt
├── mypy-requirements.txt
├── pyproject.toml
├── release.py
├── requirements.in
├── requirements.txt
├── run_release.py
├── sbom.py
├── select_jobs.py
├── tests/
│ ├── README.rst
│ ├── __init__.py
│ ├── buildbotapi/
│ │ ├── builders.json
│ │ ├── failure.json
│ │ ├── no-builds.json
│ │ └── success.json
│ ├── fake-artifact.txt
│ ├── fake-ftp-files.txt
│ ├── magicdata/
│ │ ├── Include/
│ │ │ └── internal/
│ │ │ └── pycore_magic_number.h
│ │ └── Lib/
│ │ └── test/
│ │ └── test_importlib/
│ │ └── test_util.py
│ ├── patchlevel.h
│ ├── sbom/
│ │ ├── sbom-with-pip-removed.json
│ │ └── sbom-with-pip.json
│ ├── test_add_to_pydotorg.py
│ ├── test_buildbotapi.py
│ ├── test_release.py
│ ├── test_release_tag.py
│ ├── test_run_release.py
│ ├── test_sbom.py
│ ├── test_select_jobs.py
│ ├── test_update_version_next.py
│ └── whatsnew_index.rst
├── tox.ini
├── update_version_next.py
└── windows-release/
├── README.md
├── acquire-vcruntime.yml
├── azure-pipelines.yml
├── build-steps-pgo.yml
├── build-steps.yml
├── checkout.yml
├── find-sdk.yml
├── find-tools.yml
├── layout-command.yml
├── libffi-build.yml
├── merge-and-upload.py
├── msi-steps.yml
├── openssl-build.yml
├── purge.py
├── sign-files.yml
├── stage-build.yml
├── stage-layout-embed.yml
├── stage-layout-full.yml
├── stage-layout-msix.yml
├── stage-layout-nuget.yml
├── stage-layout-pymanager.yml
├── stage-layout-symbols.yml
├── stage-msi.yml
├── stage-pack-msix.yml
├── stage-pack-nuget.yml
├── stage-pack-pymanager.yml
├── stage-publish-nugetorg.yml
├── stage-publish-pymanager.yml
├── stage-publish-pythonorg.yml
├── stage-sign.yml
├── stage-test-embed.yml
├── stage-test-msi.yml
├── stage-test-nuget.yml
├── stage-test-pymanager.yml
├── start-arm64vm.yml
├── tcltk-build.yml
└── uploadrelease.ps1
================================================
FILE CONTENTS
================================================
================================================
FILE: .coveragerc
================================================
# .coveragerc to control coverage.py
[report]
# Regexes for lines to exclude from consideration
exclude_also =
# Don't complain if non-runnable code isn't run:
if __name__ == .__main__.
def main
def get_arg_parser
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: monthly
groups:
actions:
patterns:
- "*"
cooldown:
default-days: 7
- package-ecosystem: pip
directory: "/"
schedule:
interval: monthly
assignees:
- "ezio-melotti"
groups:
pip:
patterns:
- "*"
cooldown:
default-days: 7
================================================
FILE: .github/workflows/build-release.yml
================================================
on:
push:
paths-ignore:
- ".github/dependabot.yml"
- ".github/workflows/lint.yml"
- ".github/workflows/test.yml"
- ".pre-commit-config.yaml"
- ".ruff.toml"
- "README.md"
- "tests/**"
pull_request:
paths-ignore:
- ".github/dependabot.yml"
- ".github/workflows/lint.yml"
- ".github/workflows/test.yml"
- ".pre-commit-config.yaml"
- ".ruff.toml"
- "README.md"
- "tests/**"
workflow_dispatch:
inputs:
git_remote:
type: choice
description: "Git remote to checkout"
options:
- python
- savannahostrowski
- hugovk
- Yhg1s
- pablogsal
- ambv
git_commit:
type: string
description: "Git commit to target for the release. Must use the full commit SHA, not the short ID"
cpython_release:
type: string
description: "CPython release number (ie '3.11.5', note without the 'v' prefix)"
name: "Build release artifacts"
permissions: {}
# Set from inputs for workflow_dispatch, or set defaults to test push/PR events
env:
GIT_REMOTE: ${{ github.event.inputs.git_remote || 'python' }}
GIT_COMMIT: ${{ github.event.inputs.git_commit || '55ea59e7dc35e1363b203ae4dd9cfc3a0ac0a844' }}
CPYTHON_RELEASE: ${{ github.event.inputs.cpython_release || '3.15.0a8' }}
jobs:
verify-input:
runs-on: ubuntu-24.04
timeout-minutes: 5
outputs:
build-docs: ${{ steps.select-jobs.outputs.docs }}
build-android: ${{ steps.select-jobs.outputs.android }}
build-ios: ${{ steps.select-jobs.outputs.ios }}
steps:
- name: "Workflow run information"
run: |
echo "git_remote: $GIT_REMOTE"
echo "git_commit: $GIT_COMMIT"
echo "cpython_release: $CPYTHON_RELEASE"
{
echo "| Variable | Value |"
echo "| --------------- | -------------------- |"
echo "| git_remote | \`$GIT_REMOTE\` |"
echo "| git_commit | \`$GIT_COMMIT\` |"
echo "| cpython_release | \`$CPYTHON_RELEASE\` |"
} >> "$GITHUB_STEP_SUMMARY"
- name: "Checkout python/release-tools"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: "Checkout ${{ env.GIT_REMOTE }}/cpython"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
repository: "${{ env.GIT_REMOTE }}/cpython"
ref: "v${{ env.CPYTHON_RELEASE }}"
path: "cpython"
- name: "Verify CPython commit matches tag"
run: |
if [[ "$GIT_COMMIT" != "$(cd cpython && git rev-parse HEAD)" ]]; then
echo "expected git commit ('$GIT_COMMIT') didn't match tagged commit ('$(git rev-parse HEAD)')"
exit 1
fi
- name: "Setup Python"
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.12
- name: "Select jobs"
id: select-jobs
run: |
test_flag=""
if [[ "${{ github.event_name }}" != "workflow_dispatch" ]]; then
test_flag="--test"
fi
output=$(./select_jobs.py $test_flag "$CPYTHON_RELEASE")
echo "$output" | tee -a "$GITHUB_OUTPUT"
{
echo "| Job | Enabled |"
echo "| ------- | ------- |"
echo "$output" | while IFS='=' read -r key value; do
echo "| $key | $value |"
done
} >> "$GITHUB_STEP_SUMMARY"
build-source:
runs-on: ubuntu-24.04
timeout-minutes: 15
needs:
- verify-input
steps:
- name: "Checkout python/release-tools"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: "Checkout ${{ env.GIT_REMOTE }}/cpython"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
repository: "${{ env.GIT_REMOTE }}/cpython"
ref: "v${{ env.CPYTHON_RELEASE }}"
path: "cpython"
- name: "Setup Python"
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.12
- name: "Install source dependencies"
run: |
python -m pip install --no-deps \
-r requirements.txt
- name: "Build Python release artifacts"
run: |
cd cpython
python ../release.py --export "$CPYTHON_RELEASE" --skip-docs
- name: "Upload the source artifacts"
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: source
path: |
cpython/${{ env.CPYTHON_RELEASE }}/src
build-docs:
runs-on: ubuntu-24.04
timeout-minutes: 45
needs:
- verify-input
if: fromJSON(needs.verify-input.outputs.build-docs)
steps:
- name: "Checkout ${{ env.GIT_REMOTE }}/cpython"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
repository: "${{ env.GIT_REMOTE }}/cpython"
ref: "v${{ env.CPYTHON_RELEASE }}"
- name: "Setup Python"
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.12
- name: "Install docs dependencies"
run: |
python -m pip install -r Doc/requirements.txt
- name: "Build docs"
env:
SPHINXOPTS: "-j10"
run: |
cd Doc
make dist-epub
make dist-html
make dist-texinfo
make dist-text
- name: "Upload the docs artifacts"
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docs
path: |
Doc/dist/
test-source:
runs-on: ubuntu-24.04
timeout-minutes: 60
needs:
- build-source
steps:
- name: "Download the source artifacts"
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: source
- name: "Test Python source tarballs"
run: |
mkdir -p ./tmp/installation/
cp "Python-$CPYTHON_RELEASE.tgz" ./tmp/
cd tmp/
tar xvf "Python-$CPYTHON_RELEASE.tgz"
cd "Python-$CPYTHON_RELEASE"
./configure "--prefix=$(realpath '../installation/')"
make -j
make install -j
cd ../installation
./bin/python3 -m test -uall -j4
test-docs:
runs-on: ubuntu-24.04
timeout-minutes: 15
needs:
- build-docs
steps:
- name: "Download the docs artifacts"
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: docs
- name: "Set up Python"
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.x"
- name: "Install epubcheck"
run: python -m pip install epubcheck
- name: "Run epubcheck"
continue-on-error: true
run: |
ls -la
epubcheck "python-$CPYTHON_RELEASE-docs.epub" &> epubcheck.txt
- name: "Show epubcheck output"
run: cat epubcheck.txt
- name: "Check for fatal errors in EPUB"
run: |
if grep -q "^FATAL" epubcheck.txt; then
echo "Fatal errors found in EPUB:"
grep "^FATAL" epubcheck.txt
exit 1
fi
echo "No fatal errors found in EPUB"
build-android:
name: build-android (${{ matrix.arch }})
needs:
- verify-input
if: fromJSON(needs.verify-input.outputs.build-android)
strategy:
matrix:
include:
- arch: aarch64
runs-on: macos-15
- arch: x86_64
runs-on: ubuntu-24.04
runs-on: ${{ matrix.runs-on }}
timeout-minutes: 60
env:
triplet: ${{ matrix.arch }}-linux-android
steps:
- name: "Checkout ${{ env.GIT_REMOTE }}/cpython"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
repository: "${{ env.GIT_REMOTE }}/cpython"
ref: "v${{ env.CPYTHON_RELEASE }}"
# Python 3.15 moved the build tools to the Platforms directory. Add a
# compatibility shim to simplify execution. Can be removed when 3.14
# reaches EOL
- name: Set up compatibility symlink
run: |
if [ ! -e Platforms/Android ]; then
mkdir -p Platforms
ln -s ../Android Platforms/Android
ln -s ./android.py Android/__main__.py
fi
- name: Build and test
run: python3 Platforms/Android ci --fast-ci "$triplet"
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ env.triplet }}
path: cross-build/${{ env.triplet }}/dist/*
if-no-files-found: error
build-ios:
name: build-iOS
needs:
- verify-input
if: fromJSON(needs.verify-input.outputs.build-ios)
runs-on: macos-14
timeout-minutes: 60
steps:
- name: "Checkout ${{ env.GIT_REMOTE }}/cpython"
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
repository: "${{ env.GIT_REMOTE }}/cpython"
ref: "v${{ env.CPYTHON_RELEASE }}"
- name: Build and test
run: python3 Platforms/Apple ci iOS --slow-ci
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ios
path: cross-build/dist/*
if-no-files-found: error
================================================
FILE: .github/workflows/lint.yml
================================================
name: Lint
on: [push, pull_request, workflow_dispatch]
permissions: {}
env:
FORCE_COLOR: 1
RUFF_OUTPUT_FORMAT: github
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.x"
cache: pip
- uses: j178/prek-action@cbc2f23eb5539cf20d82d1aabd0d0ecbcc56f4e3 # v2.0.2
- name: Install dependencies
run: |
python3 -m pip install -U pip
python3 -m pip install -U tox
- name: Mypy
run: tox -e mypy
- name: Run PSScriptAnalyzer on PowerShell scripts
shell: pwsh
run: |
Invoke-ScriptAnalyzer -Path . -Recurse -Severity ParseError,Error -EnableExit
================================================
FILE: .github/workflows/test.yml
================================================
name: Test
on: [push, pull_request, workflow_dispatch]
permissions: {}
env:
FORCE_COLOR: 1
jobs:
tests:
name: "Tests"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version: ["3.12", "3.13", "3.14"]
os: [macos-latest, ubuntu-latest]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: dev-requirements.txt
- run: |
python -m pip install tox
- run: |
tox -e py
- name: Upload coverage
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
with:
token: ${{ secrets.CODECOV_ORG_TOKEN }}
================================================
FILE: .gitignore
================================================
#
.idea/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
================================================
FILE: .pre-commit-config.yaml
================================================
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.10
hooks:
- id: ruff-check
args: [--exit-non-zero-on-fix]
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 25.12.0
hooks:
- id: black
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-merge-conflict
- id: check-toml
- id: check-yaml
exclude: windows-release/(azure-pipelines|msi-steps).yml
- id: debug-statements
- id: end-of-file-fixer
- id: forbid-submodules
- id: trailing-whitespace
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.36.0
hooks:
- id: check-dependabot
- id: check-github-workflows
- repo: https://github.com/rhysd/actionlint
rev: v1.7.10
hooks:
- id: actionlint
- repo: https://github.com/woodruffw/zizmor-pre-commit
rev: v1.19.0
hooks:
- id: zizmor
- repo: https://github.com/tox-dev/pyproject-fmt
rev: v2.11.1
hooks:
- id: pyproject-fmt
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.24.1
hooks:
- id: validate-pyproject
- repo: https://github.com/tox-dev/tox-ini-fmt
rev: 1.7.1
hooks:
- id: tox-ini-fmt
- repo: meta
hooks:
- id: check-hooks-apply
- id: check-useless-excludes
================================================
FILE: .ruff.toml
================================================
fix = true
[lint]
select = [
"C4", # flake8-comprehensions
"E", # pycodestyle errors
"F", # pyflakes errors
"I", # isort
"ISC", # flake8-implicit-str-concat
"LOG", # flake8-logging
"PGH", # pygrep-hooks
"RUF100", # unused noqa (yesqa)
"UP", # pyupgrade
"W", # pycodestyle warnings
"YTT", # flake8-2020
]
ignore = [
"E203", # Whitespace before ':'
"E221", # Multiple spaces before operator
"E226", # Missing whitespace around arithmetic operator
"E241", # Multiple spaces after ','
"E501", # Line too long
]
================================================
FILE: LICENSE.txt
================================================
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
--------------------------------------------
1. This LICENSE AGREEMENT is between the Python Software Foundation
("PSF"), and the Individual or Organization ("Licensee") accessing and
otherwise using this software ("Python") in source or binary form and
its associated documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
analyze, test, perform and/or display publicly, prepare derivative works,
distribute, and otherwise use Python alone or in any derivative version,
provided, however, that PSF's License Agreement and PSF's notice of copyright,
i.e., "Copyright (c) 2008 Python Software Foundation; All Rights Reserved"
are retained in Python alone or in any derivative version prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on
or incorporates Python or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python.
4. PSF is making Python available to Licensee on an "AS IS"
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
8. By copying, installing or otherwise using Python, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
================================================
FILE: README.md
================================================
# release-tools
[](https://github.com/python/release-tools/actions/workflows/test.yml)
Scripts for making (C)Python releases.
================================================
FILE: add_to_pydotorg.py
================================================
#!/usr/bin/env python
"""
Script to add ReleaseFile objects for Python releases on the new pydotorg.
To use (RELEASE is the full Python version number):
* Copy this script to dl-files (it needs access to all the release files).
You could also download all files, then you need to use the "--ftp-root"
argument.
* Make sure all download files are in place in the correct FTP subdirectory.
* Create a new Release object via the Django admin (adding via API is
currently broken), the name MUST be "Python RELEASE".
* Put an AUTH_INFO variable containing "username:api_key" in your environment.
* Call this script as "python add_to_pydotorg.py RELEASE".
Each call will remove all previous file objects, so you can call the script
multiple times.
Georg Brandl, March 2014.
"""
import argparse
import hashlib
import json
import os
import re
import subprocess
import sys
from collections.abc import Generator
from os import path
from typing import Any, NoReturn
import requests
# Copied from release.py
def error(*msgs: Any) -> NoReturn:
print("**ERROR**", file=sys.stderr)
for msg in msgs:
print(msg, file=sys.stderr)
sys.exit(1)
# Copied from release.py
def run_cmd(
cmd: list[str] | str, silent: bool = False, shell: bool = False, **kwargs: Any
) -> None:
if shell:
cmd = " ".join(cmd)
if not silent:
print(f"Executing {cmd}")
try:
if silent:
subprocess.check_call(cmd, shell=shell, stdout=subprocess.PIPE, **kwargs)
else:
subprocess.check_call(cmd, shell=shell, **kwargs)
except subprocess.CalledProcessError:
error(f"{cmd} failed")
try:
auth_info = os.environ["AUTH_INFO"]
except KeyError:
print(
"Please set an environment variable named AUTH_INFO "
'containing "username:api_key".'
)
sys.exit()
download_root = "https://www.python.org/ftp/python/"
tag_cre = re.compile(r"(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:([ab]|rc)(\d+))?$")
headers = {"Authorization": f"ApiKey {auth_info}", "Content-Type": "application/json"}
github_oidc_provider = "https://github.com/login/oauth"
google_oidc_provider = "https://accounts.google.com"
# Update this list when new release managers are added.
release_to_sigstore_identity_and_oidc_issuer = {
"3.10": ("pablogsal@python.org", google_oidc_provider),
"3.11": ("pablogsal@python.org", google_oidc_provider),
"3.12": ("thomas@python.org", google_oidc_provider),
"3.13": ("thomas@python.org", google_oidc_provider),
"3.14": ("hugo@python.org", github_oidc_provider),
"3.15": ("hugo@python.org", github_oidc_provider),
"3.16": ("savannah@python.org", github_oidc_provider),
"3.17": ("savannah@python.org", github_oidc_provider),
}
def macos_description(version: tuple[int, int, int]) -> str:
if version >= (3, 14):
return "for macOS 10.15 and later"
else:
return "for macOS 10.13 and later"
def get_file_descriptions(
release: str,
) -> list[tuple[re.Pattern[str], tuple[str, str, bool, str]]]:
v = base_version_tuple(release)
rx = re.compile
# value is (file "name", OS slug, download button, file "description").
# OS=None means no ReleaseFile object. Only one matching *file* (not regex)
# per OS can have download=True.
return [
(rx(r"\.tgz$"), ("Gzipped source tarball", "source", False, "")),
(rx(r"\.tar\.xz$"), ("XZ compressed source tarball", "source", True, "")),
(
rx(r"windows-.+\.json"),
(
"Windows release manifest",
"windows",
False,
f"Install with 'py install {v[0]}.{v[1]}'",
),
),
(
rx(r"-embed-amd64\.zip$"),
("Windows embeddable package (64-bit)", "windows", False, ""),
),
(
rx(r"-embed-arm64\.zip$"),
("Windows embeddable package (ARM64)", "windows", False, ""),
),
(
rx(r"-arm64\.exe$"),
("Windows installer (ARM64)", "windows", False, "Experimental"),
),
(
rx(r"-amd64\.exe$"),
("Windows installer (64-bit)", "windows", True, "Recommended"),
),
(
rx(r"-embed-win32\.zip$"),
("Windows embeddable package (32-bit)", "windows", False, ""),
),
(rx(r"\.exe$"), ("Windows installer (32-bit)", "windows", False, "")),
(
rx(r"-macos(x)?1[1-9](\.[0-9]*)?\.pkg$"),
(
"macOS installer",
"macos",
True,
macos_description(v),
),
),
(
rx(r"-aarch64-linux-android.tar.gz$"),
("Android embeddable package (aarch64)", "android", False, ""),
),
(
rx(r"-x86_64-linux-android.tar.gz$"),
("Android embeddable package (x86_64)", "android", False, ""),
),
(
rx(r"-iOS-XCframework.tar.gz$"),
("iOS XCframework", "ios", False, ""),
),
]
def slug_for(release: str) -> str:
return base_version(release).replace(".", "") + (
"-" + release[len(base_version(release)) :]
if release[len(base_version(release)) :]
else ""
)
def sigfile_for(release: str, rfile: str) -> str:
return download_root + f"{release}/{rfile}.asc"
def sha256sum_for(filename: str) -> str:
"""Returns SHA-256 checksum for filename."""
return hashlib.sha256(open(filename, "rb").read()).hexdigest()
def filesize_for(filename: str) -> int:
return path.getsize(filename)
def make_slug(text: str) -> str:
return re.sub("[^a-zA-Z0-9_-]", "", text.replace(" ", "-"))
def base_version(release: str) -> str:
m = tag_cre.match(release)
assert m is not None, f"Invalid release: {release}"
return ".".join(m.groups()[:3])
def base_version_tuple(release: str) -> tuple[int, int, int]:
m = tag_cre.match(release)
assert m is not None, f"Invalid release: {release}"
return int(m.groups()[0]), int(m.groups()[1]), int(m.groups()[2])
def minor_version(release: str) -> str:
m = tag_cre.match(release)
assert m is not None, f"Invalid release: {release}"
return ".".join(m.groups()[:2])
def minor_version_tuple(release: str) -> tuple[int, int]:
m = tag_cre.match(release)
assert m is not None, f"Invalid release: {release}"
return int(m.groups()[0]), int(m.groups()[1])
def build_file_dict(
ftp_root: str,
release: str,
rfile: str,
rel_pk: int,
file_desc: str,
os_pk: int,
add_download: bool,
add_desc: str,
) -> dict[str, Any]:
"""Return a dictionary with all needed fields for a ReleaseFile object."""
filename = path.join(ftp_root, base_version(release), rfile)
d = {
"name": file_desc,
"slug": slug_for(release) + "-" + make_slug(file_desc)[:40],
"os": f"/api/v1/downloads/os/{os_pk}/",
"release": f"/api/v1/downloads/release/{rel_pk}/",
"description": add_desc,
"is_source": os_pk == 3,
"url": download_root + f"{base_version(release)}/{rfile}",
"sha256_sum": sha256sum_for(filename),
"filesize": filesize_for(filename),
"download_button": add_download,
}
# Upload GPG signature
if os.path.exists(filename + ".asc"):
d["gpg_signature_file"] = sigfile_for(base_version(release), rfile)
# Upload Sigstore signature
if os.path.exists(filename + ".sig"):
d["sigstore_signature_file"] = (
download_root + f"{base_version(release)}/{rfile}.sig"
)
# Upload Sigstore certificate
if os.path.exists(filename + ".crt"):
d["sigstore_cert_file"] = download_root + f"{base_version(release)}/{rfile}.crt"
# Upload Sigstore bundle
if os.path.exists(filename + ".sigstore"):
d["sigstore_bundle_file"] = (
download_root + f"{base_version(release)}/{rfile}.sigstore"
)
# Upload SPDX SBOM file
if os.path.exists(filename + ".spdx.json"):
d["sbom_spdx2_file"] = (
download_root + f"{base_version(release)}/{rfile}.spdx.json"
)
return d
def list_files(
ftp_root: str, release: str
) -> Generator[tuple[str, str, str, bool, str], None, None]:
"""List all of the release's download files."""
reldir = base_version(release)
for rfile in sorted(os.listdir(path.join(ftp_root, reldir))):
if not path.isfile(path.join(ftp_root, reldir, rfile)):
continue
if rfile.endswith((".asc", ".sig", ".crt", ".sigstore", ".spdx.json")):
continue
prefix, _, rest = rfile.partition("-")
if prefix.lower() not in ("python", "windows"):
print(f" File {reldir}/{rfile} has wrong prefix")
continue
if not rest.startswith((release + "-", release + ".")):
print(f" File {reldir}/{rfile} has a different version")
continue
for rx, info in get_file_descriptions(release):
if rx.search(rfile):
yield (rfile, *info)
break
else:
print(f" File {reldir}/{rfile} not recognized")
continue
def query_object(base_url: str, objtype: str, **params: Any) -> int:
"""Find an API object by query parameters."""
uri = base_url + f"downloads/{objtype}/"
uri += "?" + "&".join(f"{k}={v}" for k, v in params.items())
resp = requests.get(uri, headers=headers)
if resp.status_code != 200 or not json.loads(resp.text)["objects"]:
raise RuntimeError(f"no object for {objtype} params={params!r}")
obj = json.loads(resp.text)["objects"][0]
return int(obj["resource_uri"].strip("/").split("/")[-1])
def post_object(base_url: str, objtype: str, datadict: dict[str, Any]) -> int:
"""Create a new API object."""
resp = requests.post(
base_url + "downloads/" + objtype + "/",
data=json.dumps(datadict),
headers=headers,
)
if resp.status_code != 201:
try:
info = json.loads(resp.text)
print(info.get("error_message", "No error message."))
print(info.get("traceback", ""))
except: # noqa: E722
pass
print(f"Creating {objtype} failed: {resp.status_code}")
return -1
newloc = resp.headers["Location"]
pk = int(newloc.strip("/").split("/")[-1])
return pk
def sign_release_files_with_sigstore(
ftp_root: str, release: str, release_files: list[tuple[str, str, str, bool, str]]
) -> None:
filenames = [
ftp_root + f"{base_version(release)}/{rfile}" for rfile, *_ in release_files
]
def has_sigstore_signature(filename: str) -> bool:
return os.path.exists(filename + ".sigstore") or (
os.path.exists(filename + ".sig") and os.path.exists(filename + ".crt")
)
# Skip files that already have a signature (likely source distributions)
unsigned_files = [
filename for filename in filenames if not has_sigstore_signature(filename)
]
if unsigned_files:
print("Signing release files with Sigstore")
for filename in unsigned_files:
cert_file = filename + ".crt"
sig_file = filename + ".sig"
bundle_file = filename + ".sigstore"
run_cmd(
[
"python3",
"-m",
"sigstore",
"sign",
"--oidc-disable-ambient-providers",
"--signature",
sig_file,
"--certificate",
cert_file,
"--bundle",
bundle_file,
filename,
]
)
run_cmd(["chmod", "644", sig_file])
run_cmd(["chmod", "644", cert_file])
run_cmd(["chmod", "644", bundle_file])
else:
print("All release files already signed with Sigstore")
# Verify all the files we expect to be signed with sigstore
# against the documented release manager identities and providers.
try:
sigstore_identity_and_oidc_issuer = (
release_to_sigstore_identity_and_oidc_issuer[minor_version(release)]
)
except KeyError:
error(["No release manager defined for Python release " + release])
sigstore_identity, sigstore_oidc_issuer = sigstore_identity_and_oidc_issuer
print("Verifying release files were signed correctly with Sigstore")
sigstore_verify_argv = [
"python3",
"-m",
"sigstore",
"verify",
"identity",
"--cert-identity",
sigstore_identity,
"--cert-oidc-issuer",
sigstore_oidc_issuer,
]
for filename in filenames:
filename_crt = filename + ".crt"
filename_sig = filename + ".sig"
filename_sigstore = filename + ".sigstore"
if os.path.exists(filename_sigstore):
run_cmd(
sigstore_verify_argv + ["--bundle", filename_sigstore, filename],
stderr=subprocess.STDOUT, # Sigstore sends stderr on success.
)
# We use an 'or' here to error out if one of the files is missing.
if os.path.exists(filename_sig) or os.path.exists(filename_crt):
run_cmd(
sigstore_verify_argv
+ [
"--certificate",
filename_crt,
"--signature",
filename_sig,
filename,
],
stderr=subprocess.STDOUT, # Sigstore sends stderr on success.
)
def parse_args() -> argparse.Namespace:
def ensure_trailing_slash(s: str) -> str:
if not s.endswith("/"):
s += "/"
return s
parser = argparse.ArgumentParser()
parser.add_argument(
"--base-url",
metavar="URL",
type=ensure_trailing_slash,
default="https://www.python.org/api/v1/",
help="API URL; defaults to %(default)s",
)
parser.add_argument(
"--ftp-root",
metavar="DIR",
type=ensure_trailing_slash,
default="/srv/www.python.org/ftp/python/",
help="FTP root; defaults to %(default)s",
)
parser.add_argument(
"release",
help="Python version number, e.g. 3.14.0rc2",
)
return parser.parse_args()
def main() -> None:
args = parse_args()
rel = args.release
print("Querying python.org for release", rel)
rel_pk = query_object(args.base_url, "release", name="Python+" + rel)
print("Found Release object: id =", rel_pk)
release_files = list(list_files(args.ftp_root, rel))
sign_release_files_with_sigstore(args.ftp_root, rel, release_files)
n = 0
file_dicts = {}
for rfile, file_desc, os_slug, add_download, add_desc in release_files:
if not os_slug:
continue
os_pk = query_object(args.base_url, "os", slug=os_slug)
file_dict = build_file_dict(
args.ftp_root, rel, rfile, rel_pk, file_desc, os_pk, add_download, add_desc
)
key = file_dict["slug"]
print("Creating ReleaseFile object for", rfile, key)
if key in file_dicts:
raise RuntimeError(f"duplicate slug generated: {key}")
file_dicts[key] = file_dict
print("Deleting previous release files")
resp = requests.delete(
args.base_url + f"downloads/release_file/?release={rel_pk}", headers=headers
)
if resp.status_code != 204:
raise RuntimeError(f"deleting previous releases failed: {resp.status_code}")
for file_dict in file_dicts.values():
file_pk = post_object(args.base_url, "release_file", file_dict)
if file_pk >= 0:
print("Created as id =", file_pk)
n += 1
print(f"Done - {n} files added")
if __name__ == "__main__" and not sys.flags.interactive:
main()
================================================
FILE: buildbotapi.py
================================================
import json
from dataclasses import dataclass
from typing import Any, cast
from aiohttp.client import ClientSession
JSON = dict[str, Any]
@dataclass
class Builder:
builderid: int
description: str | None
name: str
tags: list[str]
def __init__(self, **kwargs: Any) -> None:
self.__dict__.update(**kwargs)
def __hash__(self) -> int:
return hash(self.builderid)
class BuildBotAPI:
def __init__(self, session: ClientSession) -> None:
self._session = session
async def authenticate(self, token: str) -> None:
await self._session.get(
"https://buildbot.python.org/all/auth/login", params={"token": token}
)
async def _fetch_text(self, url: str) -> str:
async with self._session.get(url) as resp:
return await resp.text()
async def _fetch_json(self, url: str) -> JSON:
return cast(JSON, json.loads(await self._fetch_text(url)))
async def stable_builders(self, branch: str | None = None) -> dict[int, Builder]:
stable_builders = {
id: builder
for (id, builder) in (await self.all_builders(branch=branch)).items()
if "stable" in builder.tags
}
return stable_builders
async def all_builders(self, branch: str | None = None) -> dict[int, Builder]:
url = "https://buildbot.python.org/all/api/v2/builders"
if branch is not None:
url = f"{url}?tags__contains={branch}"
_builders: dict[str, Any] = await self._fetch_json(url)
builders = _builders["builders"]
all_builders = {
builder["builderid"]: Builder(**builder) for builder in builders
}
return all_builders
async def is_builder_failing_currently(self, builder: Builder) -> bool:
builds_: dict[str, Any] = await self._fetch_json(
f"https://buildbot.python.org/all/api/v2/builds?complete__eq=true"
f"&&builderid__eq={builder.builderid}&&order=-complete_at"
f"&&limit=1"
)
builds = builds_["builds"]
if not builds:
return False
(build,) = builds
if build["results"] == 2:
return True
return False
================================================
FILE: dev-requirements.in
================================================
pyfakefs
pytest
pytest-aiohttp
pytest-cov
pytest-mock
================================================
FILE: dev-requirements.txt
================================================
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --generate-hashes --output-file=dev-requirements.txt dev-requirements.in
#
aiohappyeyeballs==2.6.1 \
--hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \
--hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8
# via aiohttp
aiohttp==3.13.3 \
--hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \
--hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \
--hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \
--hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \
--hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \
--hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \
--hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \
--hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \
--hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \
--hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \
--hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \
--hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \
--hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \
--hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \
--hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \
--hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \
--hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \
--hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \
--hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \
--hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \
--hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \
--hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \
--hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \
--hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \
--hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \
--hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \
--hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \
--hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \
--hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \
--hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \
--hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \
--hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \
--hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \
--hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \
--hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \
--hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \
--hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \
--hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \
--hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \
--hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \
--hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \
--hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \
--hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \
--hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \
--hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \
--hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \
--hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \
--hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \
--hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \
--hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \
--hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \
--hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \
--hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \
--hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \
--hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \
--hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \
--hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \
--hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \
--hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \
--hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \
--hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \
--hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \
--hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \
--hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \
--hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \
--hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \
--hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \
--hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \
--hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \
--hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \
--hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \
--hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \
--hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \
--hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \
--hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \
--hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \
--hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \
--hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \
--hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \
--hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \
--hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \
--hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \
--hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \
--hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \
--hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \
--hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \
--hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \
--hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \
--hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \
--hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \
--hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \
--hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \
--hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \
--hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \
--hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \
--hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \
--hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \
--hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \
--hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \
--hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \
--hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \
--hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \
--hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \
--hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \
--hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \
--hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \
--hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \
--hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \
--hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \
--hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \
--hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \
--hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \
--hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \
--hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \
--hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \
--hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \
--hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \
--hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \
--hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \
--hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940
# via pytest-aiohttp
aiosignal==1.4.0 \
--hash=sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e \
--hash=sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7
# via aiohttp
attrs==24.3.0 \
--hash=sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff \
--hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308
# via aiohttp
coverage[toml]==7.10.7 \
--hash=sha256:03ffc58aacdf65d2a82bbeb1ffe4d01ead4017a21bfd0454983b88ca73af94b9 \
--hash=sha256:097c1591f5af4496226d5783d036bf6fd6cd0cbc132e071b33861de756efb880 \
--hash=sha256:0b944ee8459f515f28b851728ad224fa2d068f1513ef6b7ff1efafeb2185f999 \
--hash=sha256:0ebbaddb2c19b71912c6f2518e791aa8b9f054985a0769bdb3a53ebbc765c6a1 \
--hash=sha256:10b24412692df990dbc34f8fb1b6b13d236ace9dfdd68df5b28c2e39cafbba13 \
--hash=sha256:10b6ba00ab1132a0ce4428ff68cf50a25efd6840a42cdf4239c9b99aad83be8b \
--hash=sha256:121da30abb574f6ce6ae09840dae322bef734480ceafe410117627aa54f76d82 \
--hash=sha256:18afb24843cbc175687225cab1138c95d262337f5473512010e46831aa0c2973 \
--hash=sha256:1b4fd784344d4e52647fd7857b2af5b3fbe6c239b0b5fa63e94eb67320770e0f \
--hash=sha256:1ca6db7c8807fb9e755d0379ccc39017ce0a84dcd26d14b5a03b78563776f681 \
--hash=sha256:1ef2319dd15a0b009667301a3f84452a4dc6fddfd06b0c5c53ea472d3989fbf0 \
--hash=sha256:2120043f147bebb41c85b97ac45dd173595ff14f2a584f2963891cbcc3091541 \
--hash=sha256:212f8f2e0612778f09c55dd4872cb1f64a1f2b074393d139278ce902064d5b32 \
--hash=sha256:240af60539987ced2c399809bd34f7c78e8abe0736af91c3d7d0e795df633d17 \
--hash=sha256:2a78cd46550081a7909b3329e2266204d584866e8d97b898cd7fb5ac8d888b1a \
--hash=sha256:2af88deffcc8a4d5974cf2d502251bc3b2db8461f0b66d80a449c33757aa9f40 \
--hash=sha256:2c8b9a0636f94c43cd3576811e05b89aa9bc2d0a85137affc544ae5cb0e4bfbd \
--hash=sha256:2fafd773231dd0378fdba66d339f84904a8e57a262f583530f4f156ab83863e6 \
--hash=sha256:314f2c326ded3f4b09be11bc282eb2fc861184bc95748ae67b360ac962770be7 \
--hash=sha256:33a5e6396ab684cb43dc7befa386258acb2d7fae7f67330ebb85ba4ea27938eb \
--hash=sha256:3445258bcded7d4aa630ab8296dea4d3f15a255588dd535f980c193ab6b95f3f \
--hash=sha256:35f5e3f9e455bb17831876048355dca0f758b6df22f49258cb5a91da23ef437d \
--hash=sha256:39508ffda4f343c35f3236fe8d1a6634a51f4581226a1262769d7f970e73bffe \
--hash=sha256:399a0b6347bcd3822be369392932884b8216d0944049ae22925631a9b3d4ba4c \
--hash=sha256:3a622ac801b17198020f09af3eaf45666b344a0d69fc2a6ffe2ea83aeef1d807 \
--hash=sha256:4376538f36b533b46f8971d3a3e63464f2c7905c9800db97361c43a2b14792ab \
--hash=sha256:4b583b97ab2e3efe1b3e75248a9b333bd3f8b0b1b8e5b45578e05e5850dfb2c2 \
--hash=sha256:4b6f236edf6e2f9ae8fcd1332da4e791c1b6ba0dc16a2dc94590ceccb482e546 \
--hash=sha256:4da86b6d62a496e908ac2898243920c7992499c1712ff7c2b6d837cc69d9467e \
--hash=sha256:50aa94fb1fb9a397eaa19c0d5ec15a5edd03a47bf1a3a6111a16b36e190cff65 \
--hash=sha256:567f5c155eda8df1d3d439d40a45a6a5f029b429b06648235f1e7e51b522b396 \
--hash=sha256:5a02d5a850e2979b0a014c412573953995174743a3f7fa4ea5a6e9a3c5617431 \
--hash=sha256:5e1e9802121405ede4b0133aa4340ad8186a1d2526de5b7c3eca519db7bb89fb \
--hash=sha256:5f33166f0dfcce728191f520bd2692914ec70fac2713f6bf3ce59c3deacb4699 \
--hash=sha256:606cc265adc9aaedcc84f1f064f0e8736bc45814f15a357e30fca7ecc01504e0 \
--hash=sha256:635adb9a4507c9fd2ed65f39693fa31c9a3ee3a8e6dc64df033e8fdf52a7003f \
--hash=sha256:65646bb0359386e07639c367a22cf9b5bf6304e8630b565d0626e2bdf329227a \
--hash=sha256:67f8c5cbcd3deb7a60b3345dffc89a961a484ed0af1f6f73de91705cc6e31235 \
--hash=sha256:69212fbccdbd5b0e39eac4067e20a4a5256609e209547d86f740d68ad4f04911 \
--hash=sha256:6b8b09c1fad947c84bbbc95eca841350fad9cbfa5a2d7ca88ac9f8d836c92e23 \
--hash=sha256:6be8ed3039ae7f7ac5ce058c308484787c86e8437e72b30bf5e88b8ea10f3c87 \
--hash=sha256:6e16e07d85ca0cf8bafe5f5d23a0b850064e8e945d5677492b06bbe6f09cc699 \
--hash=sha256:736f227fb490f03c6488f9b6d45855f8e0fd749c007f9303ad30efab0e73c05a \
--hash=sha256:73ab1601f84dc804f7812dc297e93cd99381162da39c47040a827d4e8dafe63b \
--hash=sha256:77eb4c747061a6af8d0f7bdb31f1e108d172762ef579166ec84542f711d90256 \
--hash=sha256:78a384e49f46b80fb4c901d52d92abe098e78768ed829c673fbb53c498bef73a \
--hash=sha256:7bb3b9ddb87ef7725056572368040c32775036472d5a033679d1fa6c8dc08417 \
--hash=sha256:7ea7c6c9d0d286d04ed3541747e6597cbe4971f22648b68248f7ddcd329207f0 \
--hash=sha256:7fe650342addd8524ca63d77b2362b02345e5f1a093266787d210c70a50b471a \
--hash=sha256:813922f35bd800dca9994c5971883cbc0d291128a5de6b167c7aa697fcf59360 \
--hash=sha256:83082a57783239717ceb0ad584de3c69cf581b2a95ed6bf81ea66034f00401c0 \
--hash=sha256:8421e088bc051361b01c4b3a50fd39a4b9133079a2229978d9d30511fd05231b \
--hash=sha256:86b0e7308289ddde73d863b7683f596d8d21c7d8664ce1dee061d0bcf3fbb4bb \
--hash=sha256:88127d40df529336a9836870436fc2751c339fbaed3a836d42c93f3e4bd1d0a2 \
--hash=sha256:8fb190658865565c549b6b4706856d6a7b09302c797eb2cf8e7fe9dabb043f0d \
--hash=sha256:912e6ebc7a6e4adfdbb1aec371ad04c68854cd3bf3608b3514e7ff9062931d8a \
--hash=sha256:925a1edf3d810537c5a3abe78ec5530160c5f9a26b1f4270b40e62cc79304a1e \
--hash=sha256:93c1b03552081b2a4423091d6fb3787265b8f86af404cff98d1b5342713bdd69 \
--hash=sha256:972b9e3a4094b053a4e46832b4bc829fc8a8d347160eb39d03f1690316a99c14 \
--hash=sha256:981a651f543f2854abd3b5fcb3263aac581b18209be49863ba575de6edf4c14d \
--hash=sha256:99e4aa63097ab1118e75a848a28e40d68b08a5e19ce587891ab7fd04475e780f \
--hash=sha256:9fa6e4dd51fe15d8738708a973470f67a855ca50002294852e9571cdbd9433f2 \
--hash=sha256:a0ec07fd264d0745ee396b666d47cef20875f4ff2375d7c4f58235886cc1ef0c \
--hash=sha256:a2d9a3b260cc1d1dbdb1c582e63ddcf5363426a1a68faa0f5da28d8ee3c722a0 \
--hash=sha256:a3cc8638b2480865eaa3926d192e64ce6c51e3d29c849e09d5b4ad95efae5399 \
--hash=sha256:a609f9c93113be646f44c2a0256d6ea375ad047005d7f57a5c15f614dc1b2f59 \
--hash=sha256:a62c6ef0d50e6de320c270ff91d9dd0a05e7250cac2a800b7784bae474506e63 \
--hash=sha256:a6442c59a8ac8b85812ce33bc4d05bde3fb22321fa8294e2a5b487c3505f611b \
--hash=sha256:a7b55a944a7f43892e28ad4bc0561dfd5f0d73e605d1aa5c3c976b52aea121d2 \
--hash=sha256:a8b6f03672aa6734e700bbcd65ff050fd19cddfec4b031cc8cf1c6967de5a68e \
--hash=sha256:affef7c76a9ef259187ef31599a9260330e0335a3011732c4b9effa01e1cd6e0 \
--hash=sha256:b06f260b16ead11643a5a9f955bd4b5fd76c1a4c6796aeade8520095b75de520 \
--hash=sha256:b1c81d0e5e160651879755c9c675b974276f135558cf4ba79fee7b8413a515df \
--hash=sha256:b281d5eca50189325cfe1f365fafade89b14b4a78d9b40b05ddd1fc7d2a10a9c \
--hash=sha256:b51dcd060f18c19290d9b8a9dd1e0181538df2ce0717f562fff6cf74d9fc0b5b \
--hash=sha256:b7b8288eb7cdd268b0304632da8cb0bb93fadcfec2fe5712f7b9cc8f4d487be2 \
--hash=sha256:b9be91986841a75042b3e3243d0b3cb0b2434252b977baaf0cd56e960fe1e46f \
--hash=sha256:ba58bbcd1b72f136080c0bccc2400d66cc6115f3f906c499013d065ac33a4b61 \
--hash=sha256:bb45474711ba385c46a0bfe696c695a929ae69ac636cda8f532be9e8c93d720a \
--hash=sha256:bc01f57ca26269c2c706e838f6422e2a8788e41b3e3c65e2f41148212e57cd59 \
--hash=sha256:bc91b314cef27742da486d6839b677b3f2793dfe52b51bbbb7cf736d5c29281c \
--hash=sha256:bda5e34f8a75721c96085903c6f2197dc398c20ffd98df33f866a9c8fd95f4bf \
--hash=sha256:c134869d5ffe34547d14e174c866fd8fe2254918cc0a95e99052903bc1543e07 \
--hash=sha256:c41e71c9cfb854789dee6fc51e46743a6d138b1803fab6cb860af43265b42ea6 \
--hash=sha256:c4e16bd7761c5e454f4efd36f345286d6f7c5fa111623c355691e2755cae3b9e \
--hash=sha256:c7315339eae3b24c2d2fa1ed7d7a38654cba34a13ef19fbcb9425da46d3dc594 \
--hash=sha256:c79124f70465a150e89340de5963f936ee97097d2ef76c869708c4248c63ca49 \
--hash=sha256:cac0fdca17b036af3881a9d2729a850b76553f3f716ccb0360ad4dbc06b3b843 \
--hash=sha256:cc87dd1b6eaf0b848eebb1c86469b9f72a1891cb42ac7adcfbce75eadb13dd14 \
--hash=sha256:cce2109b6219f22ece99db7644b9622f54a4e915dad65660ec435e89a3ea7cc3 \
--hash=sha256:d41213ea25a86f69efd1575073d34ea11aabe075604ddf3d148ecfec9e1e96a1 \
--hash=sha256:dc7c389dce432500273eaf48f410b37886be9208b2dd5710aaf7c57fd442c698 \
--hash=sha256:dd5e856ebb7bfb7672b0086846db5afb4567a7b9714b8a0ebafd211ec7ce6a15 \
--hash=sha256:e1ed71194ef6dea7ed2d5cb5f7243d4bcd334bfb63e59878519be558078f848d \
--hash=sha256:e201e015644e207139f7e2351980feb7040e6f4b2c2978892f3e3789d1c125e5 \
--hash=sha256:e28299d9f2e889e6d51b1f043f58d5f997c373cc12e6403b90df95b8b047c13e \
--hash=sha256:f3c887f96407cea3916294046fc7dab611c2552beadbed4ea901cbc6a40cc7a0 \
--hash=sha256:f49a05acd3dfe1ce9715b657e28d138578bc40126760efb962322c56e9ca344b \
--hash=sha256:f4ab143ab113be368a3e9b795f9cd7906c5ef407d6173fe9675a902e1fffc239 \
--hash=sha256:f51328ffe987aecf6d09f3cd9d979face89a617eacdaea43e7b3080777f647ba \
--hash=sha256:f57b2a3c8353d3e04acf75b3fed57ba41f5c0646bbf1d10c7c282291c97936b4 \
--hash=sha256:f7941f6f2fe6dd6807a1208737b8a0cbcf1cc6d7b07d24998ad2d63590868260 \
--hash=sha256:fc04cc7a3db33664e0c2d10eb8990ff6b3536f6842c9590ae8da4c614b9ed05a \
--hash=sha256:fff7b9c3f19957020cac546c70025331113d2e61537f6e2441bc7657913de7d3
# via pytest-cov
frozenlist==1.5.0 \
--hash=sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e \
--hash=sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf \
--hash=sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6 \
--hash=sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a \
--hash=sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d \
--hash=sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f \
--hash=sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28 \
--hash=sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b \
--hash=sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9 \
--hash=sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2 \
--hash=sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec \
--hash=sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2 \
--hash=sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c \
--hash=sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336 \
--hash=sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4 \
--hash=sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d \
--hash=sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b \
--hash=sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c \
--hash=sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10 \
--hash=sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08 \
--hash=sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942 \
--hash=sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8 \
--hash=sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f \
--hash=sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10 \
--hash=sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5 \
--hash=sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6 \
--hash=sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21 \
--hash=sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c \
--hash=sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d \
--hash=sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923 \
--hash=sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608 \
--hash=sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de \
--hash=sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17 \
--hash=sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0 \
--hash=sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f \
--hash=sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641 \
--hash=sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c \
--hash=sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a \
--hash=sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0 \
--hash=sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9 \
--hash=sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab \
--hash=sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f \
--hash=sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3 \
--hash=sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a \
--hash=sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784 \
--hash=sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604 \
--hash=sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d \
--hash=sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5 \
--hash=sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03 \
--hash=sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e \
--hash=sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953 \
--hash=sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee \
--hash=sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d \
--hash=sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817 \
--hash=sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3 \
--hash=sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039 \
--hash=sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f \
--hash=sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9 \
--hash=sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf \
--hash=sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76 \
--hash=sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba \
--hash=sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171 \
--hash=sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb \
--hash=sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439 \
--hash=sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631 \
--hash=sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972 \
--hash=sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d \
--hash=sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869 \
--hash=sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9 \
--hash=sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411 \
--hash=sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723 \
--hash=sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2 \
--hash=sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b \
--hash=sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99 \
--hash=sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e \
--hash=sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840 \
--hash=sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3 \
--hash=sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb \
--hash=sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3 \
--hash=sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0 \
--hash=sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca \
--hash=sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45 \
--hash=sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e \
--hash=sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f \
--hash=sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5 \
--hash=sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307 \
--hash=sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e \
--hash=sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2 \
--hash=sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778 \
--hash=sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a \
--hash=sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30 \
--hash=sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a
# via
# aiohttp
# aiosignal
idna==3.10 \
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
# via yarl
iniconfig==2.0.0 \
--hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \
--hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374
# via pytest
multidict==6.1.0 \
--hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \
--hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \
--hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \
--hash=sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3 \
--hash=sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b \
--hash=sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6 \
--hash=sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748 \
--hash=sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966 \
--hash=sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f \
--hash=sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1 \
--hash=sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6 \
--hash=sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada \
--hash=sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305 \
--hash=sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2 \
--hash=sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d \
--hash=sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a \
--hash=sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef \
--hash=sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c \
--hash=sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb \
--hash=sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60 \
--hash=sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6 \
--hash=sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4 \
--hash=sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478 \
--hash=sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81 \
--hash=sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7 \
--hash=sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56 \
--hash=sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3 \
--hash=sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6 \
--hash=sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30 \
--hash=sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb \
--hash=sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506 \
--hash=sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0 \
--hash=sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925 \
--hash=sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c \
--hash=sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6 \
--hash=sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e \
--hash=sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95 \
--hash=sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2 \
--hash=sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133 \
--hash=sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2 \
--hash=sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa \
--hash=sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3 \
--hash=sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3 \
--hash=sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436 \
--hash=sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657 \
--hash=sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581 \
--hash=sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492 \
--hash=sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43 \
--hash=sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2 \
--hash=sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2 \
--hash=sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926 \
--hash=sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057 \
--hash=sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc \
--hash=sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80 \
--hash=sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255 \
--hash=sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1 \
--hash=sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972 \
--hash=sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53 \
--hash=sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1 \
--hash=sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423 \
--hash=sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a \
--hash=sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160 \
--hash=sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c \
--hash=sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd \
--hash=sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa \
--hash=sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5 \
--hash=sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b \
--hash=sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa \
--hash=sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef \
--hash=sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44 \
--hash=sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4 \
--hash=sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156 \
--hash=sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753 \
--hash=sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28 \
--hash=sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d \
--hash=sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a \
--hash=sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304 \
--hash=sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008 \
--hash=sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429 \
--hash=sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72 \
--hash=sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399 \
--hash=sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3 \
--hash=sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392 \
--hash=sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167 \
--hash=sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c \
--hash=sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774 \
--hash=sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351 \
--hash=sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76 \
--hash=sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875 \
--hash=sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd \
--hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 \
--hash=sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db
# via
# aiohttp
# yarl
packaging==23.2 \
--hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \
--hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7
# via pytest
pluggy==1.6.0 \
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \
--hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
# via
# pytest
# pytest-cov
propcache==0.2.1 \
--hash=sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4 \
--hash=sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4 \
--hash=sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a \
--hash=sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f \
--hash=sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9 \
--hash=sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d \
--hash=sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e \
--hash=sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6 \
--hash=sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf \
--hash=sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034 \
--hash=sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d \
--hash=sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16 \
--hash=sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30 \
--hash=sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba \
--hash=sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95 \
--hash=sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d \
--hash=sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae \
--hash=sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348 \
--hash=sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2 \
--hash=sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64 \
--hash=sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce \
--hash=sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54 \
--hash=sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629 \
--hash=sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54 \
--hash=sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1 \
--hash=sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b \
--hash=sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf \
--hash=sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b \
--hash=sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587 \
--hash=sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097 \
--hash=sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea \
--hash=sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24 \
--hash=sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7 \
--hash=sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541 \
--hash=sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6 \
--hash=sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634 \
--hash=sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3 \
--hash=sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d \
--hash=sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034 \
--hash=sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465 \
--hash=sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2 \
--hash=sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf \
--hash=sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1 \
--hash=sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04 \
--hash=sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5 \
--hash=sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583 \
--hash=sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb \
--hash=sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b \
--hash=sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c \
--hash=sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958 \
--hash=sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc \
--hash=sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4 \
--hash=sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82 \
--hash=sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e \
--hash=sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce \
--hash=sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9 \
--hash=sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518 \
--hash=sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536 \
--hash=sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505 \
--hash=sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052 \
--hash=sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff \
--hash=sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1 \
--hash=sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f \
--hash=sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681 \
--hash=sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347 \
--hash=sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af \
--hash=sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246 \
--hash=sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787 \
--hash=sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0 \
--hash=sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f \
--hash=sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439 \
--hash=sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3 \
--hash=sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6 \
--hash=sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca \
--hash=sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec \
--hash=sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d \
--hash=sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3 \
--hash=sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16 \
--hash=sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717 \
--hash=sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6 \
--hash=sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd \
--hash=sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212
# via
# aiohttp
# yarl
pyfakefs==6.2.0 \
--hash=sha256:0968a49db692694ffed420e54a9f1cbae4636637b880e8ab09c8ccc0f11bd7ae \
--hash=sha256:e59a36db447bf509ce9c97ab3d1510c08cc51895c5311325a560a5e5b5dc1940
# via -r dev-requirements.in
pygments==2.20.0 \
--hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \
--hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176
# via pytest
pytest==9.0.3 \
--hash=sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9 \
--hash=sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c
# via
# -r dev-requirements.in
# pytest-aiohttp
# pytest-asyncio
# pytest-cov
# pytest-mock
pytest-aiohttp==1.1.0 \
--hash=sha256:147de8cb164f3fc9d7196967f109ab3c0b93ea3463ab50631e56438eab7b5adc \
--hash=sha256:f39a11693a0dce08dd6c542d241e199dd8047a6e6596b2bcfa60d373f143456d
# via -r dev-requirements.in
pytest-asyncio==1.3.0 \
--hash=sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5 \
--hash=sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5
# via pytest-aiohttp
pytest-cov==7.1.0 \
--hash=sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2 \
--hash=sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678
# via -r dev-requirements.in
pytest-mock==3.15.1 \
--hash=sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d \
--hash=sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f
# via -r dev-requirements.in
typing-extensions==4.15.0 \
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via
# aiosignal
# pytest-asyncio
yarl==1.18.3 \
--hash=sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba \
--hash=sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193 \
--hash=sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318 \
--hash=sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee \
--hash=sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e \
--hash=sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1 \
--hash=sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a \
--hash=sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186 \
--hash=sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1 \
--hash=sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50 \
--hash=sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640 \
--hash=sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb \
--hash=sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8 \
--hash=sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc \
--hash=sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5 \
--hash=sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58 \
--hash=sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2 \
--hash=sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393 \
--hash=sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24 \
--hash=sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b \
--hash=sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910 \
--hash=sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c \
--hash=sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272 \
--hash=sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed \
--hash=sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1 \
--hash=sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04 \
--hash=sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d \
--hash=sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5 \
--hash=sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d \
--hash=sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889 \
--hash=sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae \
--hash=sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b \
--hash=sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c \
--hash=sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576 \
--hash=sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34 \
--hash=sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477 \
--hash=sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990 \
--hash=sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2 \
--hash=sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512 \
--hash=sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069 \
--hash=sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a \
--hash=sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6 \
--hash=sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0 \
--hash=sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8 \
--hash=sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb \
--hash=sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa \
--hash=sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8 \
--hash=sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e \
--hash=sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e \
--hash=sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985 \
--hash=sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8 \
--hash=sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1 \
--hash=sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5 \
--hash=sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690 \
--hash=sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10 \
--hash=sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789 \
--hash=sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b \
--hash=sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca \
--hash=sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e \
--hash=sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5 \
--hash=sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59 \
--hash=sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9 \
--hash=sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8 \
--hash=sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db \
--hash=sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde \
--hash=sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7 \
--hash=sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb \
--hash=sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3 \
--hash=sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6 \
--hash=sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285 \
--hash=sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb \
--hash=sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8 \
--hash=sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482 \
--hash=sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd \
--hash=sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75 \
--hash=sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760 \
--hash=sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782 \
--hash=sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53 \
--hash=sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2 \
--hash=sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1 \
--hash=sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719 \
--hash=sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62
# via aiohttp
================================================
FILE: mypy-requirements.txt
================================================
aiohttp==3.13.5
alive_progress>=3.3.0
mypy==1.20.2
pyfakefs
pytest
pytest-mock
python-gnupg # untyped :(
sigstore==3.6.7
types-paramiko
types-requests
================================================
FILE: pyproject.toml
================================================
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
[tool.mypy]
python_version = "3.12"
pretty = true
strict = true
# Extra checks that aren't included in --strict
enable_error_code = "ignore-without-code,redundant-expr,truthy-iterable"
extra_checks = true
warn_unreachable = true
exclude = [
"^tests/test_release_tag.py$",
"^tests/test_run_release.py$",
"^tests/test_sbom.py$",
"^windows-release/merge-and-upload.py$",
"^windows-release/purge.py$",
]
================================================
FILE: release.py
================================================
#!/usr/bin/env python3
"""An assistant for making Python releases.
Original code by Benjamin Peterson
Additions by Barry Warsaw, Georg Brandl and Benjamin Peterson
"""
from __future__ import annotations
import datetime
import glob
import hashlib
import json
import optparse
import os
import re
import readline # noqa: F401
import shutil
import subprocess
import sys
import tempfile
import urllib.request
from collections.abc import Callable, Generator, Sequence
from contextlib import contextmanager
from dataclasses import dataclass
from functools import cache
from pathlib import Path
from typing import (
Any,
Literal,
Protocol,
Self,
overload,
)
from urllib.request import urlopen
COMMASPACE = ", "
SPACE = " "
tag_cre = re.compile(r"(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:([ab]|rc)(\d+))?$")
class ReleaseShelf(Protocol):
def close(self) -> None: ...
@overload
def get(self, key: Literal["finished"], default: bool | None = None) -> bool: ...
@overload
def get(
self, key: Literal["completed_tasks"], default: list[Task] | None = None
) -> list[Task]: ...
@overload
def get(self, key: Literal["gpg_key"], default: str | None = None) -> str: ...
@overload
def get(self, key: Literal["git_repo"], default: Path | None = None) -> Path: ...
@overload
def get(self, key: Literal["auth_info"], default: str | None = None) -> str: ...
@overload
def get(self, key: Literal["ssh_user"], default: str | None = None) -> str: ...
@overload
def get(
self, key: Literal["ssh_key"], default: str | None = None
) -> str | None: ...
@overload
def get(self, key: Literal["sign_gpg"], default: bool | None = None) -> bool: ...
@overload
def get(
self, key: Literal["security_release"], default: bool | None = None
) -> bool: ...
@overload
def get(self, key: Literal["release"], default: Tag | None = None) -> Tag: ...
@overload
def __getitem__(self, key: Literal["finished"]) -> bool: ...
@overload
def __getitem__(self, key: Literal["completed_tasks"]) -> list[Task]: ...
@overload
def __getitem__(self, key: Literal["gpg_key"]) -> str: ...
@overload
def __getitem__(self, key: Literal["git_repo"]) -> Path: ...
@overload
def __getitem__(self, key: Literal["auth_info"]) -> str: ...
@overload
def __getitem__(self, key: Literal["ssh_user"]) -> str: ...
@overload
def __getitem__(self, key: Literal["ssh_key"]) -> str | None: ...
@overload
def __getitem__(self, key: Literal["sign_gpg"]) -> bool: ...
@overload
def __getitem__(self, key: Literal["security_release"]) -> bool: ...
@overload
def __getitem__(self, key: Literal["release"]) -> Tag: ...
@overload
def __setitem__(self, key: Literal["finished"], value: bool) -> None: ...
@overload
def __setitem__(
self, key: Literal["completed_tasks"], value: list[Task]
) -> None: ...
@overload
def __setitem__(self, key: Literal["gpg_key"], value: str) -> None: ...
@overload
def __setitem__(self, key: Literal["git_repo"], value: Path) -> None: ...
@overload
def __setitem__(self, key: Literal["auth_info"], value: str) -> None: ...
@overload
def __setitem__(self, key: Literal["ssh_user"], value: str) -> None: ...
@overload
def __setitem__(self, key: Literal["ssh_key"], value: str | None) -> None: ...
@overload
def __setitem__(self, key: Literal["sign_gpg"], value: bool) -> None: ...
@overload
def __setitem__(self, key: Literal["security_release"], value: bool) -> None: ...
@overload
def __setitem__(self, key: Literal["release"], value: Tag) -> None: ...
@dataclass
class Task:
function: Callable[[ReleaseShelf], None]
description: str
def __call__(self, db: ReleaseShelf) -> Any:
return getattr(self, "function")(db)
class Tag:
def __init__(self, tag_name: str) -> None:
# if tag is ".", use current directory name as tag
# e.g. if current directory name is "3.4.6",
# "release.py --bump 3.4.6" and "release.py --bump ." are the same
if tag_name == ".":
tag_name = os.path.basename(os.getcwd())
result = tag_cre.match(tag_name)
if result is None:
error(f"tag {tag_name} is not valid")
assert result is not None
data = list(result.groups())
if data[3] is None:
# A final release.
self.is_final = True
data[3] = "f"
else:
self.is_final = False
# For everything else, None means 0.
for i, thing in enumerate(data):
if thing is None:
data[i] = 0
self.major = int(data[0])
self.minor = int(data[1])
self.patch = int(data[2])
self.level = data[3]
self.serial = int(data[4])
# This has the effect of normalizing the version.
self.text = self.normalized()
if self.level != "f":
assert self.level is not None
self.text += self.level + str(self.serial)
self.basic_version = f"{self.major}.{self.minor}"
def __str__(self) -> str:
return self.text
def normalized(self) -> str:
return f"{self.major}.{self.minor}.{self.patch}"
@property
def branch(self) -> str:
if self.is_alpha_release or self.is_feature_freeze_release:
return "main"
return f"{self.major}.{self.minor}"
@property
def is_alpha_release(self) -> bool:
return self.level == "a"
@property
def is_release_candidate(self) -> bool:
return self.level == "rc"
@property
def is_feature_freeze_release(self) -> bool:
return self.level == "b" and self.serial == 1
@property
def is_security_release(self) -> bool:
url = "https://peps.python.org/api/release-cycle.json"
with urlopen(url) as response:
data = json.loads(response.read())
return str(data[self.basic_version]["status"]) == "security"
@property
def nickname(self) -> str:
return self.text.replace(".", "")
@property
def gitname(self) -> str:
return "v" + self.text
@property
def long_name(self) -> str:
if self.is_final:
return self.text
level = {
"a": "alpha",
"b": "beta",
"rc": "release candidate",
}[self.level]
return f"{self.normalized()} {level} {self.serial}"
def next_minor_release(self) -> Self:
return self.__class__(f"{self.major}.{int(self.minor)+1}.0a0")
def as_tuple(self) -> tuple[int, int, int, str, int]:
assert isinstance(self.level, str)
return self.major, self.minor, self.patch, self.level, self.serial
@property
def committed_at(self) -> datetime.datetime:
# Fetch the epoch of the tagged commit for build reproducibility.
proc = subprocess.run(
["git", "log", self.gitname, "-1", "--pretty=%ct"], stdout=subprocess.PIPE
)
if proc.returncode != 0:
error(f"Couldn't fetch the epoch of tag {self.gitname}")
return datetime.datetime.fromtimestamp(
int(proc.stdout.decode().strip()), tz=datetime.timezone.utc
)
@property
def includes_docs(self) -> bool:
"""True if docs should be included in the release"""
return self.is_final or self.is_release_candidate
@property
def doc_version(self) -> str:
"""Text used for notes in docs like 'Added in x.y'"""
# - ignore levels (alpha/beta/rc are preparation for the full release)
# - use just X.Y for patch 0
if self.patch == 0:
return f"{self.major}.{self.minor}"
else:
return f"{self.major}.{self.minor}.{self.patch}"
def error(*msgs: str) -> None:
print("**ERROR**", file=sys.stderr)
for msg in msgs:
print(msg, file=sys.stderr)
sys.exit(1)
def run_cmd(
cmd: Sequence[str] | str, silent: bool = False, shell: bool = False, **kwargs: Any
) -> None:
if shell:
cmd = SPACE.join(cmd)
if not silent:
print(f"Executing {cmd}")
try:
if silent:
subprocess.check_call(cmd, shell=shell, stdout=subprocess.PIPE, **kwargs)
else:
subprocess.check_call(cmd, shell=shell, **kwargs)
except subprocess.CalledProcessError:
error(f"{cmd} failed")
def ask_question(question: str) -> bool:
answer = ""
print(question)
while answer not in ("yes", "no"):
answer = input("Enter yes or no: ")
if answer == "yes":
return True
elif answer == "no":
return False
else:
print("Please enter yes or no.")
return True
readme_re = re.compile(r"This is Python version 3\.\d").match
def chdir_to_repo_root() -> str:
# find the root of the local CPython repo
# note that we can't ask git, because we might
# be in an exported directory tree!
# we intentionally start in a (probably nonexistent) subtree
# the first thing the while loop does is .., basically
path = os.path.abspath("garglemox")
while True:
next_path = os.path.dirname(path)
if next_path == path:
sys.exit("You're not inside a CPython repo right now!")
path = next_path
os.chdir(path)
def test_first_line(
filename: str,
test: Callable[[str], object],
) -> bool:
if not os.path.exists(filename):
return False
with open(filename) as f:
lines = f.read().split("\n")
if not (lines and test(lines[0])):
return False
return True
if not test_first_line("README.rst", readme_re):
continue
if not test_first_line("LICENSE", "A. HISTORY OF THE SOFTWARE".__eq__):
continue
if not os.path.exists("Include/Python.h"):
continue
if not os.path.exists("Python/ceval.c"):
continue
break
root = path
return root
def get_output(args: list[str]) -> bytes:
return subprocess.check_output(args)
def check_env() -> None:
if "EDITOR" not in os.environ:
error("editor not detected.", "Please set your EDITOR environment variable")
if not os.path.exists(".git"):
error("CWD is not a git clone")
def get_arg_parser() -> optparse.OptionParser:
usage = "%prog [options] tagname"
p = optparse.OptionParser(usage=usage)
p.add_option(
"-b",
"--bump",
default=False,
action="store_true",
help="bump the revision number in important files",
)
p.add_option(
"-e",
"--export",
default=False,
action="store_true",
help="Export the git tag to a tarball and build docs",
)
p.add_option(
"-u",
"--upload",
metavar="username",
help="Upload the tarballs and docs to dinsdale",
)
p.add_option(
"-m",
"--branch",
default=False,
action="store_true",
help="Create a maintenance branch to go along with the release",
)
p.add_option(
"-t",
"--tag",
default=False,
action="store_true",
help="Tag the release in Subversion",
)
p.add_option(
"-d",
"--done",
default=False,
action="store_true",
help="Do post-release cleanups (i.e. you're done!)",
)
p.add_option(
"--skip-docs",
default=False,
action="store_true",
help="Skip building the documentation during export",
)
return p
def constant_replace(
filename: str,
updated_constants: str,
comment_start: str = "/*",
comment_end: str = "*/",
) -> None:
"""Inserts in between --start constant-- and --end constant-- in a file"""
start_tag = comment_start + "--start constants--" + comment_end
end_tag = comment_start + "--end constants--" + comment_end
with open(filename, encoding="ascii") as infile, open(
filename + ".new", "w", encoding="ascii"
) as outfile:
found_constants = False
waiting_for_end = False
for line in infile:
if line[:-1] == start_tag:
print(start_tag, file=outfile)
print(updated_constants, file=outfile)
print(end_tag, file=outfile)
waiting_for_end = True
found_constants = True
elif line[:-1] == end_tag:
waiting_for_end = False
elif waiting_for_end:
pass
else:
outfile.write(line)
if not found_constants:
error(f"Constant section delimiters not found: {filename}")
os.rename(filename + ".new", filename)
def tweak_patchlevel(
tag: Tag, filename: str = "Include/patchlevel.h", done: bool = False
) -> None:
print(f"Updating {filename}...", end=" ")
template = '''
#define PY_MAJOR_VERSION\t{tag.major}
#define PY_MINOR_VERSION\t{tag.minor}
#define PY_MICRO_VERSION\t{tag.patch}
#define PY_RELEASE_LEVEL\t{level_def}
#define PY_RELEASE_SERIAL\t{tag.serial}
/* Version as a string */
#define PY_VERSION \t\"{tag.text}{plus}"'''.strip()
assert isinstance(tag.level, str)
level_def = {
"a": "PY_RELEASE_LEVEL_ALPHA",
"b": "PY_RELEASE_LEVEL_BETA",
"rc": "PY_RELEASE_LEVEL_GAMMA",
"f": "PY_RELEASE_LEVEL_FINAL",
}[tag.level]
new_constants = template.format(
tag=tag, level_def=level_def, plus=done and "+" or ""
)
if tag.as_tuple() >= (3, 7, 0, "a", 3):
new_constants = new_constants.expandtabs()
constant_replace(filename, new_constants)
print("done")
@cache
def get_pep_number(version: str) -> str:
"""Fetch PEP number for a Python version from peps.python.org.
Returns the PEP number as a string, or "TODO" if not found.
"""
url = "https://peps.python.org/api/release-cycle.json"
with urllib.request.urlopen(url, timeout=10) as response:
data = json.loads(response.read().decode())
if version in data:
pep = data[version].get("pep")
if pep:
return str(pep)
return "TODO"
def tweak_readme(tag: Tag, filename: str = "README.rst") -> None:
print(f"Updating {filename}...", end=" ")
readme = Path(filename)
# Update first line: "This is Python version X.Y.Z {release_level} N"
# and update length of underline in second line to match.
lines = readme.read_text().split("\n")
this_is = f"This is Python version {tag.long_name}"
underline = "=" * len(this_is)
lines[0] = this_is
lines[1] = underline
content = "\n".join(lines)
DOCS_URL = r"https://docs\.python\.org/"
X_Y = r"\d+\.\d+"
# Replace in: 3.14 <https://docs.python.org/3.14/whatsnew/3.14.html>`_
content = re.sub(
rf"{X_Y} (<{DOCS_URL}){X_Y}(/whatsnew/){X_Y}(\.html>`_)",
rf"{tag.basic_version} \g<1>{tag.basic_version}\g<2>{tag.basic_version}\g<3>",
content,
)
# Replace in: `Documentation for Python 3.14 <https://docs.python.org/3.14/>`_
content = re.sub(
rf"(`Documentation for Python ){X_Y}( <{DOCS_URL}){X_Y}(/>`_)",
rf"\g<1>{tag.basic_version}\g<2>{tag.basic_version}\g<3>",
content,
)
# Get PEP number for this version
pep_number = get_pep_number(tag.basic_version)
pep_padded = pep_number.zfill(4) if pep_number != "TODO" else "TODO"
# Replace in: `PEP 745 <https://peps.python.org/pep-0745/>`__ for Python 3.14
content = re.sub(
rf"(`PEP )\d+( <https://peps\.python\.org/pep-)\d+(/>`__ for Python ){X_Y}",
rf"\g<1>{pep_number}\g<2>{pep_padded}\g<3>{tag.basic_version}",
content,
)
readme.write_text(content)
print("done")
def bump(tag: Tag) -> None:
print(f"Bumping version to {tag}")
tweak_patchlevel(tag)
tweak_readme(tag)
extra_work = False
other_files = []
if tag.patch == 0 and tag.level == "a" and tag.serial == 0:
extra_work = True
other_files += [
"configure.ac",
"Doc/tutorial/interpreter.rst",
"Doc/tutorial/stdlib.rst",
"Doc/tutorial/stdlib2.rst",
"PC/pyconfig.h.in",
"PCbuild/rt.bat",
".github/ISSUE_TEMPLATE/bug.yml",
".github/ISSUE_TEMPLATE/crash.yml",
]
print("\nManual editing time...")
for filename in other_files:
if os.path.exists(filename):
print(f"Edit {filename}")
manual_edit(filename)
else:
print(f"Skipping {filename}")
print("Bumped revision")
if extra_work:
print("configure.ac has changed; re-run autotools!")
print("Please commit and use --tag")
def manual_edit(filename: str) -> None:
editor = os.environ["EDITOR"].split()
run_cmd([*editor, filename])
@contextmanager
def pushd(new: str) -> Generator[None, None, None]:
print(f"chdir'ing to {new}")
old = os.getcwd()
os.chdir(new)
try:
yield
finally:
os.chdir(old)
def make_dist(name: str) -> None:
try:
os.mkdir(name)
except OSError:
if os.path.isdir(name):
print(f"WARNING: dist dir {name} already exists", file=sys.stderr)
else:
error(f"{name}/ is not a directory")
else:
print(f"created dist directory {name}")
def tarball(source: str, clamp_mtime: str) -> None:
"""Build tarballs for a directory."""
print("Making .tgz")
base = os.path.basename(source)
tgz = os.path.join("src", base + ".tgz")
xz = os.path.join("src", base + ".tar.xz")
# Recommended options for creating reproducible tarballs from:
# https://www.gnu.org/software/tar/manual/html_node/Reproducibility.html#Reproducibility
# and https://reproducible-builds.org/docs/archives/
repro_options = [
# Sorts the entries in the tarball by name.
"--sort=name",
# Sets a maximum 'modified time' of entries in tarball.
f"--mtime={clamp_mtime}",
"--clamp-mtime",
# Sets the owner uid and gid to 0.
"--owner=0",
"--group=0",
"--numeric-owner",
# Omits process ID, file access, and status change times.
"--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime",
# Omit irrelevant info about file permissions.
"--mode=go+u,go-w",
]
run_cmd(
[
"tar",
"cf",
tgz,
*repro_options,
"--use-compress-program",
"gzip --no-name -9",
source,
]
)
print("Making .tar.xz")
run_cmd(["tar", "cJf", xz, *repro_options, source])
print("Calculating SHA-256 sums")
checksum_tgz = hashlib.sha256()
with open(tgz, "rb") as data:
checksum_tgz.update(data.read())
checksum_xz = hashlib.sha256()
with open(xz, "rb") as data:
checksum_xz.update(data.read())
print(f" {checksum_tgz.hexdigest()} {os.path.getsize(tgz):8} {tgz}")
print(f" {checksum_xz.hexdigest()} {os.path.getsize(xz):8} {xz}")
def export(tag: Tag, silent: bool = False, skip_docs: bool = False) -> None:
make_dist(tag.text)
print("Exporting tag:", tag.text)
archivename = f"Python-{tag.text}"
# I have not figured out how to get git to directly produce an
# archive directory like hg can, so use git to produce a temporary
# tarball then expand it with tar.
archivetempfile = f"{archivename}.tar"
run_cmd(
[
"git",
"archive",
"--format=tar",
f"--prefix={archivename}/",
"-o",
archivetempfile,
tag.gitname,
],
silent=silent,
)
with pushd(tag.text):
archivetempfile = f"../{archivetempfile}"
run_cmd(["tar", "-xf", archivetempfile], silent=silent)
os.unlink(archivetempfile)
with pushd(archivename):
# Touch a few files that get generated so they're up-to-date in
# the tarball.
#
# Note, with the demise of "make touch" and the hg touch
# extension, touches should not be needed anymore,
# but keep it for now as a reminder.
maybe_touchables = [
"Include/internal/pycore_ast.h",
"Include/internal/pycore_ast_state.h",
"Python/Python-ast.c",
"Python/opcode_targets.h",
]
touchables = [file for file in maybe_touchables if os.path.exists(file)]
print(
"Touching:",
COMMASPACE.join(name.rsplit("/", 1)[-1] for name in touchables),
)
for name in touchables:
os.utime(name, None)
# build docs *before* we do "blurb export"
# because docs now depend on Misc/NEWS.d
# and we remove Misc/NEWS.d as part of cleanup for export
#
# If --skip-docs is provided we don't build and docs.
if not skip_docs and (tag.is_final or tag.level == "rc"):
docdist = build_docs()
print("Using blurb to build Misc/NEWS")
run_cmd(["blurb", "merge"], silent=silent)
# Remove files we don't want to ship in tarballs.
print("Removing VCS .*ignore, .git*, Misc/NEWS.d, et al")
for name in (".gitattributes", ".gitignore"):
try:
os.unlink(name)
except OSError:
pass
# Remove directories we don't want to ship in tarballs.
run_cmd(["blurb", "export"], silent=silent)
for name in (".azure-pipelines", ".git", ".github", "Misc/mypy"):
shutil.rmtree(name, ignore_errors=True)
if not skip_docs and (tag.is_final or tag.level == "rc"):
shutil.copytree(docdist, "docs")
with pushd(os.path.join(archivename, "Doc")):
print("Removing doc build artifacts")
shutil.rmtree("venv", ignore_errors=True)
shutil.rmtree("build", ignore_errors=True)
shutil.rmtree("dist", ignore_errors=True)
with pushd(archivename):
print("Zapping pycs")
run_cmd(
[
"find",
".",
"-depth",
"-name",
"__pycache__",
"-exec",
"rm",
"-rf",
"{}",
";",
],
silent=silent,
)
run_cmd(
["find", ".", "-name", "*.py[co]", "-exec", "rm", "-f", "{}", ";"],
silent=silent,
)
os.mkdir("src")
tarball(archivename, tag.committed_at.strftime("%Y-%m-%d %H:%M:%SZ"))
print()
print(f"**Now extract the archives in {tag.text}/src and run the tests**")
print("**You may also want to run make install and re-test**")
def build_docs() -> str:
"""Build and tarball the documentation"""
print("Building docs")
with tempfile.TemporaryDirectory() as venv:
run_cmd(["python3", "-m", "venv", venv])
pip = os.path.join(venv, "bin", "pip")
run_cmd([pip, "install", "-r", "Doc/requirements.txt"])
sphinx_build = os.path.join(venv, "bin", "sphinx-build")
blurb = os.path.join(venv, "bin", "blurb")
docs_env = {
**os.environ,
"BLURB": blurb,
"SPHINXBUILD": sphinx_build,
"SPHINXOPTS": "-j10",
}
with pushd("Doc"):
run_cmd(("make", "dist-epub"), env=docs_env)
run_cmd(("make", "dist-html"), env=docs_env)
run_cmd(("make", "dist-texinfo"), env=docs_env)
run_cmd(("make", "dist-text"), env=docs_env)
return os.path.abspath("dist")
def upload(tag: Tag, username: str) -> None:
"""scp everything to dinsdale"""
address = f'"{username}@dinsdale.python.org:'
def scp(from_loc: str, to_loc: str) -> None:
run_cmd(["scp", from_loc, address + to_loc])
with pushd(tag.text):
print("Uploading source tarballs")
scp("src", f"/data/python-releases/{tag.nickname}")
print("Upload doc tarballs")
scp("docs", f"/data/python-releases/doc/{tag.nickname}")
print(
"* Now change the permissions on the tarballs so they are "
"writable by the webmaster group. *"
)
def make_tag(tag: Tag, *, sign_gpg: bool = True) -> bool:
# make sure we've run blurb export
good_files = glob.glob("Misc/NEWS.d/" + str(tag) + ".rst")
bad_files = list(glob.glob("Misc/NEWS.d/next/*/0*.rst"))
bad_files.extend(glob.glob("Misc/NEWS.d/next/*/2*.rst"))
if bad_files or not good_files:
print('It doesn\'t look like you ran "blurb release" yet.')
if bad_files:
print("There are still reST files in NEWS.d/next/...")
if not good_files:
print(f"There is no Misc/NEWS.d/{tag}.rst file.")
if not ask_question("Are you sure you want to tag?"):
print("Aborting.")
return False
# make sure we're on the correct branch
if tag.patch > 0:
if (
get_output(["git", "name-rev", "--name-only", "HEAD"]).strip().decode()
!= f"branch-{tag}"
):
print("It doesn't look like you're on the correct branch.")
if not ask_question("Are you sure you want to tag?"):
print("Aborting.")
return False
if sign_gpg:
print("Signing tag")
uid = os.environ.get("GPG_KEY_FOR_RELEASE")
if not uid:
print("List of available private keys:")
run_cmd(['gpg -K | grep -A 1 "^sec"'], shell=True)
uid = input("Please enter key ID to use for signing: ")
run_cmd(
["git", "tag", "-s", "-u", uid, tag.gitname, "-m", "Python " + str(tag)]
)
else:
print("Creating tag")
run_cmd(["git", "tag", tag.gitname, "-m", "Python " + str(tag)])
return True
def done(tag: Tag) -> None:
tweak_patchlevel(tag, done=True)
def main(argv: Any) -> None:
chdir_to_repo_root()
parser = get_arg_parser()
options, args = parser.parse_args(argv)
if options.skip_docs and not options.export:
error("--skip-docs option has no effect without --export")
if len(args) != 2:
if "RELEASE_TAG" not in os.environ:
parser.print_usage()
sys.exit(1)
tagname = os.environ["RELEASE_TAG"]
else:
tagname = args[1]
tag = Tag(tagname)
if not (options.export or options.upload):
check_env()
if options.bump:
bump(tag)
if options.tag:
make_tag(tag)
if options.export:
export(tag, skip_docs=options.skip_docs)
if options.upload:
upload(tag, options.upload)
if options.done:
done(tag)
if __name__ == "__main__":
main(sys.argv)
================================================
FILE: requirements.in
================================================
--only-binary :all:
paramiko
alive_progress>=3.3.0
python-gnupg
aiohttp
blurb>=1.2.1
# Pending https://github.com/python/release-tools/pull/289
sigstore>=3,<4
================================================
FILE: requirements.txt
================================================
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
# pip-compile --generate-hashes --output-file=requirements.txt requirements.in
#
--only-binary :all:
about-time==4.2.1 \
--hash=sha256:8bbf4c75fe13cbd3d72f49a03b02c5c7dca32169b6d49117c257e7eb3eaee341
# via alive-progress
aiohappyeyeballs==2.6.1 \
--hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8
# via aiohttp
aiohttp==3.13.3 \
--hash=sha256:01ad2529d4b5035578f5081606a465f3b814c542882804e2e8cda61adf5c71bf \
--hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \
--hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \
--hash=sha256:084911a532763e9d3dd95adf78a78f4096cd5f58cdc18e6fdbc1b58417a45423 \
--hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \
--hash=sha256:0db318f7a6f065d84cb1e02662c526294450b314a02bd9e2a8e67f0d8564ce40 \
--hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \
--hash=sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf \
--hash=sha256:147e422fd1223005c22b4fe080f5d93ced44460f5f9c105406b753612b587821 \
--hash=sha256:1cb93e166e6c28716c8c6aeb5f99dfb6d5ccf482d29fe9bf9a794110e6d0ab64 \
--hash=sha256:215a685b6fbbfcf71dfe96e3eba7a6f58f10da1dfdf4889c7dd856abe430dca7 \
--hash=sha256:2712039939ec963c237286113c68dbad80a82a4281543f3abf766d9d73228998 \
--hash=sha256:27234ef6d85c914f9efeb77ff616dbf4ad2380be0cda40b4db086ffc7ddd1b7d \
--hash=sha256:28e027cf2f6b641693a09f631759b4d9ce9165099d2b5d92af9bd4e197690eea \
--hash=sha256:2b8d8ddba8f95ba17582226f80e2de99c7a7948e66490ef8d947e272a93e9463 \
--hash=sha256:2ba0eea45eb5cc3172dbfc497c066f19c41bac70963ea1a67d51fc92e4cf9a80 \
--hash=sha256:2be0e9ccf23e8a94f6f0650ce06042cefc6ac703d0d7ab6c7a917289f2539ad4 \
--hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \
--hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \
--hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \
--hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \
--hash=sha256:31a83ea4aead760dfcb6962efb1d861db48c34379f2ff72db9ddddd4cda9ea2e \
--hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \
--hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \
--hash=sha256:37239e9f9a7ea9ac5bf6b92b0260b01f8a22281996da609206a84df860bc1261 \
--hash=sha256:37da61e244d1749798c151421602884db5270faf479cf0ef03af0ff68954c9dd \
--hash=sha256:3b61b7169ababd7802f9568ed96142616a9118dd2be0d1866e920e77ec8fa92a \
--hash=sha256:3d9908a48eb7416dc1f4524e69f1d32e5d90e3981e4e37eb0aa1cd18f9cfa2a4 \
--hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \
--hash=sha256:4021b51936308aeea0367b8f006dc999ca02bc118a0cc78c303f50a2ff6afb91 \
--hash=sha256:40c5e40ecc29ba010656c18052b877a1c28f84344825efa106705e835c28530f \
--hash=sha256:425c126c0dc43861e22cb1c14ba4c8e45d09516d0a3ae0a3f7494b79f5f233a3 \
--hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \
--hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \
--hash=sha256:49a03727c1bba9a97d3e93c9f93ca03a57300f484b6e935463099841261195d3 \
--hash=sha256:4ae5b5a0e1926e504c81c5b84353e7a5516d8778fbbff00429fe7b05bb25cbce \
--hash=sha256:4e239d501f73d6db1522599e14b9b321a7e3b1de66ce33d53a765d975e9f4808 \
--hash=sha256:56339a36b9f1fc708260c76c87e593e2afb30d26de9ae1eb445b5e051b98a7a1 \
--hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \
--hash=sha256:5b179331a481cb5529fca8b432d8d3c7001cb217513c94cd72d668d1248688a3 \
--hash=sha256:5b6073099fb654e0a068ae678b10feff95c5cae95bbfcbfa7af669d361a8aa6b \
--hash=sha256:5d2d94f1f5fcbe40838ac51a6ab5704a6f9ea42e72ceda48de5e6b898521da51 \
--hash=sha256:5dff64413671b0d3e7d5918ea490bdccb97a4ad29b3f311ed423200b2203e01c \
--hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \
--hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \
--hash=sha256:642f752c3eb117b105acbd87e2c143de710987e09860d674e068c4c2c441034f \
--hash=sha256:65d2ccb7eabee90ce0503c17716fc77226be026dcc3e65cce859a30db715025b \
--hash=sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e \
--hash=sha256:694976222c711d1d00ba131904beb60534f93966562f64440d0c9d41b8cdb440 \
--hash=sha256:697753042d57f4bf7122cab985bf15d0cef23c770864580f5af4f52023a56bd6 \
--hash=sha256:69c56fbc1993fa17043e24a546959c0178fe2b5782405ad4559e6c13975c15e3 \
--hash=sha256:6de499a1a44e7de70735d0b39f67c8f25eb3d91eb3103be99ca0fa882cdd987d \
--hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \
--hash=sha256:75ca857eba4e20ce9f546cd59c7007b33906a4cd48f2ff6ccf1ccfc3b646f279 \
--hash=sha256:7a4a94eb787e606d0a09404b9c38c113d3b099d508021faa615d70a0131907ce \
--hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \
--hash=sha256:7bfdc049127717581866fa4708791220970ce291c23e28ccf3922c700740fdc0 \
--hash=sha256:7e63f210bc1b57ef699035f2b4b6d9ce096b5914414a49b0997c839b2bd2223c \
--hash=sha256:7f9120f7093c2a32d9647abcaf21e6ad275b4fbec5b55969f978b1a97c7c86bf \
--hash=sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591 \
--hash=sha256:80dd4c21b0f6237676449c6baaa1039abae86b91636b6c91a7f8e61c87f89540 \
--hash=sha256:81e97251d9298386c2b7dbeb490d3d1badbdc69107fb8c9299dd04eb39bddc0e \
--hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \
--hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \
--hash=sha256:859bd3f2156e81dd01432f5849fc73e2243d4a487c4fd26609b1299534ee1845 \
--hash=sha256:87797e645d9d8e222e04160ee32aa06bc5c163e8499f24db719e7852ec23093a \
--hash=sha256:87b9aab6d6ed88235aa2970294f496ff1a1f9adcd724d800e9b952395a80ffd9 \
--hash=sha256:8a60e60746623925eab7d25823329941aee7242d559baa119ca2b253c88a7bd6 \
--hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \
--hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \
--hash=sha256:947c26539750deeaee933b000fb6517cc770bbd064bad6033f1cff4803881e43 \
--hash=sha256:96d604498a7c782cb15a51c406acaea70d8c027ee6b90c569baa6e7b93073679 \
--hash=sha256:988a8c5e317544fdf0d39871559e67b6341065b87fceac641108c2096d5506b7 \
--hash=sha256:9a9dc347e5a3dc7dfdbc1f82da0ef29e388ddb2ed281bfce9dd8248a313e62b7 \
--hash=sha256:9ae8dd55c8e6c4257eae3a20fd2c8f41edaea5992ed67156642493b8daf3cecc \
--hash=sha256:9af5e68ee47d6534d36791bbe9b646d2a7c7deb6fc24d7943628edfbb3581f29 \
--hash=sha256:9b174f267b5cfb9a7dba9ee6859cecd234e9a681841eb85068059bc867fb8f02 \
--hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \
--hash=sha256:9d4c940f02f49483b18b079d1c27ab948721852b281f8b015c058100e9421dd1 \
--hash=sha256:9ebf57d09e131f5323464bd347135a88622d1c0976e88ce15b670e7ad57e4bd6 \
--hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \
--hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \
--hash=sha256:a2212ad43c0833a873d0fb3c63fa1bacedd4cf6af2fee62bf4b739ceec3ab239 \
--hash=sha256:a45530014d7a1e09f4a55f4f43097ba0fd155089372e105e4bff4ca76cb1b168 \
--hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \
--hash=sha256:af71fff7bac6bb7508956696dce8f6eec2bbb045eceb40343944b1ae62b5ef11 \
--hash=sha256:b04be762396457bef43f3597c991e192ee7da460a4953d7e647ee4b1c28e7046 \
--hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \
--hash=sha256:b1a6102b4d3ebc07dad44fbf07b45bb600300f15b552ddf1851b5390202ea2e3 \
--hash=sha256:b46020d11d23fe16551466c77823df9cc2f2c1e63cc965daf67fa5eec6ca1877 \
--hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \
--hash=sha256:b903a4dfee7d347e2d87697d0713be59e0b87925be030c9178c5faa58ea58d5c \
--hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \
--hash=sha256:b99281b0704c103d4e11e72a76f1b543d4946fea7dd10767e7e1b5f00d4e5704 \
--hash=sha256:bae5c2ed2eae26cc382020edad80d01f36cb8e746da40b292e68fec40421dc6a \
--hash=sha256:bb4f7475e359992b580559e008c598091c45b5088f28614e855e42d39c2f1033 \
--hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \
--hash=sha256:bfc1cc2fe31a6026a8a88e4ecfb98d7f6b1fec150cfd708adbfd1d2f42257c29 \
--hash=sha256:c014c7ea7fb775dd015b2d3137378b7be0249a448a1612268b5a90c2d81de04d \
--hash=sha256:c048058117fd649334d81b4b526e94bde3ccaddb20463a815ced6ecbb7d11160 \
--hash=sha256:c0e2d366af265797506f0283487223146af57815b388623f0357ef7eac9b209d \
--hash=sha256:c19b90316ad3b24c69cd78d5c9b4f3aa4497643685901185b65166293d36a00f \
--hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \
--hash=sha256:c6b8568a3bb5819a0ad087f16d40e5a3fb6099f39ea1d5625a3edc1e923fc538 \
--hash=sha256:d32764c6c9aafb7fb55366a224756387cd50bfa720f32b88e0e6fa45b27dcf29 \
--hash=sha256:d5a372fd5afd301b3a89582817fdcdb6c34124787c70dbcc616f259013e7eef7 \
--hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \
--hash=sha256:dca68018bf48c251ba17c72ed479f4dafe9dbd5a73707ad8d28a38d11f3d42af \
--hash=sha256:de2c184bb1fe2cbd2cefba613e9db29a5ab559323f994b6737e370d3da0ac455 \
--hash=sha256:e3531d63d3bdfa7e3ac5e9b27b2dd7ec9df3206a98e0b3445fa906f233264c57 \
--hash=sha256:e50a2e1404f063427c9d027378472316201a2290959a295169bcf25992d04558 \
--hash=sha256:e636b3c5f61da31a92bf0d91da83e58fdfa96f178ba682f11d24f31944cdd28c \
--hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \
--hash=sha256:f33ed1a2bf1997a36661874b017f5c4b760f41266341af36febaf271d179f6d7 \
--hash=sha256:f76c1e3fe7d7c8afad7ed193f89a292e1999608170dcc9751a7462a87dfd5bc0 \
--hash=sha256:f9444f105664c4ce47a2a7171a2418bce5b7bae45fb610f4e2c36045d85911d3 \
--hash=sha256:fc290605db2a917f6e81b0e1e0796469871f5af381ce15c604a3c5c7e51cb730 \
--hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa \
--hash=sha256:fee0c6bc7db1de362252affec009707a17478a00ec69f797d23ca256e36d5940
# via -r requirements.in
aiosignal==1.4.0 \
--hash=sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e
# via aiohttp
alive-progress==3.3.0 \
--hash=sha256:63dd33bb94cde15ad9e5b666dbba8fedf71b72a4935d6fb9a92931e69402c9ff
# via -r requirements.in
annotated-types==0.7.0 \
--hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53
# via pydantic
attrs==24.3.0 \
--hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308
# via aiohttp
bcrypt==4.2.1 \
--hash=sha256:041fa0155c9004eb98a232d54da05c0b41d4b8e66b6fc3cb71b4b3f6144ba837 \
--hash=sha256:04e56e3fe8308a88b77e0afd20bec516f74aecf391cdd6e374f15cbed32783d6 \
--hash=sha256:1340411a0894b7d3ef562fb233e4b6ed58add185228650942bdc885362f32c17 \
--hash=sha256:533e7f3bcf2f07caee7ad98124fab7499cb3333ba2274f7a36cf1daee7409d99 \
--hash=sha256:687cf30e6681eeda39548a93ce9bfbb300e48b4d445a43db4298d2474d2a1e54 \
--hash=sha256:76132c176a6d9953cdc83c296aeaed65e1a708485fd55abf163e0d9f8f16ce0e \
--hash=sha256:76d3e352b32f4eeb34703370e370997065d28a561e4a18afe4fef07249cb4396 \
--hash=sha256:807261df60a8b1ccd13e6599c779014a362ae4e795f5c59747f60208daddd96d \
--hash=sha256:89df2aea2c43be1e1fa066df5f86c8ce822ab70a30e4c210968669565c0f4685 \
--hash=sha256:8ad2f4528cbf0febe80e5a3a57d7a74e6635e41af1ea5675282a33d769fba413 \
--hash=sha256:8c458cd103e6c5d1d85cf600e546a639f234964d0228909d8f8dbeebff82d526 \
--hash=sha256:8dbd0747208912b1e4ce730c6725cb56c07ac734b3629b60d4398f082ea718ad \
--hash=sha256:909faa1027900f2252a9ca5dfebd25fc0ef1417943824783d1c8418dd7d6df4a \
--hash=sha256:aaa2e285be097050dba798d537b6efd9b698aa88eef52ec98d23dcd6d7cf6fea \
--hash=sha256:adadd36274510a01f33e6dc08f5824b97c9580583bd4487c564fc4617b328005 \
--hash=sha256:b1ee315739bc8387aa36ff127afc99120ee452924e0df517a8f3e4c0187a0f5f \
--hash=sha256:b588af02b89d9fad33e5f98f7838bf590d6d692df7153647724a7f20c186f6bf \
--hash=sha256:b7703ede632dc945ed1172d6f24e9f30f27b1b1a067f32f68bf169c5f08d0425 \
--hash=sha256:c6f5fa3775966cca251848d4d5393ab016b3afed251163c1436fefdec3b02c84 \
--hash=sha256:cde78d385d5e93ece5479a0a87f73cd6fa26b171c786a884f955e165032b262c \
--hash=sha256:cfdf3d7530c790432046c40cda41dfee8c83e29482e6a604f8930b9930e94139 \
--hash=sha256:e158009a54c4c8bc91d5e0da80920d048f918c61a581f0a63e4e93bb556d362f \
--hash=sha256:e84e0e6f8e40a242b11bce56c313edc2be121cec3e0ec2d76fce01f6af33c07c \
--hash=sha256:f85b1ffa09240c89aa2e1ae9f3b1c687104f7b2b9d2098da4e923f1b7082d331
# via paramiko
betterproto==2.0.0b6 \
--hash=sha256:a0839ec165d110a69d0d116f4d0e2bec8d186af4db826257931f0831dab73fcf
# via sigstore-protobuf-specs
blurb==2.0.0 \
--hash=sha256:f6d0e858dbe94765f6a89b8228217ffdb9c19cff08fc8f2c3153954846d31aa1
# via -r requirements.in
certifi==2024.12.14 \
--hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56
# via requests
cffi==2.0.0 \
--hash=sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb \
--hash=sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b \
--hash=sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f \
--hash=sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9 \
--hash=sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44 \
--hash=sha256:0f6084a0ea23d05d20c3edcda20c3d006f9b6f3fefeac38f59262e10cef47ee2 \
--hash=sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c \
--hash=sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75 \
--hash=sha256:1cd13c99ce269b3ed80b417dcd591415d3372bcac067009b6e0f59c7d4015e65 \
--hash=sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e \
--hash=sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a \
--hash=sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e \
--hash=sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25 \
--hash=sha256:2081580ebb843f759b9f617314a24ed5738c51d2aee65d31e02f6f7a2b97707a \
--hash=sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe \
--hash=sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b \
--hash=sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91 \
--hash=sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592 \
--hash=sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187 \
--hash=sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c \
--hash=sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1 \
--hash=sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94 \
--hash=sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba \
--hash=sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb \
--hash=sha256:3f4d46d8b35698056ec29bca21546e1551a205058ae1a181d871e278b0b28165 \
--hash=sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca \
--hash=sha256:4647afc2f90d1ddd33441e5b0e85b16b12ddec4fca55f0d9671fef036ecca27c \
--hash=sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6 \
--hash=sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c \
--hash=sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0 \
--hash=sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743 \
--hash=sha256:61d028e90346df14fedc3d1e5441df818d095f3b87d286825dfcbd6459b7ef63 \
--hash=sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5 \
--hash=sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5 \
--hash=sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4 \
--hash=sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d \
--hash=sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b \
--hash=sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93 \
--hash=sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205 \
--hash=sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27 \
--hash=sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512 \
--hash=sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d \
--hash=sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c \
--hash=sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037 \
--hash=sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26 \
--hash=sha256:89472c9762729b5ae1ad974b777416bfda4ac5642423fa93bd57a09204712322 \
--hash=sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb \
--hash=sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c \
--hash=sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8 \
--hash=sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4 \
--hash=sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414 \
--hash=sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9 \
--hash=sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664 \
--hash=sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9 \
--hash=sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775 \
--hash=sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739 \
--hash=sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc \
--hash=sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062 \
--hash=sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe \
--hash=sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9 \
--hash=sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92 \
--hash=sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5 \
--hash=sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13 \
--hash=sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d \
--hash=sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26 \
--hash=sha256:cb527a79772e5ef98fb1d700678fe031e353e765d1ca2d409c92263c6d43e09f \
--hash=sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495 \
--hash=sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b \
--hash=sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6 \
--hash=sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c \
--hash=sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef \
--hash=sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5 \
--hash=sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18 \
--hash=sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad \
--hash=sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3 \
--hash=sha256:de8dad4425a6ca6e4e5e297b27b5c824ecc7581910bf9aee86cb6835e6812aa7 \
--hash=sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5 \
--hash=sha256:e6e73b9e02893c764e7e8d5bb5ce277f1a009cd5243f8228f75f842bf937c534 \
--hash=sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49 \
--hash=sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2 \
--hash=sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5 \
--hash=sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453 \
--hash=sha256:fe562eb1a64e67dd297ccc4f5addea2501664954f2692b69a76449ec7913ecbf
# via
# cryptography
# pynacl
charset-normalizer==3.4.1 \
--hash=sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537 \
--hash=sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa \
--hash=sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a \
--hash=sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294 \
--hash=sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b \
--hash=sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd \
--hash=sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601 \
--hash=sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd \
--hash=sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4 \
--hash=sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d \
--hash=sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2 \
--hash=sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313 \
--hash=sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd \
--hash=sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa \
--hash=sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8 \
--hash=sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1 \
--hash=sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2 \
--hash=sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496 \
--hash=sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d \
--hash=sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b \
--hash=sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e \
--hash=sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a \
--hash=sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4 \
--hash=sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca \
--hash=sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78 \
--hash=sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408 \
--hash=sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5 \
--hash=sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f \
--hash=sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a \
--hash=sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765 \
--hash=sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6 \
--hash=sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146 \
--hash=sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6 \
--hash=sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9 \
--hash=sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd \
--hash=sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c \
--hash=sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f \
--hash=sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545 \
--hash=sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176 \
--hash=sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770 \
--hash=sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824 \
--hash=sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f \
--hash=sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf \
--hash=sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487 \
--hash=sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d \
--hash=sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd \
--hash=sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b \
--hash=sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534 \
--hash=sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f \
--hash=sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b \
--hash=sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9 \
--hash=sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd \
--hash=sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125 \
--hash=sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9 \
--hash=sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de \
--hash=sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11 \
--hash=sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d \
--hash=sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35 \
--hash=sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f \
--hash=sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda \
--hash=sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7 \
--hash=sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a \
--hash=sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971 \
--hash=sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8 \
--hash=sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41 \
--hash=sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d \
--hash=sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f \
--hash=sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757 \
--hash=sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a \
--hash=sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886 \
--hash=sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77 \
--hash=sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76 \
--hash=sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247 \
--hash=sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85 \
--hash=sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb \
--hash=sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7 \
--hash=sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e \
--hash=sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6 \
--hash=sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037 \
--hash=sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1 \
--hash=sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e \
--hash=sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807 \
--hash=sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407 \
--hash=sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c \
--hash=sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12 \
--hash=sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3 \
--hash=sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089 \
--hash=sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd \
--hash=sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e \
--hash=sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00 \
--hash=sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616
# via requests
cryptography==46.0.7 \
--hash=sha256:04959522f938493042d595a736e7dbdff6eb6cc2339c11465b3ff89343b65f65 \
--hash=sha256:128c5edfe5e5938b86b03941e94fac9ee793a94452ad1365c9fc3f4f62216832 \
--hash=sha256:1d25aee46d0c6f1a501adcddb2d2fee4b979381346a78558ed13e50aa8a59067 \
--hash=sha256:24402210aa54baae71d99441d15bb5a1919c195398a87b563df84468160a65de \
--hash=sha256:258514877e15963bd43b558917bc9f54cf7cf866c38aa576ebf47a77ddbc43a4 \
--hash=sha256:35719dc79d4730d30f1c2b6474bd6acda36ae2dfae1e3c16f2051f215df33ce0 \
--hash=sha256:397655da831414d165029da9bc483bed2fe0e75dde6a1523ec2fe63f3c46046b \
--hash=sha256:3986ac1dee6def53797289999eabe84798ad7817f3e97779b5061a95b0ee4968 \
--hash=sha256:420b1e4109cc95f0e5700eed79908cef9268265c773d3a66f7af1eef53d409ef \
--hash=sha256:42a1e5f98abb6391717978baf9f90dc28a743b7d9be7f0751a6f56a75d14065b \
--hash=sha256:462ad5cb1c148a22b2e3bcc5ad52504dff325d17daf5df8d88c17dda1f75f2a4 \
--hash=sha256:506c4ff91eff4f82bdac7633318a526b1d1309fc07ca76a3ad182cb5b686d6d3 \
--hash=sha256:5ad9ef796328c5e3c4ceed237a183f5d41d21150f972455a9d926593a1dcb308 \
--hash=sha256:5d1c02a14ceb9148cc7816249f64f623fbfee39e8c03b3650d842ad3f34d637e \
--hash=sha256:5e51be372b26ef4ba3de3c167cd3d1022934bc838ae9eaad7e644986d2a3d163 \
--hash=sha256:60627cf07e0d9274338521205899337c5d18249db56865f943cbe753aa96f40f \
--hash=sha256:65814c60f8cc400c63131584e3e1fad01235edba2614b61fbfbfa954082db0ee \
--hash=sha256:73510b83623e080a2c35c62c15298096e2a5dc8d51c3b4e1740211839d0dea77 \
--hash=sha256:7bbc6ccf49d05ac8f7d7b5e2e2c33830d4fe2061def88210a126d130d7f71a85 \
--hash=sha256:80406c3065e2c55d7f49a9550fe0c49b3f12e5bfff5dedb727e319e1afb9bf99 \
--hash=sha256:84d4cced91f0f159a7ddacad249cc077e63195c36aac40b4150e7a57e84fffe7 \
--hash=sha256:8a469028a86f12eb7d2fe97162d0634026d92a21f3ae0ac87ed1c4a447886c83 \
--hash=sha256:91bbcb08347344f810cbe49065914fe048949648f6bd5c2519f34619142bbe85 \
--hash=sha256:935ce7e3cfdb53e3536119a542b839bb94ec1ad081013e9ab9b7cfd478b05006 \
--hash=sha256:9694078c5d44c157ef3162e3bf3946510b857df5a3955458381d1c7cfc143ddb \
--hash=sha256:a1529d614f44b863a7b480c6d000fe93b59acee9c82ffa027cfadc77521a9f5e \
--hash=sha256:abad9dac36cbf55de6eb49badd4016806b3165d396f64925bf2999bcb67837ba \
--hash=sha256:b36a4695e29fe69215d75960b22577197aca3f7a25b9cf9d165dcfe9d80bc325 \
--hash=sha256:b7b412817be92117ec5ed95f880defe9cf18a832e8cafacf0a22337dc1981b4d \
--hash=sha256:c5b1ccd1239f48b7151a65bc6dd54bcfcc15e028c8ac126d3fada09db0e07ef1 \
--hash=sha256:cbd5fb06b62bd0721e1170273d3f4d5a277044c47ca27ee257025146c34cbdd1 \
--hash=sha256:cdf1a610ef82abb396451862739e3fc93b071c844399e15b90726ef7470eeaf2 \
--hash=sha256:cdfbe22376065ffcf8be74dc9a909f032df19bc58a699456a21712d6e5eabfd0 \
--hash=sha256:d02c738dacda7dc2a74d1b2b3177042009d5cab7c7079db74afc19e56ca1b455 \
--hash=sha256:d151173275e1728cf7839aaa80c34fe550c04ddb27b34f48c232193df8db5842 \
--hash=sha256:d23c8ca48e44ee015cd0a54aeccdf9f09004eba9fc96f38c911011d9ff1bd457 \
--hash=sha256:d3b99c535a9de0adced13d159c5a9cf65c325601aa30f4be08afd680643e9c15 \
--hash=sha256:d5f7520159cd9c2154eb61eb67548ca05c5774d39e9c2c4339fd793fe7d097b2 \
--hash=sha256:db0f493b9181c7820c8134437eb8b0b4792085d37dbb24da050476ccb664e59c \
--hash=sha256:e06acf3c99be55aa3b516397fe42f5855597f430add9c17fa46bf2e0fb34c9bb \
--hash=sha256:ea42cbe97209df307fdc3b155f1b6fa2577c0defa8f1f7d3be7d31d189108ad4 \
--hash=sha256:ebd6daf519b9f189f85c479427bbd6e9c9037862cf8fe89ee35503bd209ed902 \
--hash=sha256:f247c8c1a1fb45e12586afbb436ef21ff1e80670b2861a90353d9b025583d246 \
--hash=sha256:fbfd0e5f273877695cb93baf14b185f4878128b250cc9f8e617ea0c025dfb022 \
--hash=sha256:fc9ab8856ae6cf7c9358430e49b368f3108f050031442eaeb6b9d87e4dcf4e4f \
--hash=sha256:fcd8eac50d9138c1d7fc53a653ba60a2bee81a505f9f8850b6b2888555a45d0e \
--hash=sha256:fdd1736fed309b4300346f88f74cd120c27c56852c3838cab416e7a166f67298 \
--hash=sha256:ffca7aa1d00cf7d6469b988c581598f2259e46215e0140af408966a24cf086ce
# via
# paramiko
# pyopenssl
# rfc3161-client
# sigstore
dnspython==2.7.0 \
--hash=sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86
# via email-validator
email-validator==2.2.0 \
--hash=sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631
# via pydantic
frozenlist==1.5.0 \
--hash=sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e \
--hash=sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf \
--hash=sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6 \
--hash=sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a \
--hash=sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d \
--hash=sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f \
--hash=sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28 \
--hash=sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b \
--hash=sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9 \
--hash=sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2 \
--hash=sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec \
--hash=sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2 \
--hash=sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c \
--hash=sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336 \
--hash=sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4 \
--hash=sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d \
--hash=sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b \
--hash=sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c \
--hash=sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10 \
--hash=sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08 \
--hash=sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942 \
--hash=sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8 \
--hash=sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f \
--hash=sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10 \
--hash=sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5 \
--hash=sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6 \
--hash=sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21 \
--hash=sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c \
--hash=sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d \
--hash=sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923 \
--hash=sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608 \
--hash=sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de \
--hash=sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17 \
--hash=sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0 \
--hash=sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f \
--hash=sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641 \
--hash=sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c \
--hash=sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a \
--hash=sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0 \
--hash=sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9 \
--hash=sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab \
--hash=sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f \
--hash=sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3 \
--hash=sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a \
--hash=sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784 \
--hash=sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604 \
--hash=sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d \
--hash=sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5 \
--hash=sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03 \
--hash=sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e \
--hash=sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953 \
--hash=sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee \
--hash=sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d \
--hash=sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3 \
--hash=sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039 \
--hash=sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f \
--hash=sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9 \
--hash=sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf \
--hash=sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76 \
--hash=sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba \
--hash=sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171 \
--hash=sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb \
--hash=sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439 \
--hash=sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631 \
--hash=sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972 \
--hash=sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d \
--hash=sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869 \
--hash=sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9 \
--hash=sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411 \
--hash=sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723 \
--hash=sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2 \
--hash=sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b \
--hash=sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99 \
--hash=sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e \
--hash=sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840 \
--hash=sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3 \
--hash=sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb \
--hash=sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3 \
--hash=sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0 \
--hash=sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca \
--hash=sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45 \
--hash=sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e \
--hash=sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f \
--hash=sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5 \
--hash=sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307 \
--hash=sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e \
--hash=sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2 \
--hash=sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778 \
--hash=sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a \
--hash=sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30 \
--hash=sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a
# via
# aiohttp
# aiosignal
graphemeu==0.7.2 \
--hash=sha256:1444520f6899fd30114fc2a39f297d86d10fa0f23bf7579f772f8bc7efaa2542
# via alive-progress
grpclib==0.4.8 \
--hash=sha256:a5047733a7acc1c1cee6abf3c841c7c6fab67d2844a45a853b113fa2e6cd2654
# via betterproto
h2==4.3.0 \
--hash=sha256:c438f029a25f7945c69e0ccf0fb951dc3f73a5f6412981daee861431b70e2bdd
# via grpclib
hpack==4.1.0 \
--hash=sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496
# via h2
hyperframe==6.1.0 \
--hash=sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5
# via h2
id==1.5.0 \
--hash=sha256:f1434e1cef91f2cbb8a4ec64663d5a23b9ed43ef44c4c957d02583d61714c658
# via sigstore
idna==3.10 \
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
# via
# email-validator
# requests
# yarl
invoke==2.2.0 \
--hash=sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820
# via paramiko
markdown-it-py==3.0.0 \
--hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1
# via rich
mdurl==0.1.2 \
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8
# via markdown-it-py
multidict==6.1.0 \
--hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \
--hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \
--hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \
--hash=sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3 \
--hash=sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b \
--hash=sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6 \
--hash=sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748 \
--hash=sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966 \
--hash=sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f \
--hash=sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1 \
--hash=sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6 \
--hash=sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada \
--hash=sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305 \
--hash=sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2 \
--hash=sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d \
--hash=sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef \
--hash=sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c \
--hash=sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb \
--hash=sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60 \
--hash=sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6 \
--hash=sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4 \
--hash=sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478 \
--hash=sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81 \
--hash=sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7 \
--hash=sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56 \
--hash=sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3 \
--hash=sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6 \
--hash=sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30 \
--hash=sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb \
--hash=sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506 \
--hash=sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0 \
--hash=sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925 \
--hash=sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c \
--hash=sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6 \
--hash=sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e \
--hash=sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95 \
--hash=sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2 \
--hash=sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133 \
--hash=sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2 \
--hash=sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa \
--hash=sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3 \
--hash=sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3 \
--hash=sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436 \
--hash=sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657 \
--hash=sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581 \
--hash=sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492 \
--hash=sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43 \
--hash=sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2 \
--hash=sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2 \
--hash=sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926 \
--hash=sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057 \
--hash=sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc \
--hash=sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80 \
--hash=sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255 \
--hash=sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1 \
--hash=sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972 \
--hash=sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53 \
--hash=sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1 \
--hash=sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423 \
--hash=sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a \
--hash=sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160 \
--hash=sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c \
--hash=sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd \
--hash=sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa \
--hash=sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5 \
--hash=sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b \
--hash=sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa \
--hash=sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef \
--hash=sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44 \
--hash=sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4 \
--hash=sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156 \
--hash=sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753 \
--hash=sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28 \
--hash=sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d \
--hash=sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a \
--hash=sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304 \
--hash=sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008 \
--hash=sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429 \
--hash=sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72 \
--hash=sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399 \
--hash=sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3 \
--hash=sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392 \
--hash=sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167 \
--hash=sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c \
--hash=sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774 \
--hash=sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351 \
--hash=sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76 \
--hash=sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875 \
--hash=sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd \
--hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 \
--hash=sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db
# via
# aiohttp
# grpclib
# yarl
paramiko==4.0.0 \
--hash=sha256:0e20e00ac666503bf0b4eda3b6d833465a2b7aff2e2b3d79a8bba5ef144ee3b9
# via -r requirements.in
platformdirs==4.3.6 \
--hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb
# via sigstore
propcache==0.2.1 \
--hash=sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4 \
--hash=sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4 \
--hash=sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a \
--hash=sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f \
--hash=sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9 \
--hash=sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d \
--hash=sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e \
--hash=sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6 \
--hash=sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf \
--hash=sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034 \
--hash=sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d \
--hash=sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16 \
--hash=sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30 \
--hash=sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba \
--hash=sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95 \
--hash=sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d \
--hash=sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae \
--hash=sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348 \
--hash=sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2 \
--hash=sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce \
--hash=sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54 \
--hash=sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629 \
--hash=sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54 \
--hash=sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1 \
--hash=sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b \
--hash=sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf \
--hash=sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b \
--hash=sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587 \
--hash=sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097 \
--hash=sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea \
--hash=sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24 \
--hash=sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7 \
--hash=sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541 \
--hash=sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6 \
--hash=sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634 \
--hash=sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3 \
--hash=sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d \
--hash=sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034 \
--hash=sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465 \
--hash=sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2 \
--hash=sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf \
--hash=sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1 \
--hash=sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04 \
--hash=sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5 \
--hash=sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583 \
--hash=sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb \
--hash=sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b \
--hash=sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c \
--hash=sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958 \
--hash=sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc \
--hash=sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4 \
--hash=sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82 \
--hash=sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e \
--hash=sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce \
--hash=sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9 \
--hash=sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518 \
--hash=sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536 \
--hash=sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505 \
--hash=sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052 \
--hash=sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff \
--hash=sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1 \
--hash=sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f \
--hash=sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681 \
--hash=sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347 \
--hash=sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af \
--hash=sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246 \
--hash=sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787 \
--hash=sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0 \
--hash=sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f \
--hash=sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439 \
--hash=sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3 \
--hash=sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6 \
--hash=sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca \
--hash=sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec \
--hash=sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d \
--hash=sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3 \
--hash=sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16 \
--hash=sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717 \
--hash=sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6 \
--hash=sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd \
--hash=sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212
# via
# aiohttp
# yarl
pyasn1==0.6.3 \
--hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde
# via sigstore
pycparser==2.22 \
--hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc
# via cffi
pydantic[email]==2.12.5 \
--hash=sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d
# via
# sigstore
# sigstore-rekor-types
pydantic-core==2.41.5 \
--hash=sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90 \
--hash=sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740 \
--hash=sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504 \
--hash=sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84 \
--hash=sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33 \
--hash=sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c \
--hash=sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0 \
--hash=sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0 \
--hash=sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a \
--hash=sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34 \
--hash=sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2 \
--hash=sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3 \
--hash=sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815 \
--hash=sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14 \
--hash=sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba \
--hash=sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375 \
--hash=sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf \
--hash=sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963 \
--hash=sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1 \
--hash=sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808 \
--hash=sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553 \
--hash=sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1 \
--hash=sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2 \
--hash=sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5 \
--hash=sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470 \
--hash=sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2 \
--hash=sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b \
--hash=sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660 \
--hash=sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c \
--hash=sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093 \
--hash=sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5 \
--hash=sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594 \
--hash=sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008 \
--hash=sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a \
--hash=sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a \
--hash=sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd \
--hash=sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284 \
--hash=sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586 \
--hash=sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869 \
--hash=sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294 \
--hash=sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f \
--hash=sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66 \
--hash=sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51 \
--hash=sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc \
--hash=sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97 \
--hash=sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a \
--hash=sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d \
--hash=sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9 \
--hash=sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c \
--hash=sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07 \
--hash=sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36 \
--hash=sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e \
--hash=sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05 \
--hash=sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e \
--hash=sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941 \
--hash=sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3 \
--hash=sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612 \
--hash=sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3 \
--hash=sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b \
--hash=sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe \
--hash=sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146 \
--hash=sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11 \
--hash=sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60 \
--hash=sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd \
--hash=sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b \
--hash=sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c \
--hash=sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a \
--hash=sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460 \
--hash=sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1 \
--hash=sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf \
--hash=sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf \
--hash=sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858 \
--hash=sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2 \
--hash=sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9 \
--hash=sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2 \
--hash=sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3 \
--hash=sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6 \
--hash=sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770 \
--hash=sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d \
--hash=sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc \
--hash=sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23 \
--hash=sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26 \
--hash=sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa \
--hash=sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8 \
--hash=sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d \
--hash=sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3 \
--hash=sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d \
--hash=sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034 \
--hash=sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9 \
--hash=sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1 \
--hash=sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56 \
--hash=sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b \
--hash=sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c \
--hash=sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a \
--hash=sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e \
--hash=sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9 \
--hash=sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5 \
--hash=sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a \
--hash=sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556 \
--hash=sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e \
--hash=sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49 \
--hash=sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2 \
--hash=sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9 \
--hash=sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b \
--hash=sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc \
--hash=sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb \
--hash=sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0 \
--hash=sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8 \
--hash=sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82 \
--hash=sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69 \
--hash=sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b \
--hash=sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c \
--hash=sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75 \
--hash=sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5 \
--hash=sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f \
--hash=sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad \
--hash=sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b \
--hash=sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7 \
--hash=sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425 \
--hash=sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52
# via pydantic
pygments==2.20.0 \
--hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176
# via rich
pyjwt==2.12.0 \
--hash=sha256:9bb459d1bdd0387967d287f5656bf7ec2b9a26645d1961628cda1764e087fd6e
# via sigstore
pynacl==1.6.2 \
--hash=sha256:04316d1fc625d860b6c162fff704eb8426b1a8bcd3abacea11142cbd99a6b574 \
--hash=sha256:22de65bb9010a725b0dac248f353bb072969c94fa8d6b1f34b87d7953cf7bbe4 \
--hash=sha256:26bfcd00dcf2cf160f122186af731ae30ab120c18e8375684ec2670dccd28130 \
--hash=sha256:2fef529ef3ee487ad8113d287a593fa26f48ee3620d92ecc6f1d09ea38e0709b \
--hash=sha256:320ef68a41c87547c91a8b58903c9caa641ab01e8512ce291085b5fe2fcb7590 \
--hash=sha256:3bffb6d0f6becacb6526f8f42adfb5efb26337056ee0831fb9a7044d1a964444 \
--hash=sha256:44081faff368d6c5553ccf55322ef2819abb40e25afaec7e740f159f74813634 \
--hash=sha256:46065496ab748469cdd999246d17e301b2c24ae2fdf739132e580a0e94c94a87 \
--hash=sha256:5811c72b473b2f38f7e2a3dc4f8642e3a3e9b5e7317266e4ced1fba85cae41aa \
--hash=sha256:622d7b07cc5c02c666795792931b50c91f3ce3c2649762efb1ef0d5684c81594 \
--hash=sha256:62985f233210dee6548c223301b6c25440852e13d59a8b81490203c3227c5ba0 \
--hash=sha256:68be3a09455743ff9505491220b64440ced8973fe930f270c8e07ccfa25b1f9e \
--hash=sha256:834a43af110f743a754448463e8fd61259cd4ab5bbedcf70f9dabad1d28a394c \
--hash=sha256:8845c0631c0be43abdd865511c41eab235e0be69c81dc66a50911594198679b0 \
--hash=sha256:8a66d6fb6ae7661c58995f9c6435bda2b1e68b54b598a6a10247bfcdadac996c \
--hash=sha256:8b097553b380236d51ed11356c953bf8ce36a29a3e596e934ecabe76c985a577 \
--hash=sha256:a84bf1c20339d06dc0c85d9aea9637a24f718f375d861b2668b2f9f96fa51145 \
--hash=sha256:a9f9932d8d2811ce1a8ffa79dcbdf3970e7355b5c8eb0c1a881a57e7f7d96e88 \
--hash=sha256:bc4a36b28dd72fb4845e5d8f9760610588a96d5a51f01d84d8c6ff9849968c14 \
--hash=sha256:c8a231e36ec2cab018c4ad4358c386e36eede0319a0c41fed24f840b1dac59f6 \
--hash=sha256:c949ea47e4206af7c8f604b8278093b674f7c79ed0d4719cc836902bf4517465 \
--hash=sha256:d071c6a9a4c94d79eb665db4ce5cedc537faf74f2355e4d502591d850d3913c0 \
--hash=sha256:d29bfe37e20e015a7d8b23cfc8bd6aa7909c92a1b8f41ee416bbb3e79ef182b2 \
--hash=sha256:fe9847ca47d287af41e82be1dd5e23023d3c31a951da134121ab02e42ac218c9
# via paramiko
pyopenssl==26.0.0 \
--hash=sha256:df94d28498848b98cc1c0ffb8ef1e71e40210d3b0a8064c9d29571ed2904bf81
# via sigstore
python-dateutil==2.9.0.post0 \
--hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427
# via betterproto
python-gnupg==0.5.6 \
--hash=sha256:b5050a55663d8ab9fcc8d97556d229af337a87a3ebebd7054cbd8b7e2043394a
# via -r requirements.in
requests==2.33.0 \
--hash=sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b
# via
# id
# sigstore
rfc3161-client==1.0.6 \
--hash=sha256:0b3920334f7334ec3bb9c319d53a5d08cd43b6883f75e2669cfd869cd264d53a \
--hash=sha256:1671b1be16480ea54c0d36239efd0fb62c13dd572a9865a5e91fea39f1b95303 \
--hash=sha256:1be4e1133f0f7fe875629f2c358285503c1cfc79cebfbc3fb4e28b8a57d6f1a4 \
--hash=sha256:2bc9835467f6166edd6f876470484e5b294ee141add6eff6a59f5047937aaa75 \
--hash=sha256:3da328ba08139846b1ab3a03402ba8a5f3659a640dbe2cd6a18f7f342e99ba98 \
--hash=sha256:4ef4b096abe7d55b020526e39932c2721939a6c55e9a5cd3b3e77897a0942937 \
--hash=sha256:63355099d932851eac507806bb9d0937dab546a66d5857d888168799ec635f6d \
--hash=sha256:78cdc6bde331492cb94f69328831d5c56b271012b00c6f1784c2e4b33837d585 \
--hash=sha256:8102165201c5224cf6e6634bfd68c6a39e8f800601188216f8210face4861215 \
--hash=sha256:85a1d71d1eb2c9bced2b3eb75e96f9fe49732ec2567b5dafa1dd889fff42b7fe \
--hash=sha256:8631f7db7c1327bf87ee6a9a8681b4cd6bc2a90aae651388f29d045cd9ff1ac9 \
--hash=sha256:940e1fc95ec0ca734927a82bcb5363fa988ef1a085d238ff0c861f29c0cfb746 \
--hash=sha256:9a98e9c7ff632d9571fcea25fb70bde0e8339b86368aef67a65f6a301f125733 \
--hash=sha256:b7ad54288a49379b01b1d0d9d15167d2b7c6c7f940332ab85eeb4a6e844da8c7 \
--hash=sha256:bc379167238df32cbcc1dc9c324088559c1734331030f5293d75f4fd37b5f4f6 \
--hash=sha256:bed6ef8e194cab85f6ec5678995b6406bb568383ebb6a4301be40e7939dd28d9 \
--hash=sha256:e16ed34f6f33fd62aa3b1f83615ecf2f96e1b1f57df4e1a36570b3f895333972 \
--hash=sha256:e3caffaebf43242b000c4a6659d60eaf19c3b161ccbe05b15634a856c9ea7e61
# via sigstore
rfc8785==0.1.4 \
--hash=sha256:520d690b448ecf0703691c76e1a34a24ddcd4fc5bc41d589cb7c58ec651bcd48
# via sigstore
rich==13.9.4 \
--hash=sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90
# via sigstore
securesystemslib==1.2.0 \
--hash=sha256:fa63abcb1cf4dba4f2df964f623baa45bc39029980d7a0a2119d90731942afc6
# via tuf
sigstore==3.6.7 \
--hash=sha256:85d7512499eded0ffc310462d8be81731a631320751e390d74370d6458864df9
# via -r requirements.in
sigstore-protobuf-specs==0.3.2 \
--hash=sha256:50c99fa6747a3a9c5c562a43602cf76df0b199af28f0e9d4319b6775630425ea
# via sigstore
sigstore-rekor-types==0.0.18 \
--hash=sha256:b62bf38c5b1a62bc0d7fe0ee51a0709e49311d137c7880c329882a8f4b2d1d78
# via sigstore
six==1.17.0 \
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274
# via python-dateutil
tuf==6.0.0 \
--hash=sha256:458f663a233d95cc76dde0e1a3d01796516a05ce2781fefafebe037f7729601a
# via sigstore
typing-extensions==4.15.0 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via
# aiosignal
# pydantic
# pydantic-core
# pyopenssl
# typing-inspection
typing-inspection==0.4.2 \
--hash=sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7
# via pydantic
urllib3==2.6.3 \
--hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4
# via
# requests
# tuf
yarl==1.18.3 \
--hash=sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba \
--hash=sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193 \
--hash=sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318 \
--hash=sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee \
--hash=sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e \
--hash=sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1 \
--hash=sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a \
--hash=sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186 \
--hash=sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1 \
--hash=sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50 \
--hash=sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640 \
--hash=sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb \
--hash=sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8 \
--hash=sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc \
--hash=sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5 \
--hash=sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58 \
--hash=sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2 \
--hash=sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393 \
--hash=sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24 \
--hash=sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b \
--hash=sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910 \
--hash=sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c \
--hash=sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272 \
--hash=sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed \
--hash=sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1 \
--hash=sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04 \
--hash=sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d \
--hash=sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5 \
--hash=sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d \
--hash=sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889 \
--hash=sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae \
--hash=sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b \
--hash=sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c \
--hash=sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576 \
--hash=sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34 \
--hash=sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477 \
--hash=sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990 \
--hash=sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2 \
--hash=sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512 \
--hash=sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069 \
--hash=sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a \
--hash=sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6 \
--hash=sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0 \
--hash=sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8 \
--hash=sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb \
--hash=sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa \
--hash=sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8 \
--hash=sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e \
--hash=sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e \
--hash=sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985 \
--hash=sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8 \
--hash=sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5 \
--hash=sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690 \
--hash=sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10 \
--hash=sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789 \
--hash=sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b \
--hash=sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca \
--hash=sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e \
--hash=sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5 \
--hash=sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59 \
--hash=sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9 \
--hash=sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8 \
--hash=sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db \
--hash=sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde \
--hash=sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7 \
--hash=sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb \
--hash=sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3 \
--hash=sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6 \
--hash=sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285 \
--hash=sha256:d0e883008013c
gitextract_8g54ntzm/
├── .coveragerc
├── .github/
│ ├── dependabot.yml
│ └── workflows/
│ ├── build-release.yml
│ ├── lint.yml
│ └── test.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .ruff.toml
├── LICENSE.txt
├── README.md
├── add_to_pydotorg.py
├── buildbotapi.py
├── dev-requirements.in
├── dev-requirements.txt
├── mypy-requirements.txt
├── pyproject.toml
├── release.py
├── requirements.in
├── requirements.txt
├── run_release.py
├── sbom.py
├── select_jobs.py
├── tests/
│ ├── README.rst
│ ├── __init__.py
│ ├── buildbotapi/
│ │ ├── builders.json
│ │ ├── failure.json
│ │ ├── no-builds.json
│ │ └── success.json
│ ├── fake-artifact.txt
│ ├── fake-ftp-files.txt
│ ├── magicdata/
│ │ ├── Include/
│ │ │ └── internal/
│ │ │ └── pycore_magic_number.h
│ │ └── Lib/
│ │ └── test/
│ │ └── test_importlib/
│ │ └── test_util.py
│ ├── patchlevel.h
│ ├── sbom/
│ │ ├── sbom-with-pip-removed.json
│ │ └── sbom-with-pip.json
│ ├── test_add_to_pydotorg.py
│ ├── test_buildbotapi.py
│ ├── test_release.py
│ ├── test_release_tag.py
│ ├── test_run_release.py
│ ├── test_sbom.py
│ ├── test_select_jobs.py
│ ├── test_update_version_next.py
│ └── whatsnew_index.rst
├── tox.ini
├── update_version_next.py
└── windows-release/
├── README.md
├── acquire-vcruntime.yml
├── azure-pipelines.yml
├── build-steps-pgo.yml
├── build-steps.yml
├── checkout.yml
├── find-sdk.yml
├── find-tools.yml
├── layout-command.yml
├── libffi-build.yml
├── merge-and-upload.py
├── msi-steps.yml
├── openssl-build.yml
├── purge.py
├── sign-files.yml
├── stage-build.yml
├── stage-layout-embed.yml
├── stage-layout-full.yml
├── stage-layout-msix.yml
├── stage-layout-nuget.yml
├── stage-layout-pymanager.yml
├── stage-layout-symbols.yml
├── stage-msi.yml
├── stage-pack-msix.yml
├── stage-pack-nuget.yml
├── stage-pack-pymanager.yml
├── stage-publish-nugetorg.yml
├── stage-publish-pymanager.yml
├── stage-publish-pythonorg.yml
├── stage-sign.yml
├── stage-test-embed.yml
├── stage-test-msi.yml
├── stage-test-nuget.yml
├── stage-test-pymanager.yml
├── start-arm64vm.yml
├── tcltk-build.yml
└── uploadrelease.ps1
SYMBOL INDEX (263 symbols across 17 files)
FILE: add_to_pydotorg.py
function error (line 40) | def error(*msgs: Any) -> NoReturn:
function run_cmd (line 48) | def run_cmd(
function macos_description (line 95) | def macos_description(version: tuple[int, int, int]) -> str:
function get_file_descriptions (line 102) | def get_file_descriptions(
function slug_for (line 167) | def slug_for(release: str) -> str:
function sigfile_for (line 175) | def sigfile_for(release: str, rfile: str) -> str:
function sha256sum_for (line 179) | def sha256sum_for(filename: str) -> str:
function filesize_for (line 184) | def filesize_for(filename: str) -> int:
function make_slug (line 188) | def make_slug(text: str) -> str:
function base_version (line 192) | def base_version(release: str) -> str:
function base_version_tuple (line 198) | def base_version_tuple(release: str) -> tuple[int, int, int]:
function minor_version (line 204) | def minor_version(release: str) -> str:
function minor_version_tuple (line 210) | def minor_version_tuple(release: str) -> tuple[int, int]:
function build_file_dict (line 216) | def build_file_dict(
function list_files (line 265) | def list_files(
function query_object (line 296) | def query_object(base_url: str, objtype: str, **params: Any) -> int:
function post_object (line 307) | def post_object(base_url: str, objtype: str, datadict: dict[str, Any]) -...
function sign_release_files_with_sigstore (line 328) | def sign_release_files_with_sigstore(
function parse_args (line 423) | def parse_args() -> argparse.Namespace:
function main (line 451) | def main() -> None:
FILE: buildbotapi.py
class Builder (line 11) | class Builder:
method __init__ (line 17) | def __init__(self, **kwargs: Any) -> None:
method __hash__ (line 20) | def __hash__(self) -> int:
class BuildBotAPI (line 24) | class BuildBotAPI:
method __init__ (line 25) | def __init__(self, session: ClientSession) -> None:
method authenticate (line 28) | async def authenticate(self, token: str) -> None:
method _fetch_text (line 33) | async def _fetch_text(self, url: str) -> str:
method _fetch_json (line 37) | async def _fetch_json(self, url: str) -> JSON:
method stable_builders (line 40) | async def stable_builders(self, branch: str | None = None) -> dict[int...
method all_builders (line 48) | async def all_builders(self, branch: str | None = None) -> dict[int, B...
method is_builder_failing_currently (line 59) | async def is_builder_failing_currently(self, builder: Builder) -> bool:
FILE: release.py
class ReleaseShelf (line 43) | class ReleaseShelf(Protocol):
method close (line 44) | def close(self) -> None: ...
method get (line 47) | def get(self, key: Literal["finished"], default: bool | None = None) -...
method get (line 50) | def get(
method get (line 55) | def get(self, key: Literal["gpg_key"], default: str | None = None) -> ...
method get (line 58) | def get(self, key: Literal["git_repo"], default: Path | None = None) -...
method get (line 61) | def get(self, key: Literal["auth_info"], default: str | None = None) -...
method get (line 64) | def get(self, key: Literal["ssh_user"], default: str | None = None) ->...
method get (line 67) | def get(
method get (line 72) | def get(self, key: Literal["sign_gpg"], default: bool | None = None) -...
method get (line 75) | def get(
method get (line 80) | def get(self, key: Literal["release"], default: Tag | None = None) -> ...
method __getitem__ (line 83) | def __getitem__(self, key: Literal["finished"]) -> bool: ...
method __getitem__ (line 86) | def __getitem__(self, key: Literal["completed_tasks"]) -> list[Task]: ...
method __getitem__ (line 89) | def __getitem__(self, key: Literal["gpg_key"]) -> str: ...
method __getitem__ (line 92) | def __getitem__(self, key: Literal["git_repo"]) -> Path: ...
method __getitem__ (line 95) | def __getitem__(self, key: Literal["auth_info"]) -> str: ...
method __getitem__ (line 98) | def __getitem__(self, key: Literal["ssh_user"]) -> str: ...
method __getitem__ (line 101) | def __getitem__(self, key: Literal["ssh_key"]) -> str | None: ...
method __getitem__ (line 104) | def __getitem__(self, key: Literal["sign_gpg"]) -> bool: ...
method __getitem__ (line 107) | def __getitem__(self, key: Literal["security_release"]) -> bool: ...
method __getitem__ (line 110) | def __getitem__(self, key: Literal["release"]) -> Tag: ...
method __setitem__ (line 113) | def __setitem__(self, key: Literal["finished"], value: bool) -> None: ...
method __setitem__ (line 116) | def __setitem__(
method __setitem__ (line 121) | def __setitem__(self, key: Literal["gpg_key"], value: str) -> None: ...
method __setitem__ (line 124) | def __setitem__(self, key: Literal["git_repo"], value: Path) -> None: ...
method __setitem__ (line 127) | def __setitem__(self, key: Literal["auth_info"], value: str) -> None: ...
method __setitem__ (line 130) | def __setitem__(self, key: Literal["ssh_user"], value: str) -> None: ...
method __setitem__ (line 133) | def __setitem__(self, key: Literal["ssh_key"], value: str | None) -> N...
method __setitem__ (line 136) | def __setitem__(self, key: Literal["sign_gpg"], value: bool) -> None: ...
method __setitem__ (line 139) | def __setitem__(self, key: Literal["security_release"], value: bool) -...
method __setitem__ (line 142) | def __setitem__(self, key: Literal["release"], value: Tag) -> None: ...
class Task (line 146) | class Task:
method __call__ (line 150) | def __call__(self, db: ReleaseShelf) -> Any:
class Tag (line 154) | class Tag:
method __init__ (line 155) | def __init__(self, tag_name: str) -> None:
method __str__ (line 188) | def __str__(self) -> str:
method normalized (line 191) | def normalized(self) -> str:
method branch (line 195) | def branch(self) -> str:
method is_alpha_release (line 201) | def is_alpha_release(self) -> bool:
method is_release_candidate (line 205) | def is_release_candidate(self) -> bool:
method is_feature_freeze_release (line 209) | def is_feature_freeze_release(self) -> bool:
method is_security_release (line 213) | def is_security_release(self) -> bool:
method nickname (line 220) | def nickname(self) -> str:
method gitname (line 224) | def gitname(self) -> str:
method long_name (line 228) | def long_name(self) -> str:
method next_minor_release (line 239) | def next_minor_release(self) -> Self:
method as_tuple (line 242) | def as_tuple(self) -> tuple[int, int, int, str, int]:
method committed_at (line 247) | def committed_at(self) -> datetime.datetime:
method includes_docs (line 259) | def includes_docs(self) -> bool:
method doc_version (line 264) | def doc_version(self) -> str:
function error (line 274) | def error(*msgs: str) -> None:
function run_cmd (line 281) | def run_cmd(
function ask_question (line 297) | def ask_question(question: str) -> bool:
function chdir_to_repo_root (line 314) | def chdir_to_repo_root() -> str:
function get_output (line 357) | def get_output(args: list[str]) -> bytes:
function check_env (line 361) | def check_env() -> None:
function get_arg_parser (line 368) | def get_arg_parser() -> optparse.OptionParser:
function constant_replace (line 421) | def constant_replace(
function tweak_patchlevel (line 453) | def tweak_patchlevel(
function get_pep_number (line 483) | def get_pep_number(version: str) -> str:
function tweak_readme (line 498) | def tweak_readme(tag: Tag, filename: str = "README.rst") -> None:
function bump (line 543) | def bump(tag: Tag) -> None:
function manual_edit (line 577) | def manual_edit(filename: str) -> None:
function pushd (line 583) | def pushd(new: str) -> Generator[None, None, None]:
function make_dist (line 593) | def make_dist(name: str) -> None:
function tarball (line 605) | def tarball(source: str, clamp_mtime: str) -> None:
function export (line 653) | def export(tag: Tag, silent: bool = False, skip_docs: bool = False) -> N...
function build_docs (line 760) | def build_docs() -> str:
function upload (line 783) | def upload(tag: Tag, username: str) -> None:
function make_tag (line 801) | def make_tag(tag: Tag, *, sign_gpg: bool = True) -> bool:
function done (line 844) | def done(tag: Tag) -> None:
function main (line 848) | def main(argv: Any) -> None:
FILE: run_release.py
class ReleaseException (line 210) | class ReleaseException(Exception):
class ReleaseDriver (line 214) | class ReleaseDriver:
method __init__ (line 215) | def __init__(
method checkpoint (line 267) | def checkpoint(self) -> None:
method run (line 270) | def run(self) -> None:
function cd (line 291) | def cd(path: Path) -> Iterator[None]:
function check_tool (line 298) | def check_tool(db: ReleaseShelf, tool: str) -> None:
function check_gpg_keys (line 311) | def check_gpg_keys(db: ReleaseShelf) -> None:
function check_ssh_connection (line 332) | def check_ssh_connection(db: ReleaseShelf) -> None:
function check_sigstore_client (line 346) | def check_sigstore_client(db: ReleaseShelf) -> None:
function check_sigstore_version (line 358) | def check_sigstore_version(version: str) -> None:
function check_buildbots (line 372) | def check_buildbots(db: ReleaseShelf) -> None:
function check_docker_running (line 415) | def check_docker_running(db: ReleaseShelf) -> None:
function run_blurb_release (line 419) | def run_blurb_release(db: ReleaseShelf) -> None:
function check_cpython_repo_branch (line 427) | def check_cpython_repo_branch(db: ReleaseShelf) -> None:
function check_cpython_repo_age (line 439) | def check_cpython_repo_age(db: ReleaseShelf) -> None:
function check_cpython_repo_is_clean (line 457) | def check_cpython_repo_is_clean(db: ReleaseShelf) -> None:
function check_magic_number (line 462) | def check_magic_number(db: ReleaseShelf) -> None:
function prepare_temporary_branch (line 505) | def prepare_temporary_branch(db: ReleaseShelf) -> None:
function remove_temporary_branch (line 511) | def remove_temporary_branch(db: ReleaseShelf) -> None:
function prepare_pydoc_topics (line 517) | def prepare_pydoc_topics(db: ReleaseShelf) -> None:
function run_autoconf (line 534) | def run_autoconf(db: ReleaseShelf) -> None:
function check_pyspecific (line 567) | def check_pyspecific(db: ReleaseShelf) -> None:
function bump_version (line 586) | def bump_version(db: ReleaseShelf) -> None:
function bump_version_in_docs (line 594) | def bump_version_in_docs(db: ReleaseShelf) -> None:
function create_tag (line 601) | def create_tag(db: ReleaseShelf) -> None:
function wait_for_build_release (line 610) | def wait_for_build_release(db: ReleaseShelf) -> None:
function check_doc_unreleased_version (line 660) | def check_doc_unreleased_version(db: ReleaseShelf) -> None:
function sign_source_artifacts (line 682) | def sign_source_artifacts(db: ReleaseShelf) -> None:
function build_sbom_artifacts (line 721) | def build_sbom_artifacts(db: ReleaseShelf) -> None:
class MySFTPClient (line 743) | class MySFTPClient(paramiko.SFTPClient):
method put_dir (line 744) | def put_dir(
method mkdir (line 760) | def mkdir(
function upload_files_to_server (line 772) | def upload_files_to_server(db: ReleaseShelf, server: str) -> None:
function upload_files_to_downloads_server (line 813) | def upload_files_to_downloads_server(db: ReleaseShelf) -> None:
function place_files_in_download_folder (line 817) | def place_files_in_download_folder(db: ReleaseShelf) -> None:
function upload_docs_to_the_docs_server (line 858) | def upload_docs_to_the_docs_server(db: ReleaseShelf) -> None:
function unpack_docs_in_the_docs_server (line 866) | def unpack_docs_in_the_docs_server(db: ReleaseShelf) -> None:
function extract_github_owner (line 902) | def extract_github_owner(url: str) -> str:
function get_commit_sha (line 914) | def get_commit_sha(git_version: str, git_repo: Path) -> str:
function get_origin_remote_url (line 927) | def get_origin_remote_url(git_repo: Path) -> str:
function start_build_release (line 940) | def start_build_release(db: ReleaseShelf) -> None:
function send_email_to_platform_release_managers (line 978) | def send_email_to_platform_release_managers(db: ReleaseShelf) -> None:
function create_release_object_in_db (line 998) | def create_release_object_in_db(db: ReleaseShelf) -> None:
function wait_until_all_files_are_in_folder (line 1006) | def wait_until_all_files_are_in_folder(db: ReleaseShelf) -> None:
function run_add_to_python_dot_org (line 1057) | def run_add_to_python_dot_org(db: ReleaseShelf) -> None:
function purge_the_cdn (line 1095) | def purge_the_cdn(db: ReleaseShelf) -> None:
function announce_release (line 1134) | def announce_release(db: ReleaseShelf) -> None:
function post_release_merge (line 1143) | def post_release_merge(db: ReleaseShelf) -> None:
function post_release_tagging (line 1167) | def post_release_tagging(db: ReleaseShelf) -> None:
function maybe_prepare_new_main_branch (line 1194) | def maybe_prepare_new_main_branch(db: ReleaseShelf) -> None:
function update_whatsnew_toctree (line 1235) | def update_whatsnew_toctree(db: ReleaseShelf, filename: str) -> None:
function branch_new_versions (line 1248) | def branch_new_versions(db: ReleaseShelf) -> None:
function is_mirror (line 1262) | def is_mirror(repo: Path, remote: str) -> bool:
function push_to_local_fork (line 1273) | def push_to_local_fork(db: ReleaseShelf) -> None:
function push_to_upstream (line 1297) | def push_to_upstream(db: ReleaseShelf) -> None:
function main (line 1339) | def main() -> None:
FILE: sbom.py
class SBOM (line 33) | class SBOM(TypedDict):
class Package (line 45) | class Package(TypedDict):
class File (line 61) | class File(TypedDict):
class Relationship (line 67) | class Relationship(TypedDict):
class Checksum (line 73) | class Checksum(TypedDict):
class PackageVerificationCode (line 78) | class PackageVerificationCode(TypedDict):
class Ref (line 82) | class Ref(TypedDict):
class CreationInfo (line 88) | class CreationInfo(TypedDict):
function spdx_id (line 100) | def spdx_id(value: LiteralString) -> str:
function calculate_package_verification_codes (line 115) | def calculate_package_verification_codes(sbom: SBOM) -> None:
function get_release_tools_commit_sha (line 188) | def get_release_tools_commit_sha() -> str:
function normalize_sbom_data (line 202) | def normalize_sbom_data(sbom_data: SBOM) -> None:
function check_sbom_data (line 226) | def check_sbom_data(sbom_data: SBOM) -> None:
function fetch_package_metadata_from_pypi (line 258) | def fetch_package_metadata_from_pypi(
function remove_pip_from_sbom (line 294) | def remove_pip_from_sbom(sbom_data: SBOM) -> None:
function create_pip_sbom_from_wheel (line 324) | def create_pip_sbom_from_wheel(
function create_cpython_sbom (line 450) | def create_cpython_sbom(
function create_sbom_for_source_tarball (line 531) | def create_sbom_for_source_tarball(tarball_path: str) -> SBOM:
function create_sbom_for_windows_artifact (line 695) | def create_sbom_for_windows_artifact(
function main (line 774) | def main() -> None:
FILE: select_jobs.py
function output (line 8) | def output(key: str, value: bool) -> None:
function main (line 12) | def main() -> None:
FILE: tests/magicdata/Lib/test/test_importlib/test_util.py
class SomeClass (line 4) | class SomeClass:
method some_method (line 5) | def some_method(self) -> None:
FILE: tests/test_add_to_pydotorg.py
function test_slug_for (line 21) | def test_slug_for(release: str, expected: str) -> None:
function test_sigfile_for (line 25) | def test_sigfile_for() -> None:
function test_make_slug (line 42) | def test_make_slug(text: str, expected: str) -> None:
function test_build_file_dict (line 46) | def test_build_file_dict(tmp_path: Path) -> None:
function test_base_version (line 89) | def test_base_version(release: str, expected: str) -> None:
function test_base_version_tuple (line 102) | def test_base_version_tuple(release: str, expected: tuple[int, int, int]...
function test_minor_version (line 115) | def test_minor_version(release: str, expected: str) -> None:
function test_minor_version_tuple (line 128) | def test_minor_version_tuple(release: str, expected: tuple[int, int]) ->...
function test_macos_description (line 139) | def test_macos_description(release: tuple[int, int, int], expected: str)...
function test_list_files (line 143) | def test_list_files(fs: FakeFilesystem) -> None:
FILE: tests/test_buildbotapi.py
function test_builder_class (line 10) | def test_builder_class() -> None:
function load (line 28) | def load(filename: str) -> str:
function test_buildbotapi_authenticate (line 34) | async def test_buildbotapi_authenticate() -> None:
function test_buildbotapi_all_builders (line 49) | async def test_buildbotapi_all_builders() -> None:
function test_buildbotapi_all_builders_with_branch (line 71) | async def test_buildbotapi_all_builders_with_branch() -> None:
function test_buildbotapi_stable_builders (line 90) | async def test_buildbotapi_stable_builders() -> None:
function test_buildbotapi_is_builder_failing_currently_yes (line 120) | async def test_buildbotapi_is_builder_failing_currently_yes(
FILE: tests/test_release.py
function test_manual_edit (line 17) | def test_manual_edit(
function test_task (line 34) | def test_task(mocker: MockerFixture) -> None:
function test_ask_question (line 60) | def test_ask_question(
function test_tweak_patchlevel (line 81) | def test_tweak_patchlevel(tmp_path: Path) -> None:
function test_tweak_readme (line 149) | def test_tweak_readme(
FILE: tests/test_release_tag.py
function test_tag (line 10) | def test_tag() -> None:
function test_tag_phase (line 31) | def test_tag_phase() -> None:
function test_tag_committed_at_not_found (line 71) | def test_tag_committed_at_not_found() -> None:
function test_tag_committed (line 80) | def test_tag_committed(mocker: MockerFixture) -> None:
function test_tag_dot (line 92) | def test_tag_dot(mocker: MockerFixture) -> None:
function test_tag_invalid (line 104) | def test_tag_invalid() -> None:
function test_tag_docs_attributes (line 113) | def test_tag_docs_attributes() -> None:
function test_tag_long_name (line 135) | def test_tag_long_name() -> None:
function test_tag_is_security_release (line 158) | def test_tag_is_security_release(
FILE: tests/test_run_release.py
function test_check_sigstore_version_success (line 20) | def test_check_sigstore_version_success(version) -> None:
function test_check_sigstore_version_exception (line 29) | def test_check_sigstore_version_exception(version) -> None:
function test_extract_github_owner (line 44) | def test_extract_github_owner(url: str, expected: str) -> None:
function test_invalid_extract_github_owner (line 48) | def test_invalid_extract_github_owner() -> None:
function test_check_cpython_repo_branch (line 91) | def test_check_cpython_repo_branch(
function test_check_cpython_repo_age (line 118) | def test_check_cpython_repo_age(
function test_check_magic_number (line 144) | def test_check_magic_number() -> None:
function prepare_fake_docs (line 153) | def prepare_fake_docs(tmp_path: Path, content: str) -> None:
function fake_answers (line 164) | def fake_answers(monkeypatch: pytest.MonkeyPatch, answers: list[str]) ->...
function test_check_doc_unreleased_version_no_file (line 179) | def test_check_doc_unreleased_version_no_file(tmp_path: Path) -> None:
function test_check_doc_unreleased_version_no_file_alpha (line 189) | def test_check_doc_unreleased_version_no_file_alpha(tmp_path: Path) -> N...
function test_check_doc_unreleased_version_ok (line 198) | def test_check_doc_unreleased_version_ok(tmp_path: Path) -> None:
function test_check_doc_unreleased_version_not_ok (line 210) | def test_check_doc_unreleased_version_not_ok(monkeypatch, tmp_path: Path...
function test_check_doc_unreleased_version_waived (line 223) | def test_check_doc_unreleased_version_waived(monkeypatch, tmp_path: Path...
function test_update_whatsnew_toctree (line 236) | def test_update_whatsnew_toctree(tmp_path: Path) -> None:
FILE: tests/test_sbom.py
function test_spdx_id (line 24) | def test_spdx_id(value: str, expected: str) -> None:
function test_spdx_id_collisions (line 30) | def test_spdx_id_collisions():
function test_calculate_package_verification_code (line 56) | def test_calculate_package_verification_code(package_sha1s, package_veri...
function test_normalization (line 86) | def test_normalization():
function test_fetch_project_metadata_from_pypi (line 102) | def test_fetch_project_metadata_from_pypi(mocker):
function test_remove_pip_from_sbom (line 162) | def test_remove_pip_from_sbom() -> None:
function test_create_cpython_sbom (line 176) | def test_create_cpython_sbom():
function test_create_cpython_sbom_pre_release_download_location (line 242) | def test_create_cpython_sbom_pre_release_download_location(
FILE: tests/test_select_jobs.py
function test_select_jobs (line 24) | def test_select_jobs(
function test_select_jobs_test_mode (line 52) | def test_select_jobs_test_mode(
FILE: tests/test_update_version_next.py
function test_freeze_simple_script (line 61) | def test_freeze_simple_script(tmp_path: Path) -> None:
FILE: update_version_next.py
function main (line 56) | def main(argv: list[str]) -> None:
FILE: windows-release/merge-and-upload.py
function find_cmd (line 26) | def find_cmd(env, exe):
function _std_args (line 52) | def _std_args(cmd):
class RunError (line 66) | class RunError(Exception):
function _run (line 70) | def _run(*args, single_cmd=False):
function call_ssh (line 88) | def call_ssh(*args, allow_fail=True):
function upload_ssh (line 100) | def upload_ssh(source, dest):
function download_ssh (line 108) | def download_ssh(source, dest):
function ls_ssh (line 116) | def ls_ssh(dest):
function url2path (line 128) | def url2path(url):
function get_hashes (line 140) | def get_hashes(src):
function trim_install (line 150) | def trim_install(install):
function validate_new_installs (line 156) | def validate_new_installs(installs):
function purge (line 165) | def purge(url):
function calculate_uploads (line 174) | def calculate_uploads():
function sign_json (line 205) | def sign_json(cat_file, *files):
function remove_and_insert (line 242) | def remove_and_insert(index, new_installs):
function hash_packages (line 259) | def hash_packages(uploads):
function number_sortkey (line 264) | def number_sortkey(n):
function install_sortkey (line 271) | def install_sortkey(install):
function find_missing_from_index (line 280) | def find_missing_from_index(url, installs):
Condensed preview — 83 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (536K chars).
[
{
"path": ".coveragerc",
"chars": 231,
"preview": "# .coveragerc to control coverage.py\n\n[report]\n# Regexes for lines to exclude from consideration\nexclude_also =\n # Do"
},
{
"path": ".github/dependabot.yml",
"chars": 430,
"preview": "version: 2\nupdates:\n - package-ecosystem: \"github-actions\"\n directory: \"/\"\n schedule:\n interval: monthly\n "
},
{
"path": ".github/workflows/build-release.yml",
"chars": 10102,
"preview": "on:\n push:\n paths-ignore:\n - \".github/dependabot.yml\"\n - \".github/workflows/lint.yml\"\n - \".github/wor"
},
{
"path": ".github/workflows/lint.yml",
"chars": 901,
"preview": "name: Lint\n\non: [push, pull_request, workflow_dispatch]\n\npermissions: {}\n\nenv:\n FORCE_COLOR: 1\n RUFF_OUTPUT_FORMAT: gi"
},
{
"path": ".github/workflows/test.yml",
"chars": 942,
"preview": "name: Test\n\non: [push, pull_request, workflow_dispatch]\n\npermissions: {}\n\nenv:\n FORCE_COLOR: 1\n\njobs:\n tests:\n name"
},
{
"path": ".gitignore",
"chars": 2039,
"preview": "#\n.idea/\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution "
},
{
"path": ".pre-commit-config.yaml",
"chars": 1452,
"preview": "repos:\n - repo: https://github.com/astral-sh/ruff-pre-commit\n rev: v0.14.10\n hooks:\n - id: ruff-check\n "
},
{
"path": ".ruff.toml",
"chars": 590,
"preview": "fix = true\n\n[lint]\nselect = [\n \"C4\", # flake8-comprehensions\n \"E\", # pycodestyle errors\n \"F\", # pyflake"
},
{
"path": "LICENSE.txt",
"chars": 2364,
"preview": "PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2\n--------------------------------------------\n\n1. This LICENSE AGREEMENT is "
},
{
"path": "README.md",
"chars": 235,
"preview": "# release-tools\n\n[\nfor CPython release artifacts. Can also be run manually with"
},
{
"path": "select_jobs.py",
"chars": 1022,
"preview": "#!/usr/bin/env python3\n\nimport argparse\n\nfrom release import Tag\n\n\ndef output(key: str, value: bool) -> None:\n print("
},
{
"path": "tests/README.rst",
"chars": 8906,
"preview": "This is Python version 3.14.0 alpha 3\n=====================================\n\n.. image:: https://github.com/python/cpytho"
},
{
"path": "tests/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "tests/buildbotapi/builders.json",
"chars": 1049,
"preview": "{\n \"builders\": [\n {\n \"builderid\": 3,\n \"description\": null,\n \"description_form"
},
{
"path": "tests/buildbotapi/failure.json",
"chars": 419,
"preview": "{\n \"builds\": [\n {\n \"builderid\": 3,\n \"buildid\": 1732278,\n \"buildrequestid\": 2341889,\n \"complete\":"
},
{
"path": "tests/buildbotapi/no-builds.json",
"chars": 54,
"preview": "{\n \"builds\": [\n ],\n \"meta\": {\n \"total\": 0\n }\n}\n"
},
{
"path": "tests/buildbotapi/success.json",
"chars": 417,
"preview": "{\n \"builds\": [\n {\n \"builderid\": 3,\n \"buildid\": 1645411,\n \"buildrequestid\": 2211085,\n \"complete\":"
},
{
"path": "tests/fake-artifact.txt",
"chars": 0,
"preview": ""
},
{
"path": "tests/fake-ftp-files.txt",
"chars": 17925,
"preview": "# Test data only, doesn't need to be updated for each release\nPython-3.14.0a1.tar.xz\nPython-3.14.0a1.tar.xz.crt\nPython-3"
},
{
"path": "tests/magicdata/Include/internal/pycore_magic_number.h",
"chars": 221,
"preview": "// copied from cpython bd3d31f380cd451a4ab6da5fbfde463fed95b5b5\n// ...\n\n#ifndef Py_INTERNAL_MAGIC_NUMBER_H\n#define Py_IN"
},
{
"path": "tests/magicdata/Lib/test/test_importlib/test_util.py",
"chars": 191,
"preview": "# copied from cpython bd3d31f380cd451a4ab6da5fbfde463fed95b5b5\n\n\nclass SomeClass:\n def some_method(self) -> None:\n "
},
{
"path": "tests/patchlevel.h",
"chars": 1302,
"preview": "\n/* Python version identification scheme.\n\n When the major or minor version changes, the VERSION variable in\n config"
},
{
"path": "tests/sbom/sbom-with-pip-removed.json",
"chars": 552,
"preview": "{\n \"SPDXID\": \"SPDXRef-DOCUMENT\",\n \"name\": \"CPython SBOM\",\n \"spdxVersion\": \"SPDX-2.3\",\n \"dataLicense\": \"CC0-1.0\",\n \""
},
{
"path": "tests/sbom/sbom-with-pip.json",
"chars": 1698,
"preview": "{\n \"SPDXID\": \"SPDXRef-DOCUMENT\",\n \"name\": \"CPython SBOM\",\n \"spdxVersion\": \"SPDX-2.3\",\n \"dataLicense\": \"CC0-1.0\",\n \""
},
{
"path": "tests/test_add_to_pydotorg.py",
"chars": 6392,
"preview": "import os\nfrom pathlib import Path\n\nimport pytest\nfrom pyfakefs.fake_filesystem import FakeFilesystem\n\nos.environ[\"AUTH_"
},
{
"path": "tests/test_buildbotapi.py",
"chars": 4059,
"preview": "from functools import cache\nfrom unittest.mock import AsyncMock\n\nimport aiohttp\nimport pytest\n\nimport buildbotapi\n\n\ndef "
},
{
"path": "tests/test_release.py",
"chars": 5381,
"preview": "from pathlib import Path\nfrom typing import cast\n\nimport pytest\nfrom pytest_mock import MockerFixture\n\nimport release\n\n\n"
},
{
"path": "tests/test_release_tag.py",
"chars": 4583,
"preview": "import io\nfrom subprocess import CompletedProcess\n\nimport pytest\nfrom pytest_mock import MockerFixture\n\nimport release\n\n"
},
{
"path": "tests/test_run_release.py",
"chars": 7749,
"preview": "import builtins\nimport contextlib\nimport io\nimport tarfile\nfrom contextlib import nullcontext as does_not_raise\nfrom pat"
},
{
"path": "tests/test_sbom.py",
"chars": 8631,
"preview": "import hashlib\nimport json\nimport pathlib\nimport random\nimport re\nimport unittest.mock\nfrom pathlib import Path\n\nimport "
},
{
"path": "tests/test_select_jobs.py",
"chars": 1563,
"preview": "import sys\nfrom textwrap import dedent\n\nimport pytest\n\nimport select_jobs\n\n\n@pytest.mark.parametrize(\n (\"version\", \"d"
},
{
"path": "tests/test_update_version_next.py",
"chars": 1561,
"preview": "\"\"\"Tests for the update_version_next tool.\"\"\"\n\nfrom pathlib import Path\n\nimport update_version_next\n\nTO_CHANGE = \"\"\"\nDir"
},
{
"path": "tests/whatsnew_index.rst",
"chars": 839,
"preview": ".. _whatsnew-index:\n\n######################\n What's New in Python\n######################\n\nThe \"What's New in Python\" ser"
},
{
"path": "tox.ini",
"chars": 608,
"preview": "[tox]\nrequires =\n tox>=4.2\nenv_list =\n lint\n py{314, 313, 312}\n\n[testenv]\nskip_install = true\ndeps =\n -r dev"
},
{
"path": "update_version_next.py",
"chars": 2592,
"preview": "#!/usr/bin/env python3\n\"\"\"\nReplace `.. versionchanged:: next` lines in docs files by the given version.\n\nRun this at rel"
},
{
"path": "windows-release/README.md",
"chars": 4445,
"preview": "# Windows Releases\n\nThis build script is used for official releases of CPython on Windows.\nIt is somewhat more complex t"
},
{
"path": "windows-release/acquire-vcruntime.yml",
"chars": 382,
"preview": "parameters:\n Remote: https://github.com/python/cpython-bin-deps\n Ref: vcruntime\n\nsteps:\n- powershell: |\n git clone "
},
{
"path": "windows-release/azure-pipelines.yml",
"chars": 11954,
"preview": "name: Release_$(SourceTag)_$(Date:yyyyMMdd)$(Rev:.rr)\n\nparameters:\n- name: GitRemote\n displayName: \"Git remote\"\n type:"
},
{
"path": "windows-release/build-steps-pgo.yml",
"chars": 5527,
"preview": "parameters:\n PGInstrument: false\n PGRun: false\n PGUpdate: false\n\nsteps:\n- template: ./checkout.yml\n\n- ${{ if or(eq(pa"
},
{
"path": "windows-release/build-steps.yml",
"chars": 2633,
"preview": "parameters:\n ShouldPGO: false\n\nsteps:\n- template: ./checkout.yml\n- template: ./acquire-vcruntime.yml\n\n- powershell: |\n "
},
{
"path": "windows-release/checkout.yml",
"chars": 2229,
"preview": "parameters:\n depth: 3\n IncludeSelf: false\n Path: .\n\nsteps:\n- ${{ if eq(parameters.IncludeSelf, 'true') }}:\n - checko"
},
{
"path": "windows-release/find-sdk.yml",
"chars": 619,
"preview": "# Locate the Windows SDK and add its binaries directory to PATH\n#\n# `toolname` can be overridden to use a different mark"
},
{
"path": "windows-release/find-tools.yml",
"chars": 993,
"preview": "# Locate a set of the tools used for builds\n\nsteps:\n - template: ./find-sdk.yml\n parameters:\n toolname: 'signto"
},
{
"path": "windows-release/layout-command.yml",
"chars": 1803,
"preview": "parameters:\n Binaries: $(Pipeline.Workspace)\\bin_$(Name)\n Sources: $(Build.SourcesDirectory)\n Temp: $(Build.BinariesD"
},
{
"path": "windows-release/libffi-build.yml",
"chars": 2939,
"preview": "parameters:\n- name: SourceTag\n displayName: 'LibFFI Source Tag'\n type: string\n- name: SigningCertificate\n displayName"
},
{
"path": "windows-release/merge-and-upload.py",
"chars": 12773,
"preview": "import hashlib\nimport json\nimport os\nimport re\nimport subprocess\nimport sys\nfrom pathlib import Path\nfrom urllib.parse i"
},
{
"path": "windows-release/msi-steps.yml",
"chars": 6785,
"preview": "parameters:\n BuildToPackage: current\n DoFreethreaded: false\n SigningCertificate: ''\n Artifacts: []\n\nsteps:\n - templ"
},
{
"path": "windows-release/openssl-build.yml",
"chars": 3907,
"preview": "parameters:\n- name: SourceTag\n displayName: 'OpenSSL Source Tag'\n type: string\n- name: SigningCertificate\n displayNam"
},
{
"path": "windows-release/purge.py",
"chars": 1885,
"preview": "# Purges the Fastly cache for Windows download files\n#\n# Usage:\n# py -3 purge.py 3.5.1rc1\n#\n\n__author__ = \"Steve Dower"
},
{
"path": "windows-release/sign-files.yml",
"chars": 7280,
"preview": "parameters:\n Include: '*'\n Exclude: ''\n Filter: ''\n WorkingDir: '$(Build.BinariesDirectory)'\n ExtractDir: ''\n Sign"
},
{
"path": "windows-release/stage-build.yml",
"chars": 12331,
"preview": "parameters:\n DoPGO: false\n # DoPGOARM64 only applies if DoPGO is also true\n DoPGOARM64: true\n DoFreethreaded: false\n"
},
{
"path": "windows-release/stage-layout-embed.yml",
"chars": 3138,
"preview": "parameters:\n BuildToPackage: current\n SigningCertificate: ''\n\njobs:\n- job: Make_Embed_Layout\n displayName: Make embed"
},
{
"path": "windows-release/stage-layout-full.yml",
"chars": 4711,
"preview": "parameters:\n BuildToPackage: current\n DoFreethreaded: false\n SigningCertificate: ''\n\njobs:\n- job: Make_Layouts\n disp"
},
{
"path": "windows-release/stage-layout-msix.yml",
"chars": 4381,
"preview": "parameters:\n BuildToPackage: current\n SigningCertificate: ''\n\njobs:\n- job: Make_MSIX_Layout\n displayName: Make MSIX l"
},
{
"path": "windows-release/stage-layout-nuget.yml",
"chars": 2164,
"preview": "parameters:\n BuildToPackage: current\n DoFreethreaded: false\n SigningCertificate: ''\n\njobs:\n- job: Make_Nuget_Layout\n "
},
{
"path": "windows-release/stage-layout-pymanager.yml",
"chars": 7648,
"preview": "parameters:\n BuildToPackage: current\n DoFreethreaded: false\n DoEmbed: false\n LayoutScriptBranch: main\n SigningCerti"
},
{
"path": "windows-release/stage-layout-symbols.yml",
"chars": 1913,
"preview": "parameters:\n BuildToPackage: current\n DoFreethreaded: false\n Packages:\n - win32\n - amd64\n - arm64\n - win32_d\n - "
},
{
"path": "windows-release/stage-msi.yml",
"chars": 3503,
"preview": "parameters:\n BuildToPackage: current\n DoARM64: true\n DoFreethreaded: false\n SigningCertificate: ''\n Post315OutputDi"
},
{
"path": "windows-release/stage-pack-msix.yml",
"chars": 4518,
"preview": "parameters:\n SigningCertificate: ''\n\njobs:\n- job: Pack_MSIX\n displayName: Pack MSIX bundles\n\n workspace:\n clean: a"
},
{
"path": "windows-release/stage-pack-nuget.yml",
"chars": 2206,
"preview": "parameters:\n DoFreethreaded: false\n SigningCertificate: ''\n\njobs:\n- job: Pack_Nuget\n displayName: Pack Nuget bundles\n"
},
{
"path": "windows-release/stage-pack-pymanager.yml",
"chars": 1937,
"preview": "parameters:\n DoFreethreaded: false\n DoEmbed: false\n SigningCertificate: ''\n\n Artifacts:\n - name: win32\n - name: am"
},
{
"path": "windows-release/stage-publish-nugetorg.yml",
"chars": 1351,
"preview": "parameters:\n BuildToPublish: current\n\njobs:\n- job: Publish_Nuget\n displayName: Publish Nuget packages\n condition: and"
},
{
"path": "windows-release/stage-publish-pymanager.yml",
"chars": 5913,
"preview": "parameters:\n BuildToPublish: current\n DoFreethreaded: false\n DoEmbed: false\n HashAlgorithms: ['SHA256']\n SigningCer"
},
{
"path": "windows-release/stage-publish-pythonorg.yml",
"chars": 6676,
"preview": "parameters:\n BuildToPublish: current\n DoEmbed: true\n IncludeGPG: false\n HashAlgorithms: ['SHA256', 'MD5']\n\njobs:\n- j"
},
{
"path": "windows-release/stage-sign.yml",
"chars": 2512,
"preview": "parameters:\n Include: '*.exe, *.dll, *.pyd, *.cat, *.ps1'\n Exclude: 'vcruntime*, libffi*, libcrypto*, libssl*'\n Signi"
},
{
"path": "windows-release/stage-test-embed.yml",
"chars": 1014,
"preview": "jobs:\n- job: Test_Embed\n displayName: Test Embed\n\n workspace:\n clean: all\n\n strategy:\n matrix:\n win32:\n "
},
{
"path": "windows-release/stage-test-msi.yml",
"chars": 4649,
"preview": "parameters:\n DoFreethreaded: false\n\njobs:\n- job: Test_MSI\n displayName: Test MSI\n\n workspace:\n clean: all\n\n varia"
},
{
"path": "windows-release/stage-test-nuget.yml",
"chars": 1430,
"preview": "jobs:\n- job: Test_Nuget\n displayName: Test Nuget\n\n workspace:\n clean: all\n\n strategy:\n matrix:\n win32:\n "
},
{
"path": "windows-release/stage-test-pymanager.yml",
"chars": 1672,
"preview": "parameters:\n DoEmbed: false\n DoFreethreaded: false\n\njobs:\n- job: Test_PyManager\n displayName: Test PyManager\n\n works"
},
{
"path": "windows-release/start-arm64vm.yml",
"chars": 1708,
"preview": "parameters:\n DoARM64: false\n DoPGOARM64: false\n\njobs:\n# Only include the job if we need the VM, which means ARM64 PGO."
},
{
"path": "windows-release/tcltk-build.yml",
"chars": 4472,
"preview": "parameters:\n- name: TclSourceTag\n displayName: 'Tcl Source Tag'\n type: string\n- name: TkSourceTag\n displayName: 'Tk S"
},
{
"path": "windows-release/uploadrelease.ps1",
"chars": 4189,
"preview": "<#\n.Synopsis\n Uploads from a VSTS release build layout to python.org\n.Description\n Given the downloaded/extracted "
}
]
About this extraction
This page contains the full source code of the python/release-tools GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 83 files (496.9 KB), approximately 172.1k tokens, and a symbol index with 263 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.