diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml
index fccacae..c7b5167 100644
--- a/.github/dependabot.yaml
+++ b/.github/dependabot.yaml
@@ -15,3 +15,16 @@ updates:
- "*"
cooldown:
default-days: 7
+ - package-ecosystem: "pre-commit"
+ directory: "/"
+ labels:
+ - dependencies
+ - skip news
+ schedule:
+ interval: "weekly"
+ day: "tuesday"
+ allow:
+ - dependency-name: mdformat-gfm
+ - dependency-name: mdformat-ruff
+ cooldown:
+ default-days: 7
diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml
index 8a097c8..dfd9f53 100644
--- a/.github/workflows/check.yaml
+++ b/.github/workflows/check.yaml
@@ -5,12 +5,12 @@ on:
branches: ["main"]
tags-ignore: ["**"]
pull_request:
- types: [opened, synchronize, reopened, labeled, unlabeled]
+ types: [opened, synchronize, reopened]
schedule:
- cron: "0 8 * * *"
concurrency:
group: check-${{ github.ref }}
- cancel-in-progress: true
+ cancel-in-progress: false
permissions:
contents: read
jobs:
@@ -34,9 +34,10 @@ jobs:
with:
fetch-depth: 0
persist-credentials: false
- - name: Install the latest version of uv
+ - name: Set up uv
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
with:
+ version: latest-known
python-version: "3.15"
enable-cache: false
cache-dependency-glob: "pyproject.toml"
@@ -45,39 +46,46 @@ jobs:
run: uv tool install --python-preference only-managed --python 3.15 tox --with tox-uv
- name: Install Python
if: startsWith(matrix.env, '3.') && matrix.env != '3.15'
- run: uv python install --python-preference only-managed ${{ matrix.env }}
+ env:
+ MATRIX_ENV: ${{ matrix.env }}
+ run: uv python install --python-preference only-managed "$MATRIX_ENV"
- name: Setup test suite
- run: tox run -vv --notest --skip-missing-interpreters false -e ${{ matrix.env }}
+ env:
+ MATRIX_ENV: ${{ matrix.env }}
+ run: tox run -vv --notest --skip-missing-interpreters false -e "$MATRIX_ENV"
- name: Run test suite
- run: tox run --skip-pkg-install -e ${{ matrix.env }}
+ run: tox run --skip-pkg-install -e "$MATRIX_ENV"
env:
+ MATRIX_ENV: ${{ matrix.env }}
PYTEST_ADDOPTS: "-vv --durations=5"
- changelog:
- if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'skip news')
- runs-on: ubuntu-24.04
+ hook-cooldown:
+ name: Hook update cooldown
+ if: github.event_name == 'pull_request'
+ runs-on: ubuntu-26.04
+ permissions:
+ actions: read
+ contents: read
+ pull-requests: read
steps:
- - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - uses: tox-dev/github-workflows/check-hook-update-cooldown@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
with:
- fetch-depth: 0
- persist-credentials: false
- - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
- with:
- python-version: "3.15"
- enable-cache: false
- - run: uvx towncrier check --compare-with "origin/${GITHUB_BASE_REF}"
+ release-app-client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
+ env:
+ GH_TOKEN: ${{ github.token }}
gate:
name: Required checks pass
- if: always()
- needs: [test, changelog]
- runs-on: ubuntu-24.04
+ if: ${{ !cancelled() }} # codespell:ignore cancelled
+ needs: [test, hook-cooldown]
+ runs-on: ubuntu-26.04
steps:
- env:
NEEDS_JSON: ${{ toJSON(needs) }}
+ EVENT_NAME: ${{ github.event_name }}
run: |
- jq -e '
+ jq -e --arg event "$EVENT_NAME" '
all(
to_entries[];
.value.result == "success" or
- (.key == "changelog" and .value.result == "skipped")
+ ((.key == "hook-cooldown") and .value.result == "skipped" and $event != "pull_request")
)
- ' <<< "$NEEDS_JSON"
+ ' <<<"$NEEDS_JSON"
diff --git a/.github/workflows/news.yaml b/.github/workflows/news.yaml
new file mode 100644
index 0000000..22b949e
--- /dev/null
+++ b/.github/workflows/news.yaml
@@ -0,0 +1,30 @@
+name: Changelog
+on:
+ pull_request:
+ types: [opened, reopened, synchronize, labeled, unlabeled]
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
+ cancel-in-progress: true
+permissions:
+ contents: read
+jobs:
+ changelog:
+ name: News fragment
+ if: github.event_name == 'pull_request'
+ runs-on: ubuntu-26.04
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ fetch-depth: 0
+ persist-credentials: false
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
+ with:
+ version: latest-known
+ python-version: "3.15"
+ enable-cache: false
+ - name: Install locked release tools
+ uses: tox-dev/github-workflows/install-locked-tools@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ with:
+ groups: release-news
+ venv: ${{ runner.temp }}/release-tools
+ - uses: tox-dev/github-workflows/validate-news@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
diff --git a/.github/workflows/prepare-release.yaml b/.github/workflows/prepare-release.yaml
index 144d291..af55186 100644
--- a/.github/workflows/prepare-release.yaml
+++ b/.github/workflows/prepare-release.yaml
@@ -2,105 +2,24 @@ name: Prepare release
on:
workflow_dispatch:
inputs:
- version:
- description: Version to release, without a v prefix
+ bump:
+ description: Version bump type
required: true
-permissions: {}
-concurrency:
- group: prepare-release
- cancel-in-progress: false
+ type: choice
+ options:
+ - auto
+ - major
+ - minor
+ - patch
+ default: auto
+permissions:
+ contents: read
+ pull-requests: read
jobs:
- assemble:
- if: github.ref == 'refs/heads/main'
- runs-on: ubuntu-26.04
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- with:
- fetch-depth: 0
- persist-credentials: false
- - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
- with:
- python-version: "3.15"
- enable-cache: false
- - name: Build release patch
- env:
- VERSION: ${{ inputs.version }}
- run: |
- set -euo pipefail
- if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
- echo "::error::expected a major.minor.patch version"
- exit 1
- fi
- latest=$(git tag --list '[0-9]*' | sort -V | tail -n 1)
- if [[ "$(printf '%s\n' "$latest" "$VERSION" | sort -V | tail -n 1)" != "$VERSION" || "$latest" == "$VERSION" ]]; then
- echo "::error::$VERSION must be newer than $latest"
- exit 1
- fi
- if ! compgen -G 'changelog.d/*.md' > /dev/null; then
- echo "::error::no changelog fragments to release"
- exit 1
- fi
- uvx towncrier build --yes --version "$VERSION"
- git diff HEAD --binary > "$RUNNER_TEMP/release.patch"
- test -s "$RUNNER_TEMP/release.patch"
- - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
- with:
- name: release-patch
- path: ${{ runner.temp }}/release.patch
- if-no-files-found: error
- push:
- needs: assemble
- runs-on: ubuntu-26.04
- environment: release-auth
- permissions:
- contents: read
- steps:
- - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- with:
- fetch-depth: 0
- persist-credentials: false
- - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
- with:
- name: release-patch
- path: ${{ runner.temp }}/release-patch
- - name: Validate release patch
- env:
- VERSION: ${{ inputs.version }}
- run: |
- set -euo pipefail
- git fetch origin main
- git reset --hard origin/main
- git apply --check "$RUNNER_TEMP/release-patch/release.patch"
- git apply --index "$RUNNER_TEMP/release-patch/release.patch"
- while IFS= read -r path; do
- case "$path" in
- CHANGELOG.md|changelog.d/*.md) ;;
- *) echo "::error::unexpected release path: $path"; exit 1 ;;
- esac
- done < <(git diff --cached --name-only)
- grep -Fq "## $VERSION (" CHANGELOG.md
- git diff --cached --check
- - id: token
- uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
- with:
- client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
- private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- owner: ${{ github.repository_owner }}
- repositories: ${{ github.event.repository.name }}
- permission-contents: write
- - name: Commit and tag the release
- env:
- VERSION: ${{ inputs.version }}
- GH_TOKEN: ${{ steps.token.outputs.token }}
- APP_SLUG: ${{ steps.token.outputs.app-slug }}
- run: |
- set -euo pipefail
- app_user_id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id)
- git config user.name "${APP_SLUG}[bot]"
- git config user.email "${app_user_id}+${APP_SLUG}[bot]@users.noreply.github.com"
- git commit -m "chore: prepare $VERSION"
- git tag "$VERSION"
- gh auth setup-git --hostname github.com --force
- git push --atomic origin HEAD:main "refs/tags/$VERSION"
+ prepare:
+ name: Prepare Towncrier release
+ uses: tox-dev/github-workflows/.github/workflows/prepare-towncrier-release.yaml@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ with:
+ bump: ${{ inputs.bump }}
+ secrets:
+ RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
diff --git a/.github/workflows/recheck-hook-cooldown.yaml b/.github/workflows/recheck-hook-cooldown.yaml
new file mode 100644
index 0000000..2a3151f
--- /dev/null
+++ b/.github/workflows/recheck-hook-cooldown.yaml
@@ -0,0 +1,18 @@
+name: Recheck hook cooldown
+on:
+ schedule:
+ - cron: "17 7 * * *"
+ workflow_dispatch:
+permissions: {}
+jobs:
+ recheck:
+ runs-on: ubuntu-26.04
+ permissions:
+ actions: write
+ contents: read
+ pull-requests: read
+ steps:
+ - uses: tox-dev/github-workflows/recheck-hook-update-cooldown@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ with:
+ workflow: check.yaml
+ job-name: Hook update cooldown
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 0874cb6..0ecdbcc 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -4,84 +4,199 @@ on:
tags: ["*"]
permissions:
contents: read
+concurrency:
+ group: release-${{ github.ref }}
+ cancel-in-progress: false
env:
dists-artifact-name: python-package-distributions
jobs:
build:
+ name: Build and validate distributions
+ uses: tox-dev/github-workflows/.github/workflows/validate-python-release.yaml@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ permissions:
+ contents: read
+ previous-tag:
+ name: Select previous tag
runs-on: ubuntu-26.04
+ permissions:
+ contents: read
+ outputs:
+ previous: ${{ steps.select.outputs.previous }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- - name: Require a changelog section for the tag
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
+ with:
+ version: latest-known
+ python-version: "3.15"
+ enable-cache: false
+ - name: Install locked release tools
+ uses: tox-dev/github-workflows/install-locked-tools@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ with:
+ groups: release-notes
+ venv: ${{ runner.temp }}/release-tools
+ - name: Select previous tag
+ id: select
+ uses: tox-dev/github-workflows/select-previous-tag@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ with:
+ tag: ${{ github.ref_name }}
+ contributor-metadata:
+ name: Fetch contributor metadata
+ needs: previous-tag
+ runs-on: ubuntu-26.04
+ environment: release
+ permissions:
+ contents: write # GitHub's generated-notes endpoint requires this permission.
+ steps:
+ - name: Fetch contributor metadata
+ if: needs.previous-tag.outputs.previous != ''
env:
+ GH_TOKEN: ${{ github.token }}
+ TAG: ${{ github.ref_name }}
+ PREVIOUS: ${{ needs.previous-tag.outputs.previous }}
+ run: >-
+ gh api -X POST "repos/${GITHUB_REPOSITORY}/releases/generate-notes" -f tag_name="$TAG" -f previous_tag_name="$PREVIOUS" --jq .body >"$RUNNER_TEMP/generated-notes.md"
+ - name: Fetch first-release contributor metadata
+ if: needs.previous-tag.outputs.previous == ''
+ env:
+ GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
- run: |
- if [[ ! "$TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
- echo "::error::unexpected release tag $TAG"
- exit 1
- fi
- if ! grep -qF "## $TAG (" CHANGELOG.md; then
- echo "::error::CHANGELOG.md has no section for $TAG"
- exit 1
- fi
- - name: Install the latest version of uv
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
+ run: >-
+ gh api -X POST "repos/${GITHUB_REPOSITORY}/releases/generate-notes" -f tag_name="$TAG" --jq .body >"$RUNNER_TEMP/generated-notes.md"
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
+ name: github-generated-notes
+ path: ${{ runner.temp }}/generated-notes.md
+ if-no-files-found: error
+ github-notes:
+ name: Render GitHub notes
+ needs: [build, contributor-metadata, previous-tag]
+ runs-on: ubuntu-26.04
+ permissions:
+ contents: read
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ fetch-depth: 0
+ persist-credentials: false
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
+ with:
+ name: github-generated-notes
+ path: ${{ runner.temp }}
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
+ with:
+ version: latest-known
python-version: "3.15"
enable-cache: false
- cache-dependency-glob: "pyproject.toml"
- github-token: ${{ secrets.GITHUB_TOKEN }}
- - name: Build package
- run: uv build --python 3.15 --python-preference only-managed --sdist --wheel . --out-dir dist
- - name: Store the distribution packages
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
+ - name: Install locked release tools
+ uses: tox-dev/github-workflows/install-locked-tools@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
with:
- name: ${{ env.dists-artifact-name }}
- path: dist/*
+ groups: release-notes
+ venv: ${{ runner.temp }}/release-tools
+ - uses: tox-dev/github-workflows/render-release-notes@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ with:
+ tag: ${{ github.ref_name }}
+ previous: ${{ needs.previous-tag.outputs.previous }}
+ changelog: CHANGELOG.md
+ artifact-url: https://pypi.org/project/devpi-process/${{ github.ref_name }}/
+ generated-notes: ${{ runner.temp }}/generated-notes.md
+ output: ${{ runner.temp }}/release-notes.md
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
+ with:
+ name: github-release-notes
+ path: ${{ runner.temp }}/release-notes.md
+ if-no-files-found: error
+ github-draft:
+ name: Stage GitHub Release
+ needs: github-notes
+ runs-on: ubuntu-26.04
+ environment: release
+ permissions:
+ contents: write
+ steps:
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
+ with:
+ name: github-release-notes
+ path: ${{ runner.temp }}
+ - uses: tox-dev/github-workflows/publish-github-release@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ env:
+ GH_TOKEN: ${{ github.token }}
+ with:
+ tag: ${{ github.ref_name }}
+ commit: ${{ github.sha }}
+ title: ${{ github.ref_name }}
+ notes-file: ${{ runner.temp }}/release-notes.md
+ mode: stage
release:
+ name: Publish to PyPI
needs:
- build
+ - github-notes
+ - github-draft
runs-on: ubuntu-26.04
environment:
name: release
url: https://pypi.org/project/devpi-process/${{ github.ref_name }}
permissions:
- id-token: write
+ id-token: write # PyPI verifies this workflow through OIDC.
steps:
- - name: Download all the dists
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ env.dists-artifact-name }}
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
- attestations: true
- github-release:
- needs: release
+ packages-dir: dist
+ skip-existing: true
+ verify-pypi:
+ name: Verify PyPI distributions
+ needs:
+ - build
+ - github-notes
+ - github-draft
+ - release
runs-on: ubuntu-26.04
permissions:
- contents: write
+ contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
- fetch-depth: 0
persist-credentials: false
- - name: Publish GitHub Release
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
+ with:
+ name: ${{ env.dists-artifact-name }}
+ path: dist/
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
+ with:
+ version: latest-known
+ python-version: "3.15"
+ enable-cache: false
+ - uses: tox-dev/github-workflows/reconcile-pypi-artifacts@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ with:
+ project: devpi-process
+ version: ${{ github.ref_name }}
+ dist: dist
+ github-release:
+ name: Publish GitHub Release
+ needs: [verify-pypi, github-notes, github-draft]
+ runs-on: ubuntu-26.04
+ environment: release
+ permissions:
+ contents: write # GitHub Release creation and edits require this permission.
+ steps:
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
+ with:
+ name: github-release-notes
+ path: ${{ runner.temp }}
+ - uses: tox-dev/github-workflows/publish-github-release@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
env:
GH_TOKEN: ${{ github.token }}
- TAG: ${{ github.ref_name }}
- run: |
- set -euo pipefail
- awk -v tag="$TAG" 'index($0, "## " tag " (") == 1 { found = 1; next } found && /^## / { exit } found { print }' CHANGELOG.md > "$RUNNER_TEMP/release-notes.md"
- test -s "$RUNNER_TEMP/release-notes.md"
- printf '\n[PyPI release](https://pypi.org/project/devpi-process/%s/)\n' "$TAG" >> "$RUNNER_TEMP/release-notes.md"
- previous=$(git tag --list '[0-9]*' | grep -E '^[0-9]+(\.[0-9]+){1,2}$' | sort -V | awk -v tag="$TAG" '$0 == tag { print previous; exit } { previous = $0 }')
- if [[ -n "$previous" ]]; then
- printf '\n**Full Changelog**: https://github.com/%s/compare/%s...%s\n' "$GITHUB_REPOSITORY" "$previous" "$TAG" >> "$RUNNER_TEMP/release-notes.md"
- else
- printf '\n**Full Changelog**: https://github.com/%s/commits/%s\n' "$GITHUB_REPOSITORY" "$TAG" >> "$RUNNER_TEMP/release-notes.md"
- fi
- gh release create "$TAG" --verify-tag --title "$TAG" --notes-file "$RUNNER_TEMP/release-notes.md"
+ with:
+ tag: ${{ github.ref_name }}
+ commit: ${{ github.sha }}
+ title: ${{ github.ref_name }}
+ notes-file: ${{ runner.temp }}/release-notes.md
+ mode: publish
diff --git a/.github/workflows/upgrade-release-tools.yaml b/.github/workflows/upgrade-release-tools.yaml
new file mode 100644
index 0000000..f757b25
--- /dev/null
+++ b/.github/workflows/upgrade-release-tools.yaml
@@ -0,0 +1,24 @@
+name: Upgrade release tools
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: "0 8 * * 2"
+permissions: {}
+concurrency:
+ group: upgrade-release-tools
+ cancel-in-progress: false
+jobs:
+ upgrade:
+ uses: tox-dev/github-workflows/.github/workflows/upgrade-release-tools.yaml@e2d5e308194a31710039f3237b7157431c0e38b5 # v2.0.0
+ permissions:
+ contents: read
+ secrets:
+ RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
+ with:
+ lock-groups: >-
+ release-check release-news release-notes release-prepare release-validate
+ commit-message: "build(deps): refresh release lock"
+ pull-request-title: "build(deps): refresh project lock"
+ pull-request-body: |-
+ Refresh the release tool lock after the seven-day cooldown.
+ Release and changelog jobs install only their required groups from `pylock.toml`.
diff --git a/.gitignore b/.gitignore
index cb7c58d..ee557b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ coverage.xml
__pycache__
**.pyc
src/devpi_process/_version.py
+/uv.lock
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index e91bdb0..221cfc7 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,49 +2,47 @@ default_language_version:
python: python3.15
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v6.0.0
+ rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/python-jsonschema/check-jsonschema
- rev: 0.38.2
+ rev: 0494aa7fa1314e98913a41227d8f0a515b2c1049 # frozen: 0.38.2
hooks:
- id: check-github-workflows
args: ["--verbose"]
- repo: https://github.com/codespell-project/codespell
- rev: v2.4.3
+ rev: 57b21406f092110c18776e39b0bda50d37c945c8 # frozen: v2.4.3
hooks:
- id: codespell
- repo: https://github.com/tox-dev/tox-toml-fmt
- rev: "v1.11.1"
+ rev: 5125f601c3e134347288c3d42f3b34298b7cf1be # frozen: v1.11.1
hooks:
- id: tox-toml-fmt
- repo: https://github.com/tox-dev/pyproject-fmt
- rev: "v2.30.3"
+ rev: 50e0f3aee9dc5747a5f173f79a7417403c18dda6 # frozen: v2.30.3
hooks:
- id: pyproject-fmt
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: "v0.17.1"
+ rev: 38bfb07c0c64c304f47eb52090f8288150c77730 # frozen: v0.17.1
hooks:
- id: ruff-format
- - id: ruff
+ - id: ruff-check
args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"]
- repo: https://github.com/google/yamlfmt
- rev: "v0.21.0"
+ rev: 21ca5323a9c87ee37a434e0ca908efc0a89daa07 # frozen: v0.21.0
hooks:
- id: yamlfmt
- - repo: local
+ - repo: https://github.com/executablebooks/mdformat
+ rev: 82912cdaea4fb830f751504486a7879c70526547 # frozen: 1.0.0
hooks:
- id: mdformat
- name: mdformat
- entry: mdformat --wrap 120
- language: python
- types: [markdown]
+ args: ["--wrap", "120"]
additional_dependencies:
- - mdformat-gfm>=1
- - mdformat-ruff>=0.1.3
+ - mdformat-gfm==1.0.0
+ - mdformat-ruff==0.1.3
- repo: https://github.com/zizmorcore/zizmor-pre-commit
- rev: v1.31.1
+ rev: c92afdf2c6ca336aaa8f39e2bd8d48f62dbd8e1f # frozen: v1.31.1
hooks:
- id: zizmor
- repo: meta
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 863cc5a..da74765 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,54 +2,116 @@
+
+
## 1.3.1 (2026-10-19)
-### Documentation
+
+
+### Packaging
-- Publish a GitHub Release with the tagged changelog after each PyPI upload. (#290)
+- Publish a GitHub Release with the tagged changelog after each PyPI upload
+ ([#290](https://github.com/tox-dev/devpi-process/pull/290)) by [@gaborbernat](https://github.com/gaborbernat).
+
+
## 1.3.0 (2026-10-10)
-- Require Python 3.11 and use Python 3.15 by default ([#284](https://github.com/tox-dev/devpi-process/pull/284)).
+
+
+### Added
+
+- Require Python 3.11 ([#284](https://github.com/tox-dev/devpi-process/pull/284)) by
+ [@gaborbernat](https://github.com/gaborbernat).
+
+
## 1.2.0 (2026-07-21)
-- Test on Python 3.15 and tighten GitHub Actions security checks.
+
+
+### Added
+
+- Add Python 3.15 support ([#262](https://github.com/tox-dev/devpi-process/pull/262)) by
+ [@gaborbernat](https://github.com/gaborbernat).
+
+
## 1.1.1 (2026-02-23)
-- Move the development tooling to `tox.toml`, dependency groups, and ty.
+
## 1.1.0 (2025-10-09)
+
+
+### Added
+
- Add Python 3.14 support and end support for Python 3.8 and 3.9
- ([#196](https://github.com/tox-dev/devpi-process/pull/196)).
+ ([#196](https://github.com/tox-dev/devpi-process/pull/196)) by [@gaborbernat](https://github.com/gaborbernat).
+
+
## 1.0.2 (2024-09-18)
-- Improve CI ([#134](https://github.com/tox-dev/devpi-process/pull/134)).
+
## 1.0.1 (2024-09-08)
-- Declare Python 3.13 support ([#130](https://github.com/tox-dev/devpi-process/pull/130)).
+
+
+### Added
+
+- Declare Python 3.13 support ([#130](https://github.com/tox-dev/devpi-process/pull/130)) by
+ [@gaborbernat](https://github.com/gaborbernat).
+
+
## 1.0.0 (2023-08-22)
-- Exclude automated dependency and hook updates from generated release notes.
+
## 0.3.1 (2023-06-15)
-- Update dependencies and development tooling.
+
## 0.3.0 (2022-12-03)
-- Show stdout/stderr details if a command fails
+
+
+### Added
+
+- Declare Python 3.11 support ([#31](https://github.com/tox-dev/devpi-process/pull/31)) by
+ [@gaborbernat](https://github.com/gaborbernat).
+
+
+
+### Fixed
+
+- Show stdout/stderr details if a command fails by [@gaborbernat](https://github.com/gaborbernat).
+
+
## 0.2 (2021-12-29)
-- Drop 3.6 support and bump linters
-- Index URL now ends with `/` to avoid redirect when sending a GET
+
+
+### Added
+
+- Drop Python 3.6 support by [@gaborbernat](https://github.com/gaborbernat).
+
+
+
+### Fixed
+
+- Index URL now ends with `/` to avoid redirect when sending a GET by [@gaborbernat](https://github.com/gaborbernat).
+
+
## 0.1 (2021-06-17)
-- First release
+
+
+### Added
+
+- First release by [@gaborbernat](https://github.com/gaborbernat).
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..9509c09
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,36 @@
+# Contributing
+
+Run the tests and type checker with `tox -e 3.15,type`. Run `prek run --all-files` before pushing a pull request.
+
+## Release notes
+
+Add a `changelog.d/+short-name..md` fragment when a pull request changes what package users can use or observe.
+Use one fragment per user-facing change. The release workflow links each fragment to its merged squash pull request.
+
+| Type | Changelog section | Use for |
+| ------------- | ----------------- | ---------------------------------------------------------- |
+| `feature` | Added | New capabilities and Python support additions or removals |
+| `change` | Changes | Changed behavior that remains available |
+| `bugfix` | Fixed | Corrected behavior |
+| `doc` | Documentation | Documentation changes users need to know about |
+| `breaking` | Breaking changes | Changes that require users to update code or configuration |
+| `security` | Security | Security fixes users need to act on |
+| `performance` | Performance | User-visible speed or resource improvements |
+| `deprecation` | Deprecated | Supported behavior scheduled for removal |
+| `removal` | Removed | Removed user-facing capabilities other than Python support |
+| `packaging` | Packaging | Install, wheel, or distribution changes |
+
+Use `skip news` for a pull request with no user-facing change. The label can be applied after the pull request opens. A
+fragment still has to be valid when the label is present. Dependabot, pre-commit.ci, and repository automation receive
+the label when their pull request has no fragment.
+
+The release workflow credits the pull request author. If several people authored the change, add their linked GitHub
+handles in one `by` phrase in the fragment. Omit bots and reviewers.
+
+Pending fragments stay in `changelog.d` until a release. The prepare workflow writes the tagged entries to
+`CHANGELOG.md`; maintenance-only releases keep their version heading without a news entry. The GitHub Release uses the
+same entries with unwrapped lines and GitHub contributor metadata. The PyPI upload runs only after the notes render.
+
+`pylock.toml` records the selectable dependency groups for supported Python versions and platforms. The weekly release
+lock workflow refreshes it after a seven-day cooldown. Release jobs install the specific tool groups they need from this
+lock.
diff --git a/README.md b/README.md
index 9e1324e..9ed93c2 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
# devpi-process
-See the [changelog](CHANGELOG.md) for released changes. Pull requests need a `changelog.d/..md` fragment; use
-the `skip news` label for changes that do not need release notes.
+See the [changelog](CHANGELOG.md) for released changes and [contributing guide](CONTRIBUTING.md) for fragment rules.
[](https://pypi.org/project/devpi-process)
[](https://pypi.org/project/devpi-process)
diff --git a/changelog.d/+pypi-readme-links.bugfix.md b/changelog.d/+pypi-readme-links.bugfix.md
new file mode 100644
index 0000000..d916c91
--- /dev/null
+++ b/changelog.d/+pypi-readme-links.bugfix.md
@@ -0,0 +1 @@
+Fix repository links in the PyPI project description.
diff --git a/pylock.toml b/pylock.toml
new file mode 100644
index 0000000..99ad293
--- /dev/null
+++ b/pylock.toml
@@ -0,0 +1,2247 @@
+lock-version = "1.0"
+environments = [
+ "python_version == \"3.15\" and sys_platform == \"linux\" and platform_machine == \"x86_64\" and implementation_name == \"cpython\" and os_name == \"posix\" and platform_python_implementation == \"CPython\" and platform_system == \"Linux\"",
+ "python_version == \"3.15\" and sys_platform == \"linux\" and platform_machine == \"aarch64\" and implementation_name == \"cpython\" and os_name == \"posix\" and platform_python_implementation == \"CPython\" and platform_system == \"Linux\"",
+ "python_version == \"3.15\" and sys_platform == \"darwin\" and platform_machine == \"arm64\" and implementation_name == \"cpython\" and os_name == \"posix\" and platform_python_implementation == \"CPython\" and platform_system == \"Darwin\"",
+ "python_version == \"3.15\" and sys_platform == \"win32\" and platform_machine == \"AMD64\" and implementation_name == \"cpython\" and os_name == \"nt\" and platform_python_implementation == \"CPython\" and platform_system == \"Windows\"",
+]
+requires-python = ">=3.11"
+dependency-groups = [
+ "build",
+ "project-runtime",
+ "release-check",
+ "release-news",
+ "release-notes",
+ "release-prepare",
+ "release-validate",
+]
+default-groups = [
+ "project-runtime",
+]
+created-by = "nab"
+
+[[packages]]
+name = "anyio"
+version = "4.15.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "idna" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "anyio-4.15.1.tar.gz"
+upload-time = 2026-09-05 10:42:39.440376+00:00
+url = "https://files.pythonhosted.org/packages/a9/d2/f4d173e22df740bc37b1db102b386ba719b66e95b0f0d751f556b387e6d2/anyio-4.15.1.tar.gz"
+size = 276966
+
+[packages.sdist.hashes]
+sha256 = "9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94"
+
+[[packages.wheels]]
+name = "anyio-4.15.1-py3-none-any.whl"
+upload-time = 2026-09-05 10:42:37.923487+00:00
+url = "https://files.pythonhosted.org/packages/12/b8/4bd346e22b28902df4d651910f5242c28d84e4a5c2435ca5c3f797ed7e2e/anyio-4.15.1-py3-none-any.whl"
+size = 132079
+
+[packages.wheels.hashes]
+sha256 = "6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101"
+
+[[packages]]
+name = "argon2-cffi"
+version = "25.1.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.8"
+dependencies = [
+ { name = "argon2-cffi-bindings" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "argon2_cffi-25.1.0.tar.gz"
+upload-time = 2025-06-03 06:55:32.073787+00:00
+url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz"
+size = 45706
+
+[packages.sdist.hashes]
+sha256 = "694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1"
+
+[[packages.wheels]]
+name = "argon2_cffi-25.1.0-py3-none-any.whl"
+upload-time = 2025-06-03 06:55:30.804163+00:00
+url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl"
+size = 14657
+
+[packages.wheels.hashes]
+sha256 = "fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741"
+
+[[packages]]
+name = "argon2-cffi-bindings"
+version = "26.1.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "cffi" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "argon2_cffi_bindings-26.1.0.tar.gz"
+upload-time = 2026-08-20 07:44:22.492439+00:00
+url = "https://files.pythonhosted.org/packages/0b/43/bb8b6e8708d49a5ab36781333af092d9f483b198a2710d01281204640055/argon2_cffi_bindings-26.1.0.tar.gz"
+size = 1790807
+
+[packages.sdist.hashes]
+sha256 = "63505c71542a44b68b1e38060450fb006404170da375feb31af153e7f9c6205d"
+
+[[packages.wheels]]
+name = "argon2_cffi_bindings-26.1.0-cp310-abi3-macosx_11_0_arm64.whl"
+upload-time = 2026-08-20 07:32:43.019930+00:00
+url = "https://files.pythonhosted.org/packages/e7/d2/0ae991f1b2181e5be49007c574710a800ad36c2978683addb3e67c474e55/argon2_cffi_bindings-26.1.0-cp310-abi3-macosx_11_0_arm64.whl"
+size = 25521
+
+[packages.wheels.hashes]
+sha256 = "21ca0396fe5ec995dd54431c32698189666f9224810acfa752e50d2bd94d9df2"
+
+[[packages.wheels]]
+name = "argon2_cffi_bindings-26.1.0-cp310-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl"
+upload-time = 2026-08-20 07:32:44.158574+00:00
+url = "https://files.pythonhosted.org/packages/7e/e4/ad91d8297638aa2258aad4501c306aca99480dfe76ccd638173fa3702db9/argon2_cffi_bindings-26.1.0-cp310-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl"
+size = 27177
+
+[packages.wheels.hashes]
+sha256 = "78de2d65e0b9ea7ce9d1b1c3e87297b2d7305a02c266ee2a2d6910daddd7ee69"
+
+[[packages.wheels]]
+name = "argon2_cffi_bindings-26.1.0-cp310-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl"
+upload-time = 2026-08-20 07:32:45.172418+00:00
+url = "https://files.pythonhosted.org/packages/6f/86/5363df11b86d02cf3662208e7406496327649cc90eb365bf6f4e8a54a41f/argon2_cffi_bindings-26.1.0-cp310-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl"
+size = 26597
+
+[packages.wheels.hashes]
+sha256 = "27f1821903e2ceadcb88ec2b45ef190897b7682449c772f4d9b53e42c520cf29"
+
+[[packages.wheels]]
+name = "argon2_cffi_bindings-26.1.0-cp310-abi3-win_amd64.whl"
+upload-time = 2026-08-20 07:32:51.091752+00:00
+url = "https://files.pythonhosted.org/packages/6d/3a/0cc14a05810e6add9bce5e87693334baa2222de5f647fa31781885b6573f/argon2_cffi_bindings-26.1.0-cp310-abi3-win_amd64.whl"
+size = 25730
+
+[packages.wheels.hashes]
+sha256 = "2c36ff87b5dfaa477d0bd51e9d7f6abdae7c8955d2983c97419085d842154b3e"
+
+[[packages]]
+name = "attrs"
+version = "26.1.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "attrs-26.1.0.tar.gz"
+upload-time = 2026-03-19 14:22:25.026315+00:00
+url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz"
+size = 952055
+
+[packages.sdist.hashes]
+sha256 = "d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"
+
+[[packages.wheels]]
+name = "attrs-26.1.0-py3-none-any.whl"
+upload-time = 2026-03-19 14:22:23.645947+00:00
+url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl"
+size = 67548
+
+[packages.wheels.hashes]
+sha256 = "c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"
+
+[[packages]]
+name = "build"
+version = "1.6.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "colorama" },
+ { name = "packaging" },
+ { name = "pyproject-hooks" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "build-1.6.1.tar.gz"
+upload-time = 2026-09-10 07:56:00.417084+00:00
+url = "https://files.pythonhosted.org/packages/bd/67/4898a44ea4f3f8e213b0954ec0aa0a16971d62a6212d6ea3931e97115b99/build-1.6.1.tar.gz"
+size = 113427
+
+[packages.sdist.hashes]
+sha256 = "51cc11666391ab6f092070437ac747002ff46f3e4113a3622177ee6b488bfc53"
+
+[[packages.wheels]]
+name = "build-1.6.1-py3-none-any.whl"
+upload-time = 2026-09-10 07:55:59.148398+00:00
+url = "https://files.pythonhosted.org/packages/ad/9b/9fb3585dabcd73a1b2a6267f63f62649347c9e6d072c9fde365b105abb2c/build-1.6.1-py3-none-any.whl"
+size = 31179
+
+[packages.wheels.hashes]
+sha256 = "ecd351a4be9d35a9eaaba244a7687143c9c7d4aea6ac964e7e7ddab20cbcf4e7"
+
+[[packages]]
+name = "certifi"
+version = "2026.7.22"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "certifi-2026.7.22.tar.gz"
+upload-time = 2026-07-22 03:35:12.644458+00:00
+url = "https://files.pythonhosted.org/packages/a3/c2/24167ea9858356b47a87a50d39908bfdb72ceeefe0041586e704e5376b3a/certifi-2026.7.22.tar.gz"
+size = 138112
+
+[packages.sdist.hashes]
+sha256 = "741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55"
+
+[[packages.wheels]]
+name = "certifi-2026.7.22-py3-none-any.whl"
+upload-time = 2026-07-22 03:35:11.276376+00:00
+url = "https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl"
+size = 136983
+
+[packages.wheels.hashes]
+sha256 = "62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775"
+
+[[packages]]
+name = "cffi"
+version = "2.1.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "pycparser" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "cffi-2.1.1.tar.gz"
+upload-time = 2026-08-03 21:21:18.939988+00:00
+url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz"
+size = 530807
+
+[packages.sdist.hashes]
+sha256 = "dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be"
+
+[[packages.wheels]]
+name = "cffi-2.1.1-cp315-cp315-macosx_11_0_arm64.whl"
+upload-time = 2026-08-03 21:20:52.173342+00:00
+url = "https://files.pythonhosted.org/packages/0c/75/2f5207ff6d1a613133b23a5203cc0c2a628313b5eb3974d7956ae3c57950/cffi-2.1.1-cp315-cp315-macosx_11_0_arm64.whl"
+size = 185002
+
+[packages.wheels.hashes]
+sha256 = "2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8"
+
+[[packages.wheels]]
+name = "cffi-2.1.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl"
+upload-time = 2026-08-03 21:20:53.462549+00:00
+url = "https://files.pythonhosted.org/packages/e2/31/9e1313b0a6e30e91b3b3d3fff51ae99c857c07738e3afcce1f7334e1b7ab/cffi-2.1.1-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl"
+size = 222271
+
+[packages.wheels.hashes]
+sha256 = "507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6"
+
+[[packages.wheels]]
+name = "cffi-2.1.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"
+upload-time = 2026-08-03 21:20:57.336082+00:00
+url = "https://files.pythonhosted.org/packages/44/16/29e6d01b388bef055ecd6ca8244b3f4d336bd09e92d5d892187b9601084e/cffi-2.1.1-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"
+size = 221630
+
+[packages.wheels.hashes]
+sha256 = "aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399"
+
+[[packages.wheels]]
+name = "cffi-2.1.1-cp315-cp315-win_amd64.whl"
+upload-time = 2026-08-03 21:21:16.108179+00:00
+url = "https://files.pythonhosted.org/packages/e0/31/5158704cc474ab65c1647932e88be78dc0873f47130e253be38bcaf13d01/cffi-2.1.1-cp315-cp315-win_amd64.whl"
+size = 187897
+
+[packages.wheels.hashes]
+sha256 = "e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960"
+
+[[packages]]
+name = "charset-normalizer"
+version = "3.5.2"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "charset_normalizer-3.5.2.tar.gz"
+upload-time = 2026-09-30 04:39:23.398219+00:00
+url = "https://files.pythonhosted.org/packages/33/1c/f41d4e74c28ab327ff3acd36053f7ea506c55872d7a90b0fa71aa3ab0c89/charset_normalizer-3.5.2.tar.gz"
+size = 172659
+
+[packages.sdist.hashes]
+sha256 = "39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef"
+
+[[packages.wheels]]
+name = "charset_normalizer-3.5.2-cp315-cp315-macosx_10_15_universal2.whl"
+upload-time = 2026-09-30 04:37:28.329851+00:00
+url = "https://files.pythonhosted.org/packages/ca/e9/34e597dee616d0b8ee4b34d29399e85c2204ade174157a48505d42baa4ff/charset_normalizer-3.5.2-cp315-cp315-macosx_10_15_universal2.whl"
+size = 367676
+
+[packages.wheels.hashes]
+sha256 = "87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26"
+
+[[packages.wheels]]
+name = "charset_normalizer-3.5.2-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl"
+upload-time = 2026-09-30 04:37:30.167187+00:00
+url = "https://files.pythonhosted.org/packages/60/9f/a5d1c91c0263745e2cd344c5a4415d787c575501ab1d449f1148ac6b495d/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl"
+size = 248414
+
+[packages.wheels.hashes]
+sha256 = "9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364"
+
+[[packages.wheels]]
+name = "charset_normalizer-3.5.2-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl"
+upload-time = 2026-09-30 04:37:37.397915+00:00
+url = "https://files.pythonhosted.org/packages/a0/a1/4fbf5d0f0f1b2a080474c1cf9a2f12c4c6531bb0e8ba591055e846d2b4e9/charset_normalizer-3.5.2-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl"
+size = 257336
+
+[packages.wheels.hashes]
+sha256 = "3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229"
+
+[[packages.wheels]]
+name = "charset_normalizer-3.5.2-cp315-cp315-win_amd64.whl"
+upload-time = 2026-09-30 04:37:53.427053+00:00
+url = "https://files.pythonhosted.org/packages/98/e8/55d5fd3935b4bce6da4fe0df61898e8c82653e317e677bd58aceb9c60f13/charset_normalizer-3.5.2-cp315-cp315-win_amd64.whl"
+size = 210858
+
+[packages.wheels.hashes]
+sha256 = "89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8"
+
+[[packages.wheels]]
+name = "charset_normalizer-3.5.2-cp37-abi3-macosx_10_9_universal2.whl"
+upload-time = 2026-09-30 04:38:26.216534+00:00
+url = "https://files.pythonhosted.org/packages/8c/ab/176fbfd5b64939c55d652366aa5b9ef1d767af207a3aa6ebeb0d226c484d/charset_normalizer-3.5.2-cp37-abi3-macosx_10_9_universal2.whl"
+size = 331815
+
+[packages.wheels.hashes]
+sha256 = "4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd"
+
+[[packages.wheels]]
+name = "charset_normalizer-3.5.2-cp37-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl"
+upload-time = 2026-09-30 04:38:28.032254+00:00
+url = "https://files.pythonhosted.org/packages/7e/84/371eac6b30bdbcbf2d632a1a01809103459216fcaae61b8b8d922c1bfb8a/charset_normalizer-3.5.2-cp37-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl"
+size = 253276
+
+[packages.wheels.hashes]
+sha256 = "1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7"
+
+[[packages.wheels]]
+name = "charset_normalizer-3.5.2-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl"
+upload-time = 2026-09-30 04:38:29.732000+00:00
+url = "https://files.pythonhosted.org/packages/43/6f/c4fbae58febff71709c51bc7e18fdfa55341dc382704740f9f0cbf03817b/charset_normalizer-3.5.2-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl"
+size = 241239
+
+[packages.wheels.hashes]
+sha256 = "d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f"
+
+[[packages.wheels]]
+name = "charset_normalizer-3.5.2-cp37-abi3-win_amd64.whl"
+upload-time = 2026-09-30 04:38:49.707190+00:00
+url = "https://files.pythonhosted.org/packages/9d/8a/b618149cc5207943a0242068d7a27897f56a62947b5a039085f2a22029f8/charset_normalizer-3.5.2-cp37-abi3-win_amd64.whl"
+size = 200092
+
+[packages.wheels.hashes]
+sha256 = "9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036"
+
+[[packages.wheels]]
+name = "charset_normalizer-3.5.2-py3-none-any.whl"
+upload-time = 2026-09-30 04:39:21.828049+00:00
+url = "https://files.pythonhosted.org/packages/fc/ad/d07d7862a62ffa6d79d68074d14823243dd235a77c45262acbf6adeb28bf/charset_normalizer-3.5.2-py3-none-any.whl"
+size = 68872
+
+[packages.wheels.hashes]
+sha256 = "b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685"
+
+[[packages]]
+name = "check-manifest"
+version = "0.51"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.8"
+dependencies = [
+ { name = "build" },
+ { name = "setuptools" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "check_manifest-0.51.tar.gz"
+upload-time = 2025-10-15 11:15:48.007179+00:00
+url = "https://files.pythonhosted.org/packages/16/e3/8ce797dfdf12d447683490107c4dcd97bb2535d7a2b031bf3f3e4c441c3d/check_manifest-0.51.tar.gz"
+size = 36302
+
+[packages.sdist.hashes]
+sha256 = "9801c7637675755a563f33e3c48ee59a59b37a7677297c05c910c16c5b9b6d67"
+
+[[packages.wheels]]
+name = "check_manifest-0.51-py3-none-any.whl"
+upload-time = 2025-10-15 11:15:46.058910+00:00
+url = "https://files.pythonhosted.org/packages/02/c1/df01ef6ba1c8a2bfc201be45d0889b06f165008b240e8d1657aa665421a8/check_manifest-0.51-py3-none-any.whl"
+size = 20500
+
+[packages.wheels.hashes]
+sha256 = "f5f35ed561012fc2115bb070e42a748ac2e034cf8904ab4dfaae893859085ca4"
+
+[[packages]]
+name = "click"
+version = "8.5.0"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.10"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "click-8.5.0.tar.gz"
+upload-time = 2026-08-26 13:33:14.560531+00:00
+url = "https://files.pythonhosted.org/packages/c7/0e/7fa0ef50764b67090eca4114772a2abf8b6148198475e54c660b97caeee6/click-8.5.0.tar.gz"
+size = 382235
+
+[packages.sdist.hashes]
+sha256 = "ba0d2089de75ea0310e2dde03160e6ca10009947fb95a182f9b54021bb272e34"
+
+[[packages.wheels]]
+name = "click-8.5.0-py3-none-any.whl"
+upload-time = 2026-08-26 13:33:12.928043+00:00
+url = "https://files.pythonhosted.org/packages/58/50/6c0d534c5f134586a8e1ba4e330569e32f057e33372ae556463212fb4cd3/click-8.5.0-py3-none-any.whl"
+size = 125251
+
+[packages.wheels.hashes]
+sha256 = "255bc9599cf7748b4b1a446ccc735421bd08a2ae529a8b88597d3de5664ee360"
+
+[[packages]]
+name = "colorama"
+version = "0.4.6"
+marker = "\"project-runtime\" in dependency_groups and sys_platform == \"win32\""
+requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "colorama-0.4.6.tar.gz"
+upload-time = 2022-10-25 02:36:22.414799+00:00
+url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz"
+size = 27697
+
+[packages.sdist.hashes]
+sha256 = "08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"
+
+[[packages.wheels]]
+name = "colorama-0.4.6-py2.py3-none-any.whl"
+upload-time = 2022-10-25 02:36:20.889702+00:00
+url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl"
+size = 25335
+
+[packages.wheels.hashes]
+sha256 = "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"
+
+[[packages]]
+name = "defusedxml"
+version = "0.7.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "defusedxml-0.7.1.tar.gz"
+upload-time = 2021-03-08 10:59:26.269532+00:00
+url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz"
+size = 75520
+
+[packages.sdist.hashes]
+sha256 = "1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"
+
+[[packages.wheels]]
+name = "defusedxml-0.7.1-py2.py3-none-any.whl"
+upload-time = 2021-03-08 10:59:24.450195+00:00
+url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl"
+size = 25604
+
+[packages.wheels.hashes]
+sha256 = "a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"
+
+[[packages]]
+name = "devpi-client"
+version = "7.3.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7"
+dependencies = [
+ { name = "build" },
+ { name = "check-manifest" },
+ { name = "colorama" },
+ { name = "devpi-common" },
+ { name = "iniconfig" },
+ { name = "pkginfo" },
+ { name = "platformdirs" },
+ { name = "pluggy" },
+ { name = "requests" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "devpi_client-7.3.0.tar.gz"
+upload-time = 2026-04-30 11:13:38.167356+00:00
+url = "https://files.pythonhosted.org/packages/14/52/48baa46cc2cbc91bfd7df9533266e8969adbc3b83ad2983c0cee973d9674/devpi_client-7.3.0.tar.gz"
+size = 97522
+
+[packages.sdist.hashes]
+sha256 = "03eda8adb28c2974de00bfd7186ad5a978e46adaca7bc957231f2dfa489abec7"
+
+[[packages.wheels]]
+name = "devpi_client-7.3.0-py3-none-any.whl"
+upload-time = 2026-04-30 11:13:36.615301+00:00
+url = "https://files.pythonhosted.org/packages/b3/64/2781d58acea82a4ff8956ba6d7633e71f1facbf0a20717bd62e62cf5fa82/devpi_client-7.3.0-py3-none-any.whl"
+size = 46648
+
+[packages.wheels.hashes]
+sha256 = "fa51a27eb0f98415426dc3d2488006345701441f8e7ad5d170b5c674c2910492"
+
+[[packages]]
+name = "devpi-common"
+version = "4.1.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7"
+dependencies = [
+ { name = "lazy" },
+ { name = "packaging-legacy" },
+ { name = "requests" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "devpi_common-4.1.1.tar.gz"
+upload-time = 2026-02-09 12:18:40.829086+00:00
+url = "https://files.pythonhosted.org/packages/fb/86/744e5756d6bf7721333a9aa1470269e14a3b345f89f4641e9032a8f0567d/devpi_common-4.1.1.tar.gz"
+size = 25851
+
+[packages.sdist.hashes]
+sha256 = "a413dcc9d1cb6430ff09c7f4e0d76b39910fb5b3419882d78384c3e0fb785931"
+
+[[packages.wheels]]
+name = "devpi_common-4.1.1-py3-none-any.whl"
+upload-time = 2026-02-09 12:18:38.842640+00:00
+url = "https://files.pythonhosted.org/packages/60/ac/e2ccd03a92280f42181b806bda590519dd3c16237fddf9a51d18d8fc5e2b/devpi_common-4.1.1-py3-none-any.whl"
+size = 16735
+
+[packages.wheels.hashes]
+sha256 = "8fda7e8965d3744b1184d6c426fd5caf1345ed74513db687beeb5ee0e63a675c"
+
+[[packages]]
+name = "devpi-server"
+version = "6.20.3"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.9"
+dependencies = [
+ { name = "argon2-cffi" },
+ { name = "attrs" },
+ { name = "defusedxml" },
+ { name = "devpi-common" },
+ { name = "httpx" },
+ { name = "itsdangerous" },
+ { name = "lazy" },
+ { name = "legacy-cgi" },
+ { name = "passlib" },
+ { name = "platformdirs" },
+ { name = "pluggy" },
+ { name = "py" },
+ { name = "pyramid" },
+ { name = "repoze-lru" },
+ { name = "requests" },
+ { name = "ruamel-yaml" },
+ { name = "setuptools" },
+ { name = "strictyaml" },
+ { name = "waitress" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "devpi_server-6.20.3.tar.gz"
+upload-time = 2026-06-30 18:49:37.223031+00:00
+url = "https://files.pythonhosted.org/packages/3b/7f/c1e727cc26a522d28c6e8693f2d05f84d35f251f0fcb945fe4bfb2b246b5/devpi_server-6.20.3.tar.gz"
+size = 310390
+
+[packages.sdist.hashes]
+sha256 = "8307fe955288b85d591168add03a8a9fd377e730f5602d60b71a1abc116200d7"
+
+[[packages.wheels]]
+name = "devpi_server-6.20.3-py3-none-any.whl"
+upload-time = 2026-06-30 18:49:35.275036+00:00
+url = "https://files.pythonhosted.org/packages/f7/ee/1cf7c78e111a4717ce69efb8588c178ac4d7477c93a7dc20170f68e54504/devpi_server-6.20.3-py3-none-any.whl"
+size = 323472
+
+[packages.wheels.hashes]
+sha256 = "4cdc372ce695ad45c7e5eb20f5eaf7e50fd5abe1991db3700f0e68b26e406e67"
+
+[[packages]]
+name = "docutils"
+version = "0.23"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "docutils-0.23.tar.gz"
+upload-time = 2026-05-27 17:41:06.934109+00:00
+url = "https://files.pythonhosted.org/packages/39/a4/5180d9afc57e8fca05601dd652bdff19604c218814037fe90ffc7625a50a/docutils-0.23.tar.gz"
+size = 2303823
+
+[packages.sdist.hashes]
+sha256 = "746f5060322511280a1e50eb76846ed6bf2342984b2ac04dc42caa1a8d78799e"
+
+[[packages.wheels]]
+name = "docutils-0.23-py3-none-any.whl"
+upload-time = 2026-05-27 17:40:58.442528+00:00
+url = "https://files.pythonhosted.org/packages/32/91/30151a39f7570f448ed84529390628a651d7f27c87d73c9b887f8189695e/docutils-0.23-py3-none-any.whl"
+size = 634701
+
+[packages.wheels.hashes]
+sha256 = "25d013af9bf23bc1c7b2b093dff4208166c53a94786c9e447808335ef1185fea"
+
+[[packages]]
+name = "h11"
+version = "0.16.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.8"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "h11-0.16.0.tar.gz"
+upload-time = 2025-04-24 03:35:25.427659+00:00
+url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz"
+size = 101250
+
+[packages.sdist.hashes]
+sha256 = "4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"
+
+[[packages.wheels]]
+name = "h11-0.16.0-py3-none-any.whl"
+upload-time = 2025-04-24 03:35:24.344199+00:00
+url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl"
+size = 37515
+
+[packages.wheels.hashes]
+sha256 = "63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"
+
+[[packages]]
+name = "hatch-fancy-pypi-readme"
+version = "25.1.0"
+marker = "\"build\" in dependency_groups"
+requires-python = ">=3.8"
+dependencies = [
+ { name = "hatchling" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "hatch_fancy_pypi_readme-25.1.0.tar.gz"
+upload-time = 2025-05-01 10:34:42.989334+00:00
+url = "https://files.pythonhosted.org/packages/f3/0f/aed57c301f339936eb91cb4d8c1e5088a101081854bd3ec18a889df32365/hatch_fancy_pypi_readme-25.1.0.tar.gz"
+size = 29701
+
+[packages.sdist.hashes]
+sha256 = "9c58ed3dff90d51f43414ce37009ad1d5b0f08ffc9fc216998a06380f01c0045"
+
+[[packages.wheels]]
+name = "hatch_fancy_pypi_readme-25.1.0-py3-none-any.whl"
+upload-time = 2025-05-01 10:34:41.204793+00:00
+url = "https://files.pythonhosted.org/packages/58/b4/ad71e051b34f1935783de37beffee16e343ff2514b204dc515f9e939d4af/hatch_fancy_pypi_readme-25.1.0-py3-none-any.whl"
+size = 10046
+
+[packages.wheels.hashes]
+sha256 = "ce0134c40d63d874ac48f48ccc678b8f3b62b8e50e9318520d2bffc752eedaf3"
+
+[[packages]]
+name = "hatch-vcs"
+version = "0.5.0"
+marker = "\"build\" in dependency_groups"
+requires-python = ">=3.9"
+dependencies = [
+ { name = "hatchling" },
+ { name = "setuptools-scm" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "hatch_vcs-0.5.0.tar.gz"
+upload-time = 2025-05-27 05:16:04.490926+00:00
+url = "https://files.pythonhosted.org/packages/6b/b0/4cc743d38adbee9d57d786fa496ed1daadb17e48589b6da8fa55717a0746/hatch_vcs-0.5.0.tar.gz"
+size = 11424
+
+[packages.sdist.hashes]
+sha256 = "0395fa126940340215090c344a2bf4e2a77bcbe7daab16f41b37b98c95809ff9"
+
+[[packages.wheels]]
+name = "hatch_vcs-0.5.0-py3-none-any.whl"
+upload-time = 2025-05-27 05:16:03.184909+00:00
+url = "https://files.pythonhosted.org/packages/5f/48/1f85cee4b7b4f40b9b814b1febbc661bda6ced9649e410a0b74f6e415dd0/hatch_vcs-0.5.0-py3-none-any.whl"
+size = 8507
+
+[packages.wheels.hashes]
+sha256 = "b49677dbdc597460cc22d01b27ab3696f5e16a21ecf2700fb01bc28e1f2a04a7"
+
+[[packages]]
+name = "hatchling"
+version = "1.32.4"
+marker = "\"build\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "packaging" },
+ { name = "pathspec" },
+ { name = "pluggy" },
+ { name = "tomlkit" },
+ { name = "trove-classifiers" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "hatchling-1.32.4.tar.gz"
+upload-time = 2026-09-20 22:48:45.398505+00:00
+url = "https://files.pythonhosted.org/packages/f6/97/b5312f01a8c6daf729a9d272dd442e0c546dbcc630495788786c4b567ed0/hatchling-1.32.4.tar.gz"
+size = 58065
+
+[packages.sdist.hashes]
+sha256 = "c4468f73144c054d2aab4ef0f0378c43b9878bf07f8ffd6b79690e970d375f07"
+
+[[packages.wheels]]
+name = "hatchling-1.32.4-py3-none-any.whl"
+upload-time = 2026-09-20 22:48:44.190681+00:00
+url = "https://files.pythonhosted.org/packages/5f/80/91f51f439c05d4ec4623c22928ce16a938d6d793bf709477830823497859/hatchling-1.32.4-py3-none-any.whl"
+size = 78748
+
+[packages.wheels.hashes]
+sha256 = "08ecf7548fb48205e7f213d70c71e67b8271b7242093dc3f1da578b42c734a2c"
+
+[[packages]]
+name = "httpcore"
+version = "1.0.9"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.8"
+dependencies = [
+ { name = "certifi" },
+ { name = "h11" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "httpcore-1.0.9.tar.gz"
+upload-time = 2025-04-24 22:06:22.219726+00:00
+url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz"
+size = 85484
+
+[packages.sdist.hashes]
+sha256 = "6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"
+
+[[packages.wheels]]
+name = "httpcore-1.0.9-py3-none-any.whl"
+upload-time = 2025-04-24 22:06:20.566605+00:00
+url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl"
+size = 78784
+
+[packages.wheels.hashes]
+sha256 = "2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"
+
+[[packages]]
+name = "httpx"
+version = "0.28.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.8"
+dependencies = [
+ { name = "anyio" },
+ { name = "certifi" },
+ { name = "httpcore" },
+ { name = "idna" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "httpx-0.28.1.tar.gz"
+upload-time = 2024-12-06 15:37:23.222462+00:00
+url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz"
+size = 141406
+
+[packages.sdist.hashes]
+sha256 = "75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"
+
+[[packages.wheels]]
+name = "httpx-0.28.1-py3-none-any.whl"
+upload-time = 2024-12-06 15:37:21.509172+00:00
+url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl"
+size = 73517
+
+[packages.wheels.hashes]
+sha256 = "d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"
+
+[[packages]]
+name = "hupper"
+version = "1.12.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "hupper-1.12.1.tar.gz"
+upload-time = 2024-01-26 09:14:57.294780+00:00
+url = "https://files.pythonhosted.org/packages/bd/e6/bb064537288eee2be97f3e0fcad8e7242bc5bbe9664ae57c7d29b3fa18c2/hupper-1.12.1.tar.gz"
+size = 43231
+
+[packages.sdist.hashes]
+sha256 = "06bf54170ff4ecf4c84ad5f188dee3901173ab449c2608ad05b9bfd6b13e32eb"
+
+[[packages.wheels]]
+name = "hupper-1.12.1-py3-none-any.whl"
+upload-time = 2024-01-26 09:14:55.176326+00:00
+url = "https://files.pythonhosted.org/packages/86/7d/3888833e4f5ea56af4a9935066ec09a83228e533d7b8877f65889d706ee4/hupper-1.12.1-py3-none-any.whl"
+size = 22830
+
+[packages.wheels.hashes]
+sha256 = "e872b959f09d90be5fb615bd2e62de89a0b57efc037bdf9637fb09cdf8552b19"
+
+[[packages]]
+name = "idna"
+version = "3.20"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "idna-3.20.tar.gz"
+upload-time = 2026-09-17 14:11:04.752193+00:00
+url = "https://files.pythonhosted.org/packages/f5/08/8eea9d4b8302028f3abb2c0813953f7aec26d33b7a8960ed760e65ff29fa/idna-3.20.tar.gz"
+size = 216463
+
+[packages.sdist.hashes]
+sha256 = "a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44"
+
+[[packages.wheels]]
+name = "idna-3.20-py3-none-any.whl"
+upload-time = 2026-09-17 14:11:03.168153+00:00
+url = "https://files.pythonhosted.org/packages/58/a2/bb081bab032533a855d44de1d56f8e8426114ff1ba5d1f07a438a0a654f8/idna-3.20-py3-none-any.whl"
+size = 69583
+
+[packages.wheels.hashes]
+sha256 = "ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c"
+
+[[packages]]
+name = "iniconfig"
+version = "2.3.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "iniconfig-2.3.1.tar.gz"
+upload-time = 2026-10-06 22:48:38.076390+00:00
+url = "https://files.pythonhosted.org/packages/01/e1/2069291243c926a2ff1cd706c7f3eeb9b62144bf60f77c9fb9ff2fb26bd3/iniconfig-2.3.1.tar.gz"
+size = 21209
+
+[packages.sdist.hashes]
+sha256 = "67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960"
+
+[[packages.wheels]]
+name = "iniconfig-2.3.1-py3-none-any.whl"
+upload-time = 2026-10-06 22:48:36.959685+00:00
+url = "https://files.pythonhosted.org/packages/56/43/4ca9e49d27a1fcf6bece6f6aec0ea46bb9112489b93d4b688fb415457bdb/iniconfig-2.3.1-py3-none-any.whl"
+size = 7552
+
+[packages.wheels.hashes]
+sha256 = "9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7"
+
+[[packages]]
+name = "itsdangerous"
+version = "2.2.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.8"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "itsdangerous-2.2.0.tar.gz"
+upload-time = 2024-04-16 21:28:15.614771+00:00
+url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz"
+size = 54410
+
+[packages.sdist.hashes]
+sha256 = "e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"
+
+[[packages.wheels]]
+name = "itsdangerous-2.2.0-py3-none-any.whl"
+upload-time = 2024-04-16 21:28:14.499616+00:00
+url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl"
+size = 16234
+
+[packages.wheels.hashes]
+sha256 = "c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"
+
+[[packages]]
+name = "jinja2"
+version = "3.1.6"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.7"
+dependencies = [
+ { name = "markupsafe" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "jinja2-3.1.6.tar.gz"
+upload-time = 2025-03-05 20:05:02.478302+00:00
+url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz"
+size = 245115
+
+[packages.sdist.hashes]
+sha256 = "0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"
+
+[[packages.wheels]]
+name = "jinja2-3.1.6-py3-none-any.whl"
+upload-time = 2025-03-05 20:05:00.369721+00:00
+url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl"
+size = 134899
+
+[packages.wheels.hashes]
+sha256 = "85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"
+
+[[packages]]
+name = "lazy"
+version = "2.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.5"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "lazy-2.0.tar.gz"
+upload-time = 2026-07-04 15:50:01.984793+00:00
+url = "https://files.pythonhosted.org/packages/c3/4a/e1204ed0cdf2feb50768e638fda3e97363f362c9a10123c585d5056af556/lazy-2.0.tar.gz"
+size = 10602
+
+[packages.sdist.hashes]
+sha256 = "f92ec0d32dd6bd115ddec4e3323473ebc0b682ad58c6aca78ebfd9e6d1aa5777"
+
+[[packages.wheels]]
+name = "lazy-2.0-py3-none-any.whl"
+upload-time = 2026-07-04 15:50:00.800146+00:00
+url = "https://files.pythonhosted.org/packages/31/82/11dc927238558638dcabc59b37c398ca3e1c0db935e2539d7e710e515aa0/lazy-2.0-py3-none-any.whl"
+size = 5274
+
+[packages.wheels.hashes]
+sha256 = "6bf06f6a71dbe6148f3948c6388b264772493972ad22fb958d24bb52e7e7ec9b"
+
+[[packages]]
+name = "legacy-cgi"
+version = "2.6.4"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.8"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "legacy_cgi-2.6.4.tar.gz"
+upload-time = 2025-10-27 05:20:05.395452+00:00
+url = "https://files.pythonhosted.org/packages/f4/9c/91c7d2c5ebbdf0a1a510bfa0ddeaa2fbb5b78677df5ac0a0aa51cf7125b0/legacy_cgi-2.6.4.tar.gz"
+size = 24603
+
+[packages.sdist.hashes]
+sha256 = "abb9dfc7835772f7c9317977c63253fd22a7484b5c9bbcdca60a29dcce97c577"
+
+[[packages.wheels]]
+name = "legacy_cgi-2.6.4-py3-none-any.whl"
+upload-time = 2025-10-27 05:20:04.289906+00:00
+url = "https://files.pythonhosted.org/packages/8c/7e/e7394eeb49a41cc514b3eb49020223666cbf40d86f5721c2f07871e6d84a/legacy_cgi-2.6.4-py3-none-any.whl"
+size = 20035
+
+[packages.wheels.hashes]
+sha256 = "7e235ce58bf1e25d1fc9b2d299015e4e2cd37305eccafec1e6bac3fc04b878cd"
+
+[[packages]]
+name = "markdown-it-py"
+version = "4.2.0"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "mdurl" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "markdown_it_py-4.2.0.tar.gz"
+upload-time = 2026-05-07 12:08:28.360612+00:00
+url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz"
+size = 82454
+
+[packages.sdist.hashes]
+sha256 = "04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49"
+
+[[packages.wheels]]
+name = "markdown_it_py-4.2.0-py3-none-any.whl"
+upload-time = 2026-05-07 12:08:27.182789+00:00
+url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl"
+size = 91687
+
+[packages.wheels.hashes]
+sha256 = "9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a"
+
+[[packages]]
+name = "markupsafe"
+version = "3.0.4"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "markupsafe-3.0.4.tar.gz"
+upload-time = 2026-10-02 23:07:22.290270+00:00
+url = "https://files.pythonhosted.org/packages/38/9b/e422a865e1d5d57d0e509b4e0bf1c1a70a7f6382c29a5aa428df994c8bc8/markupsafe-3.0.4.tar.gz"
+size = 153777
+
+[packages.sdist.hashes]
+sha256 = "2e9ad7dd851bf45fab9f75cbff4cb493fee9979e8d8c7c9c3ee119022518edd6"
+
+[[packages.wheels]]
+name = "markupsafe-3.0.4-cp315-cp315-macosx_11_0_arm64.whl"
+upload-time = 2026-10-02 23:06:17.855823+00:00
+url = "https://files.pythonhosted.org/packages/96/24/3ec292b44064c16229e064d770b2625bd8ea941aa61f44905a9fa44942c0/markupsafe-3.0.4-cp315-cp315-macosx_11_0_arm64.whl"
+size = 12075
+
+[packages.wheels.hashes]
+sha256 = "ae9dcb8fbe244cb82f8a6458b455b927a03685e383d9bacf1ea5ce180b96dc97"
+
+[[packages.wheels]]
+name = "markupsafe-3.0.4-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl"
+upload-time = 2026-10-02 23:06:18.963942+00:00
+url = "https://files.pythonhosted.org/packages/aa/85/b64fdb1f304848518742136983c24e96d967bfb59a0ea160e92736901ab0/markupsafe-3.0.4-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl"
+size = 24656
+
+[packages.wheels.hashes]
+sha256 = "4bced6e2a6dba6a28f7dd3c6ce14df1b2dd495923f16ea484cad03decd463b2b"
+
+[[packages.wheels]]
+name = "markupsafe-3.0.4-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl"
+upload-time = 2026-10-02 23:06:22.524416+00:00
+url = "https://files.pythonhosted.org/packages/82/96/ef49135ce260db4ca4a12b119ed468449cd248db6b1468e2112b546d7a2e/markupsafe-3.0.4-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl"
+size = 23111
+
+[packages.wheels.hashes]
+sha256 = "925f929d6b59a8b3f8b8c6ac363cd0af7eecc81efb3071770b3c6717c450a369"
+
+[[packages.wheels]]
+name = "markupsafe-3.0.4-cp315-cp315-win_amd64.whl"
+upload-time = 2026-10-02 23:06:33.258900+00:00
+url = "https://files.pythonhosted.org/packages/5b/ec/6000fd82e8791e58fcd0456ec20f098957e2b03d5ed02eb73241a577c0ba/markupsafe-3.0.4-cp315-cp315-win_amd64.whl"
+size = 14496
+
+[packages.wheels.hashes]
+sha256 = "d882a373d8093c2941e01291b7ced96e9cbe4781da9a7751ca7e6c70385e5214"
+
+[[packages]]
+name = "mdformat"
+version = "1.0.0"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "markdown-it-py" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "mdformat-1.0.0.tar.gz"
+upload-time = 2025-10-16 12:05:03.695033+00:00
+url = "https://files.pythonhosted.org/packages/3f/05/32b5e14b192b0a8a309f32232c580aefedd9d06017cb8fe8fce34bec654c/mdformat-1.0.0.tar.gz"
+size = 56953
+
+[packages.sdist.hashes]
+sha256 = "4954045fcae797c29f86d4ad879e43bb151fa55dbaf74ac6eaeacf1d45bb3928"
+
+[[packages.wheels]]
+name = "mdformat-1.0.0-py3-none-any.whl"
+upload-time = 2025-10-16 12:05:02.607432+00:00
+url = "https://files.pythonhosted.org/packages/54/9a/8fe71b95985ca7a4001effbcc58e5a07a1f2a2884203f74dcf48a3b08315/mdformat-1.0.0-py3-none-any.whl"
+size = 53288
+
+[packages.wheels.hashes]
+sha256 = "bca015d65a1d063a02e885a91daee303057bc7829c2cd37b2075a50dbb65944b"
+
+[[packages]]
+name = "mdformat-gfm"
+version = "1.0.0"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "markdown-it-py" },
+ { name = "mdformat" },
+ { name = "mdit-py-plugins" },
+ { name = "wcwidth" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "mdformat_gfm-1.0.0.tar.gz"
+upload-time = 2025-10-16 09:12:22.402429+00:00
+url = "https://files.pythonhosted.org/packages/56/6f/a626ebb142a290474401b67e2d61e73ce096bf7798ee22dfe6270f924b3f/mdformat_gfm-1.0.0.tar.gz"
+size = 10112
+
+[packages.sdist.hashes]
+sha256 = "d1d49a409a6acb774ce7635c72d69178df7dce1dc8cdd10e19f78e8e57b72623"
+
+[[packages.wheels]]
+name = "mdformat_gfm-1.0.0-py3-none-any.whl"
+upload-time = 2025-10-16 09:12:21.276157+00:00
+url = "https://files.pythonhosted.org/packages/e6/18/6bc2189b744dd383cad03764f41f30352b1278d2205096f77a29c0b327ad/mdformat_gfm-1.0.0-py3-none-any.whl"
+size = 10970
+
+[packages.wheels.hashes]
+sha256 = "7305a50efd2a140d7c83505b58e3ac5df2b09e293f9bbe72f6c7bee8c678b005"
+
+[[packages]]
+name = "mdit-py-plugins"
+version = "0.6.1"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "markdown-it-py" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "mdit_py_plugins-0.6.1.tar.gz"
+upload-time = 2026-05-13 09:03:38.910230+00:00
+url = "https://files.pythonhosted.org/packages/59/fc/f8d0863f8862f25602c0404d75568e89fb6b4109804645e5cdfb1be5cf56/mdit_py_plugins-0.6.1.tar.gz"
+size = 56114
+
+[packages.sdist.hashes]
+sha256 = "a2bca0f039f39dbd35fb74ae1b5f998608c437463371f0ff7f49a19a17a114d0"
+
+[[packages.wheels]]
+name = "mdit_py_plugins-0.6.1-py3-none-any.whl"
+upload-time = 2026-05-13 09:03:37.760000+00:00
+url = "https://files.pythonhosted.org/packages/a5/69/6da5581c6a7fede7dc261bf4e67d6adca4196f176b43288b55b3db395b6e/mdit_py_plugins-0.6.1-py3-none-any.whl"
+size = 66663
+
+[packages.wheels.hashes]
+sha256 = "214c82fb2ac524472ab6a5bcab1de80f73b50443e187f401bfd77efbc7c6481d"
+
+[[packages]]
+name = "mdurl"
+version = "0.1.2"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "mdurl-0.1.2.tar.gz"
+upload-time = 2022-08-14 12:40:10.846281+00:00
+url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz"
+size = 8729
+
+[packages.sdist.hashes]
+sha256 = "bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"
+
+[[packages.wheels]]
+name = "mdurl-0.1.2-py3-none-any.whl"
+upload-time = 2022-08-14 12:40:09.779676+00:00
+url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl"
+size = 9979
+
+[packages.wheels.hashes]
+sha256 = "84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"
+
+[[packages]]
+name = "packaging"
+version = "26.3"
+marker = "\"build\" in dependency_groups or \"project-runtime\" in dependency_groups or \"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "packaging-26.3.tar.gz"
+upload-time = 2026-08-04 18:15:28.737071+00:00
+url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz"
+size = 313412
+
+[packages.sdist.hashes]
+sha256 = "94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79"
+
+[[packages.wheels]]
+name = "packaging-26.3-py3-none-any.whl"
+upload-time = 2026-08-04 18:15:27.159957+00:00
+url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl"
+size = 129956
+
+[packages.wheels.hashes]
+sha256 = "d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c"
+
+[[packages]]
+name = "packaging-legacy"
+version = "23.0.post0"
+marker = "\"project-runtime\" in dependency_groups"
+dependencies = [
+ { name = "packaging" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "packaging_legacy-23.0.post0.tar.gz"
+upload-time = 2023-11-28 02:29:56.174861+00:00
+url = "https://files.pythonhosted.org/packages/f8/31/3a2fe3f5fc01a0671ba20560c556b4239b69bfef842a20bba99e3239fd3e/packaging_legacy-23.0.post0.tar.gz"
+size = 8655
+
+[packages.sdist.hashes]
+sha256 = "c974a42291a77112313f0198b87ad96e07a3c357295d572560a4b9c368f7d9db"
+
+[[packages.wheels]]
+name = "packaging_legacy-23.0.post0-py3-none-any.whl"
+upload-time = 2023-11-28 02:29:54.610565+00:00
+url = "https://files.pythonhosted.org/packages/64/3a/cca5260a6e346027495775bef30869acce88d6f72f69ad7c27a0ba87ec95/packaging_legacy-23.0.post0-py3-none-any.whl"
+size = 8216
+
+[packages.wheels.hashes]
+sha256 = "6cd21cd283c09409349bccc10bb55bfd837b4aab86a7b0f87bfcb8dd9831a8a3"
+
+[[packages]]
+name = "passlib"
+version = "1.7.4"
+marker = "\"project-runtime\" in dependency_groups"
+dependencies = [
+ { name = "argon2-cffi" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "passlib-1.7.4.tar.gz"
+upload-time = 2020-10-08 19:00:52.121177+00:00
+url = "https://files.pythonhosted.org/packages/b6/06/9da9ee59a67fae7761aab3ccc84fa4f3f33f125b370f1ccdb915bf967c11/passlib-1.7.4.tar.gz"
+size = 689844
+
+[packages.sdist.hashes]
+sha256 = "defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"
+
+[[packages.wheels]]
+name = "passlib-1.7.4-py2.py3-none-any.whl"
+upload-time = 2020-10-08 19:00:49.856832+00:00
+url = "https://files.pythonhosted.org/packages/3b/a4/ab6b7589382ca3df236e03faa71deac88cae040af60c071a78d254a62172/passlib-1.7.4-py2.py3-none-any.whl"
+size = 525554
+
+[packages.wheels.hashes]
+sha256 = "aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"
+
+[[packages]]
+name = "pastedeploy"
+version = "3.1.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "PasteDeploy-3.1.0.tar.gz"
+upload-time = 2023-11-21 04:54:33.203638+00:00
+url = "https://files.pythonhosted.org/packages/e3/97/0c4a613ec96a54d21daa7e089178263915554320402e89b4e319436a63cb/PasteDeploy-3.1.0.tar.gz"
+size = 37841
+
+[packages.sdist.hashes]
+sha256 = "9ddbaf152f8095438a9fe81f82c78a6714b92ae8e066bed418b6a7ff6a095a95"
+
+[[packages.wheels]]
+name = "PasteDeploy-3.1.0-py3-none-any.whl"
+upload-time = 2023-11-21 04:54:28.226254+00:00
+url = "https://files.pythonhosted.org/packages/85/30/cdddd9a88969683a59222a6d61cd6dce923977f2e9f9ffba38e1324149cd/PasteDeploy-3.1.0-py3-none-any.whl"
+size = 16943
+
+[packages.wheels.hashes]
+sha256 = "76388ad53a661448d436df28c798063108f70e994ddc749540d733cdbd1b38cf"
+
+[[packages]]
+name = "pathspec"
+version = "1.1.1"
+marker = "\"build\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "pathspec-1.1.1.tar.gz"
+upload-time = 2026-04-27 01:46:08.907631+00:00
+url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz"
+size = 135180
+
+[packages.sdist.hashes]
+sha256 = "17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a"
+
+[[packages.wheels]]
+name = "pathspec-1.1.1-py3-none-any.whl"
+upload-time = 2026-04-27 01:46:07.060850+00:00
+url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl"
+size = 57328
+
+[packages.wheels.hashes]
+sha256 = "a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189"
+
+[[packages]]
+name = "pkginfo"
+version = "1.13.3"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "pkginfo-1.13.3.tar.gz"
+upload-time = 2026-10-16 23:15:07.012407+00:00
+url = "https://files.pythonhosted.org/packages/3e/25/5ebd69526479b3684e210f441b05d2d68ce38a4a8c26788bd238cbb0ef54/pkginfo-1.13.3.tar.gz"
+size = 456355
+
+[packages.sdist.hashes]
+sha256 = "ad74cc8184b28b77b06cccc49361fd0fdc56fd87e307425ce1c2b7596dbe3185"
+
+[[packages.wheels]]
+name = "pkginfo-1.13.3-py3-none-any.whl"
+upload-time = 2026-10-16 23:15:05.874130+00:00
+url = "https://files.pythonhosted.org/packages/f3/8f/3e29b55ad92de525931a5683ca245af58d50d5756f35cd74555aaf859427/pkginfo-1.13.3-py3-none-any.whl"
+size = 35615
+
+[packages.wheels.hashes]
+sha256 = "66520cd19fddf3faa9554d68dcc0e6801944275bf612e8b581dfba968a9b4cc9"
+
+[[packages]]
+name = "plaster"
+version = "1.1.2"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "plaster-1.1.2.tar.gz"
+upload-time = 2022-11-21 01:44:54.490549+00:00
+url = "https://files.pythonhosted.org/packages/26/93/66df0f87f1442d8afea8531ae8a4a9eca656006a54eac2b4489427e92c10/plaster-1.1.2.tar.gz"
+size = 33232
+
+[packages.sdist.hashes]
+sha256 = "f8befc54bf8c1147c10ab40297ec84c2676fa2d4ea5d6f524d9436a80074ef98"
+
+[[packages.wheels]]
+name = "plaster-1.1.2-py2.py3-none-any.whl"
+upload-time = 2022-11-21 01:44:52.984107+00:00
+url = "https://files.pythonhosted.org/packages/e7/8b/3f98db1448e3b4d2d142716874a7e02f6101685fdaa0f55a8668e9ffa048/plaster-1.1.2-py2.py3-none-any.whl"
+size = 11554
+
+[packages.wheels.hashes]
+sha256 = "42992ab1f4865f1278e2ad740e8ad145683bb4022e03534265528f0c23c0df2d"
+
+[[packages]]
+name = "plaster-pastedeploy"
+version = "1.0.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7"
+dependencies = [
+ { name = "pastedeploy" },
+ { name = "plaster" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "plaster_pastedeploy-1.0.1.tar.gz"
+upload-time = 2022-11-07 01:23:05.348112+00:00
+url = "https://files.pythonhosted.org/packages/c7/af/01a22f73ce97c6375c88d7ceaf6f5f4f345e940da93c94f98833d898a449/plaster_pastedeploy-1.0.1.tar.gz"
+size = 20915
+
+[packages.sdist.hashes]
+sha256 = "be262e6d2e41a7264875daa2fe2850cbb0615728bcdc92828fdc72736e381412"
+
+[[packages.wheels]]
+name = "plaster_pastedeploy-1.0.1-py2.py3-none-any.whl"
+upload-time = 2022-11-07 01:23:03.230572+00:00
+url = "https://files.pythonhosted.org/packages/bd/30/2d4cf89035c22a89bf0e34dbc50fdc07c42c9bdc90fd972d495257ad2b6e/plaster_pastedeploy-1.0.1-py2.py3-none-any.whl"
+size = 7823
+
+[packages.wheels.hashes]
+sha256 = "ad3550cc744648969ed3b810f33c9344f515ee8d8a8cec18e8f2c4a643c2181f"
+
+[[packages]]
+name = "platformdirs"
+version = "4.13.3"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.11"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "platformdirs-4.13.3.tar.gz"
+upload-time = 2026-10-16 01:16:16.573321+00:00
+url = "https://files.pythonhosted.org/packages/da/91/4a03cfdb03314cfca262921797fff04ff4054bd86a160aed76eddf8aa12b/platformdirs-4.13.3.tar.gz"
+size = 61559
+
+[packages.sdist.hashes]
+sha256 = "5e567f664eb087ab8521c0179cd8d1bd60857d271136567a39719e28e2d383ce"
+
+[[packages.wheels]]
+name = "platformdirs-4.13.3-py3-none-any.whl"
+upload-time = 2026-10-16 01:16:15.051988+00:00
+url = "https://files.pythonhosted.org/packages/45/b8/fd1af06b079af236f5423f7c1821264419cc8f6b4803f79353acbb8bfa53/platformdirs-4.13.3-py3-none-any.whl"
+size = 32762
+
+[packages.wheels.hashes]
+sha256 = "f6ad7f447f24f8a3b82cce5976387428bff894a0eca6c3488f4a17f153c130c4"
+
+[[packages]]
+name = "pluggy"
+version = "1.7.0"
+marker = "\"build\" in dependency_groups or \"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "pluggy-1.7.0.tar.gz"
+upload-time = 2026-10-15 09:50:58.343484+00:00
+url = "https://files.pythonhosted.org/packages/bf/db/7fc19e6f2dc92a966727031389fc2e08b558f0f25eb7403c1119ad4713cd/pluggy-1.7.0.tar.gz"
+size = 123304
+
+[packages.sdist.hashes]
+sha256 = "d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8"
+
+[[packages.wheels]]
+name = "pluggy-1.7.0-py3-none-any.whl"
+upload-time = 2026-10-15 09:50:56.808462+00:00
+url = "https://files.pythonhosted.org/packages/40/9e/2b38731e0fc536806f16490e1a12d7f0dc2a1235aa8cc07bcc75416a7daa/pluggy-1.7.0-py3-none-any.whl"
+size = 27082
+
+[packages.wheels.hashes]
+sha256 = "7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec"
+
+[[packages]]
+name = "prek"
+version = "0.5.5"
+marker = "\"release-check\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.8"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "prek-0.5.5.tar.gz"
+upload-time = 2026-10-05 06:08:59.165911+00:00
+url = "https://files.pythonhosted.org/packages/9b/7b/11538b8e6cd7e269261feae62a2d08818fdcf8f43c3b1a253cec01a5488d/prek-0.5.5.tar.gz"
+size = 570428
+
+[packages.sdist.hashes]
+sha256 = "16bf596768bb754779c7d42317e9ca16ac609c0cce7d13bae0829944ab40a26a"
+
+[[packages.wheels]]
+name = "prek-0.5.5-py3-none-macosx_11_0_arm64.whl"
+upload-time = 2026-10-05 06:08:41.428822+00:00
+url = "https://files.pythonhosted.org/packages/63/ea/fc857c6b3f1e3fdb4d81bdca2051076de82e986cb1455a01b351ac7a5cd1/prek-0.5.5-py3-none-macosx_11_0_arm64.whl"
+size = 5548955
+
+[packages.wheels.hashes]
+sha256 = "2f610927b95e84b28173a4c810892a7b5d5bb55bee792ddf97178fa97654633e"
+
+[[packages.wheels]]
+name = "prek-0.5.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl"
+upload-time = 2026-10-05 06:08:44.051128+00:00
+url = "https://files.pythonhosted.org/packages/47/c3/2bab54f6393fb9f247225681d476086e24fa6242f329e9ca1e5bd638ec50/prek-0.5.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl"
+size = 5848228
+
+[packages.wheels.hashes]
+sha256 = "120ef7d4b6bb58155e74827743c266e48501efb0e4c37ff726b14fe6e86a126b"
+
+[[packages.wheels]]
+name = "prek-0.5.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+upload-time = 2026-10-05 06:08:48.645837+00:00
+url = "https://files.pythonhosted.org/packages/93/fc/e566be5919eaffef4cc22488f16e4bbfd08961734bd67c06f85d405e4cbc/prek-0.5.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
+size = 6269922
+
+[packages.wheels.hashes]
+sha256 = "73d509c0d9556171de2502bada4962be7a25871e7b23e782549074e1416dc850"
+
+[[packages.wheels]]
+name = "prek-0.5.5-py3-none-manylinux_2_28_aarch64.whl"
+upload-time = 2026-10-05 06:08:50.808055+00:00
+url = "https://files.pythonhosted.org/packages/d2/39/a48d8e6203055bff7bb734b1f2f9aede4a4539bee6ab4c9273dbc01fa546/prek-0.5.5-py3-none-manylinux_2_28_aarch64.whl"
+size = 5861518
+
+[packages.wheels.hashes]
+sha256 = "76c867fdbd4e4f19e6b6b2988bd1e1407d1324170ebcf1428e4e34f8f0751a99"
+
+[[packages.wheels]]
+name = "prek-0.5.5-py3-none-win_amd64.whl"
+upload-time = 2026-10-05 06:08:55.056244+00:00
+url = "https://files.pythonhosted.org/packages/8c/04/1e9ccf3a61a3bfd4107b83973f7afde9177b6ff8f2d5d4b00125e77c2100/prek-0.5.5-py3-none-win_amd64.whl"
+size = 5784759
+
+[packages.wheels.hashes]
+sha256 = "15bff9039349466ea9bf6b0c173b822ff08f8ae4cfbfdea782492e519c06d874"
+
+[[packages]]
+name = "py"
+version = "1.11.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "py-1.11.0.tar.gz"
+upload-time = 2021-11-04 17:17:01.377437+00:00
+url = "https://files.pythonhosted.org/packages/98/ff/fec109ceb715d2a6b4c4a85a61af3b40c723a961e8828319fbcb15b868dc/py-1.11.0.tar.gz"
+size = 207796
+
+[packages.sdist.hashes]
+sha256 = "51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"
+
+[[packages.wheels]]
+name = "py-1.11.0-py2.py3-none-any.whl"
+upload-time = 2021-11-04 17:17:00.152107+00:00
+url = "https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl"
+size = 98708
+
+[packages.wheels.hashes]
+sha256 = "607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"
+
+[[packages]]
+name = "pycparser"
+version = "3.11"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "pycparser-3.11.tar.gz"
+upload-time = 2026-10-09 12:56:59.539345+00:00
+url = "https://files.pythonhosted.org/packages/da/a8/c5fdbeee588bb8ada9458774f43adf1bdd30bd59157055142183e769a024/pycparser-3.11.tar.gz"
+size = 113796
+
+[packages.sdist.hashes]
+sha256 = "d875f09c3507d00e1aba0eecc6dcadc1352f30fff09dc6bff2f1c2935e97c2bc"
+
+[[packages.wheels]]
+name = "pycparser-3.11-py3-none-any.whl"
+upload-time = 2026-10-09 12:56:58.131173+00:00
+url = "https://files.pythonhosted.org/packages/90/11/0e6f11117525ff0eec40ebac3d313376f102df93ca44ad9e893ee85e4f89/pycparser-3.11-py3-none-any.whl"
+size = 51178
+
+[packages.wheels.hashes]
+sha256 = "51d5a8ba2be0bbe440b99d2112604c95bbbc3c2748a64260186c541e1729cd80"
+
+[[packages]]
+name = "pyproject-hooks"
+version = "1.3.3"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.8"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "pyproject_hooks-1.3.3.tar.gz"
+upload-time = 2026-09-16 08:58:03.999217+00:00
+url = "https://files.pythonhosted.org/packages/6d/5d/f2ddeef4a855a102aaae5e97826a0260007522ab504421b75addfdb1517c/pyproject_hooks-1.3.3.tar.gz"
+size = 21013
+
+[packages.sdist.hashes]
+sha256 = "defda19b854fa0d3bd4f76ea4ddcba8abd7dcfcdd585a6690ade050744fc5f43"
+
+[[packages.wheels]]
+name = "pyproject_hooks-1.3.3-py3-none-any.whl"
+upload-time = 2026-09-16 08:58:02.960279+00:00
+url = "https://files.pythonhosted.org/packages/85/11/044d1ae1b4ec0d7af88ee5bc91e081be1022533032b906a7bdabdbb60977/pyproject_hooks-1.3.3-py3-none-any.whl"
+size = 10724
+
+[packages.wheels.hashes]
+sha256 = "5fc53fdac9f7bd63fbcdc868fb5f90b4784d78a53a3d3388cd738b807441a20b"
+
+[[packages]]
+name = "pyramid"
+version = "2.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "hupper" },
+ { name = "plaster" },
+ { name = "plaster-pastedeploy" },
+ { name = "setuptools" },
+ { name = "translationstring" },
+ { name = "venusian" },
+ { name = "webob" },
+ { name = "zope-deprecation" },
+ { name = "zope-interface" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "pyramid-2.1.tar.gz"
+upload-time = 2026-03-11 01:23:59.642857+00:00
+url = "https://files.pythonhosted.org/packages/7e/f3/05b49d8bbc6f4592f8820d9e306e20b0b4c266171f3455c737c49b4a7338/pyramid-2.1.tar.gz"
+size = 2628991
+
+[packages.sdist.hashes]
+sha256 = "5a24bc1b5f9e0f0d1c0b6ddd1111e84c15dac44a07e3c1d24e74dd9bb4fc22eb"
+
+[[packages.wheels]]
+name = "pyramid-2.1-py3-none-any.whl"
+upload-time = 2026-03-11 01:23:56.896701+00:00
+url = "https://files.pythonhosted.org/packages/1f/d4/03a8f9b60b8f2a9198c962d08fd9b657c1c0797cbbde3793babbad200845/pyramid-2.1-py3-none-any.whl"
+size = 243407
+
+[packages.wheels.hashes]
+sha256 = "0aa62604221f6a8ac6e77a0faa02a5b7a294d6675f15581d8d416dffe2ac98e7"
+
+[[packages]]
+name = "python-dateutil"
+version = "2.9.0.post0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+dependencies = [
+ { name = "six" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "python-dateutil-2.9.0.post0.tar.gz"
+upload-time = 2024-03-01 18:36:20.211056+00:00
+url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz"
+size = 342432
+
+[packages.sdist.hashes]
+sha256 = "37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"
+
+[[packages.wheels]]
+name = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl"
+upload-time = 2024-03-01 18:36:18.570437+00:00
+url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl"
+size = 229892
+
+[packages.wheels.hashes]
+sha256 = "a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"
+
+[[packages]]
+name = "pyyaml"
+version = "6.0.3"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.8"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "pyyaml-6.0.3.tar.gz"
+upload-time = 2025-09-25 21:33:16.546886+00:00
+url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz"
+size = 130960
+
+[packages.sdist.hashes]
+sha256 = "d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"
+
+[[packages]]
+name = "release-creator"
+version = "1.0.0"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.15"
+dependencies = [
+ { name = "docutils" },
+ { name = "markdown-it-py" },
+ { name = "mdformat" },
+ { name = "mdformat-gfm" },
+ { name = "packaging" },
+ { name = "pyyaml" },
+ { name = "towncrier" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "release_creator-1.0.0.tar.gz"
+upload-time = 2026-10-24 06:07:45.789370+00:00
+url = "https://files.pythonhosted.org/packages/e2/92/dfc1c6e8f52d50d91a05f77f67592c2408cabd9d96079fedbe551f24530d/release_creator-1.0.0.tar.gz"
+size = 134186
+
+[packages.sdist.hashes]
+sha256 = "1174e3a3fd39e9117eb9c34e3fbc58a8e32c49f5f65d01f39195231b967807f6"
+
+[[packages.wheels]]
+name = "release_creator-1.0.0-py3-none-any.whl"
+upload-time = 2026-10-24 06:07:44.366184+00:00
+url = "https://files.pythonhosted.org/packages/6a/17/b1cd851932786f3e9e9f2187d150bc0860e04adf76cbfd45e6531715bf97/release_creator-1.0.0-py3-none-any.whl"
+size = 53396
+
+[packages.wheels.hashes]
+sha256 = "613a26a0d1b0042d9dad60dfc00f3e78208d84ab9f78cec792a407b6a0a75c24"
+
+[[packages]]
+name = "repoze-lru"
+version = "0.8"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "repoze_lru-0.8.tar.gz"
+upload-time = 2026-05-16 16:57:28.315222+00:00
+url = "https://files.pythonhosted.org/packages/b5/19/727d5c904ea513a6a9044bf43beaa2c5e632e017b1e0ab71e9d111d20967/repoze_lru-0.8.tar.gz"
+size = 22169
+
+[packages.sdist.hashes]
+sha256 = "a252408cd93fe670c88d6665b96fe5d42e071dba2507a1f21a1e609ae4fa891a"
+
+[[packages.wheels]]
+name = "repoze_lru-0.8-py3-none-any.whl"
+upload-time = 2026-05-16 16:57:27.257891+00:00
+url = "https://files.pythonhosted.org/packages/6f/a1/cc0848069e3937651582c74db0fdddda96f853060a25617754a264913afe/repoze_lru-0.8-py3-none-any.whl"
+size = 6379
+
+[packages.wheels.hashes]
+sha256 = "979a30d2e567e31f292009ba4467aa444c89ee0da3e3013980c35f1fb4f19d99"
+
+[[packages]]
+name = "requests"
+version = "2.34.2"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+dependencies = [
+ { name = "certifi" },
+ { name = "charset-normalizer" },
+ { name = "idna" },
+ { name = "urllib3" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "requests-2.34.2.tar.gz"
+upload-time = 2026-05-14 19:25:27.735762+00:00
+url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz"
+size = 142856
+
+[packages.sdist.hashes]
+sha256 = "f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed"
+
+[[packages.wheels]]
+name = "requests-2.34.2-py3-none-any.whl"
+upload-time = 2026-05-14 19:25:26.443000+00:00
+url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl"
+size = 73075
+
+[packages.wheels.hashes]
+sha256 = "2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0"
+
+[[packages]]
+name = "ruamel-yaml"
+version = "0.19.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "ruamel_yaml-0.19.1.tar.gz"
+upload-time = 2026-01-02 16:50:31.840645+00:00
+url = "https://files.pythonhosted.org/packages/c7/3b/ebda527b56beb90cb7652cb1c7e4f91f48649fbcd8d2eb2fb6e77cd3329b/ruamel_yaml-0.19.1.tar.gz"
+size = 142709
+
+[packages.sdist.hashes]
+sha256 = "53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993"
+
+[[packages.wheels]]
+name = "ruamel_yaml-0.19.1-py3-none-any.whl"
+upload-time = 2026-01-02 16:50:29.201949+00:00
+url = "https://files.pythonhosted.org/packages/b8/0c/51f6841f1d84f404f92463fc2b1ba0da357ca1e3db6b7fbda26956c3b82a/ruamel_yaml-0.19.1-py3-none-any.whl"
+size = 118102
+
+[packages.wheels.hashes]
+sha256 = "27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93"
+
+[[packages]]
+name = "setuptools"
+version = "81.0.0"
+marker = "\"build\" in dependency_groups or \"project-runtime\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "setuptools-81.0.0.tar.gz"
+upload-time = 2026-02-06 21:10:39.601535+00:00
+url = "https://files.pythonhosted.org/packages/0d/1c/73e719955c59b8e424d015ab450f51c0af856ae46ea2da83eba51cc88de1/setuptools-81.0.0.tar.gz"
+size = 1198299
+
+[packages.sdist.hashes]
+sha256 = "487b53915f52501f0a79ccfd0c02c165ffe06631443a886740b91af4b7a5845a"
+
+[[packages.wheels]]
+name = "setuptools-81.0.0-py3-none-any.whl"
+upload-time = 2026-02-06 21:10:37.175649+00:00
+url = "https://files.pythonhosted.org/packages/e1/e3/c164c88b2e5ce7b24d667b9bd83589cf4f3520d97cad01534cd3c4f55fdb/setuptools-81.0.0-py3-none-any.whl"
+size = 1062021
+
+[packages.wheels.hashes]
+sha256 = "fdd925d5c5d9f62e4b74b30d6dd7828ce236fd6ed998a08d81de62ce5a6310d6"
+
+[[packages]]
+name = "setuptools-scm"
+version = "10.3.4"
+marker = "\"build\" in dependency_groups"
+requires-python = ">=3.8"
+dependencies = [
+ { name = "packaging" },
+ { name = "setuptools" },
+ { name = "vcs-versioning" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "setuptools_scm-10.3.4.tar.gz"
+upload-time = 2026-09-23 19:21:42.950372+00:00
+url = "https://files.pythonhosted.org/packages/85/d8/fc143f88819ccf10ba2388ba86732ee2de193e578234e25a783f6cc14bf7/setuptools_scm-10.3.4.tar.gz"
+size = 78410
+
+[packages.sdist.hashes]
+sha256 = "a69f28bfc245608781205e912faae437c2b2165773afa4e7b979d77447a69dd2"
+
+[[packages.wheels]]
+name = "setuptools_scm-10.3.4-py3-none-any.whl"
+upload-time = 2026-09-23 19:21:41.607429+00:00
+url = "https://files.pythonhosted.org/packages/da/f5/54538a1f17ea753c42b0928dc2e62986d463f8c393340b9a1e602f2d4dd9/setuptools_scm-10.3.4-py3-none-any.whl"
+size = 33366
+
+[packages.wheels.hashes]
+sha256 = "82f34c3e3084fc2b57d397200637cc13f2338004052d2fee47baa5f0e902464e"
+
+[[packages]]
+name = "six"
+version = "1.17.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "six-1.17.0.tar.gz"
+upload-time = 2024-12-04 17:35:28.174320+00:00
+url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz"
+size = 34031
+
+[packages.sdist.hashes]
+sha256 = "ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"
+
+[[packages.wheels]]
+name = "six-1.17.0-py2.py3-none-any.whl"
+upload-time = 2024-12-04 17:35:26.475808+00:00
+url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl"
+size = 11050
+
+[packages.wheels.hashes]
+sha256 = "4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"
+
+[[packages]]
+name = "strictyaml"
+version = "1.7.3"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7.0"
+dependencies = [
+ { name = "python-dateutil" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "strictyaml-1.7.3.tar.gz"
+upload-time = 2023-03-10 12:50:27.062960+00:00
+url = "https://files.pythonhosted.org/packages/b3/08/efd28d49162ce89c2ad61a88bd80e11fb77bc9f6c145402589112d38f8af/strictyaml-1.7.3.tar.gz"
+size = 115206
+
+[packages.sdist.hashes]
+sha256 = "22f854a5fcab42b5ddba8030a0e4be51ca89af0267961c8d6cfa86395586c407"
+
+[[packages.wheels]]
+name = "strictyaml-1.7.3-py3-none-any.whl"
+upload-time = 2023-03-10 12:50:17.242713+00:00
+url = "https://files.pythonhosted.org/packages/96/7c/a81ef5ef10978dd073a854e0fa93b5d8021d0594b639cc8f6453c3c78a1d/strictyaml-1.7.3-py3-none-any.whl"
+size = 123917
+
+[packages.wheels.hashes]
+sha256 = "fb5c8a4edb43bebb765959e420f9b3978d7f1af88c80606c03fb420888f5d1c7"
+
+[[packages]]
+name = "tomlkit"
+version = "0.15.2"
+marker = "\"build\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "tomlkit-0.15.2.tar.gz"
+upload-time = 2026-10-16 04:07:08.166827+00:00
+url = "https://files.pythonhosted.org/packages/08/72/fc01563df95c189a9f65850096bdc205bc2fe37da6c740cd64afaf18d07e/tomlkit-0.15.2.tar.gz"
+size = 190522
+
+[packages.sdist.hashes]
+sha256 = "83e32755ba1d20d9340bd069ee97e9f6232ba2346b63ffcba425de01f7e327a6"
+
+[[packages.wheels]]
+name = "tomlkit-0.15.2-py3-none-any.whl"
+upload-time = 2026-10-16 04:07:09.216014+00:00
+url = "https://files.pythonhosted.org/packages/da/46/7d84138a60a8bd796825b2d38ebe92d0d16501ca57d501b7c5d677401bbc/tomlkit-0.15.2-py3-none-any.whl"
+size = 52225
+
+[packages.wheels.hashes]
+sha256 = "05562412163a3037b94497385fb7f9204c637bc605af7a48199e41cf2272f437"
+
+[[packages]]
+name = "towncrier"
+version = "26.9.0"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.9"
+dependencies = [
+ { name = "click" },
+ { name = "jinja2" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "towncrier-26.9.0.tar.gz"
+upload-time = 2026-09-04 12:57:25.341701+00:00
+url = "https://files.pythonhosted.org/packages/92/d4/e85ce614bf45b1a7fe13b82cc687819c2eaac5a1dd94b84834322095fd98/towncrier-26.9.0.tar.gz"
+size = 79338
+
+[packages.sdist.hashes]
+sha256 = "ace9031631c718cc0709107b8755e6e31350eb8acdc877af43df3177addb9a55"
+
+[[packages.wheels]]
+name = "towncrier-26.9.0-py3-none-any.whl"
+upload-time = 2026-09-04 12:57:23.986160+00:00
+url = "https://files.pythonhosted.org/packages/82/88/f9340b545dafa64de053798e760515a2736fbb60092cf9aa6b146ccf3ede/towncrier-26.9.0-py3-none-any.whl"
+size = 67030
+
+[packages.wheels.hashes]
+sha256 = "ae4d223e6aadaff98d29b7f09e58d9c9ccf4cd3b455a2d2e0486d432cd8bf660"
+
+[[packages]]
+name = "translationstring"
+version = "1.4"
+marker = "\"project-runtime\" in dependency_groups"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "translationstring-1.4.tar.gz"
+upload-time = 2020-07-09 11:58:32.041458+00:00
+url = "https://files.pythonhosted.org/packages/14/39/32325add93da9439775d7fe4b4887eb7986dbc1d5675b0431f4531f560e5/translationstring-1.4.tar.gz"
+size = 24199
+
+[packages.sdist.hashes]
+sha256 = "bf947538d76e69ba12ab17283b10355a9ecfbc078e6123443f43f2107f6376f3"
+
+[[packages.wheels]]
+name = "translationstring-1.4-py2.py3-none-any.whl"
+upload-time = 2020-07-09 11:58:30.995187+00:00
+url = "https://files.pythonhosted.org/packages/3b/98/36187601a15e3d37e9bfcf0e0e1055532b39d044353b06861c3a519737a9/translationstring-1.4-py2.py3-none-any.whl"
+size = 15028
+
+[packages.wheels.hashes]
+sha256 = "5f4dc4d939573db851c8d840551e1a0fb27b946afe3b95aafc22577eed2d6262"
+
+[[packages]]
+name = "trove-classifiers"
+version = "2026.9.21.13"
+marker = "\"build\" in dependency_groups"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "trove_classifiers-2026.9.21.13.tar.gz"
+upload-time = 2026-09-21 13:29:07.301512+00:00
+url = "https://files.pythonhosted.org/packages/bf/93/af436dfaa845cab5d96f0adbc1e4f3730532d37fa249e4eb796fb1d7fc82/trove_classifiers-2026.9.21.13.tar.gz"
+size = 17085
+
+[packages.sdist.hashes]
+sha256 = "0a9ebc8d4e2f3e8a22848c5258033035bec17a3012ac3fea16dbaa764489eb71"
+
+[[packages.wheels]]
+name = "trove_classifiers-2026.9.21.13-py3-none-any.whl"
+upload-time = 2026-09-21 13:29:06.123578+00:00
+url = "https://files.pythonhosted.org/packages/30/81/0da8afb52a71d0a4f2bd3152357b1a441e393b286374802b9d3addab4ab5/trove_classifiers-2026.9.21.13-py3-none-any.whl"
+size = 14232
+
+[packages.wheels.hashes]
+sha256 = "8b1ff4f9c191b1040b71c37f1e445ab99732911e3cd91de52838453a854d7a17"
+
+[[packages]]
+name = "urllib3"
+version = "2.8.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.10"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "urllib3-2.8.0.tar.gz"
+upload-time = 2026-09-15 19:29:36.253420+00:00
+url = "https://files.pythonhosted.org/packages/e3/05/b17359e1cefb4f909b5e40b1b90a496d987258916dbbf88e842c729f510e/urllib3-2.8.0.tar.gz"
+size = 458972
+
+[packages.sdist.hashes]
+sha256 = "63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63"
+
+[[packages.wheels]]
+name = "urllib3-2.8.0-py3-none-any.whl"
+upload-time = 2026-09-15 19:29:34.577402+00:00
+url = "https://files.pythonhosted.org/packages/92/9d/c4e665119135114480843e7ab388fa94d8480650450e6f8e26b70d323a4c/urllib3-2.8.0-py3-none-any.whl"
+size = 135717
+
+[packages.wheels.hashes]
+sha256 = "0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3"
+
+[[packages]]
+name = "vcs-versioning"
+version = "2.6.0"
+marker = "\"build\" in dependency_groups"
+requires-python = ">=3.8"
+dependencies = [
+ { name = "packaging" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "vcs_versioning-2.6.0.tar.gz"
+upload-time = 2026-10-06 22:21:55.024903+00:00
+url = "https://files.pythonhosted.org/packages/ad/e7/2a691db7d076b75d099fdba1a14cd966931f2aeb591e77f6d22f15097326/vcs_versioning-2.6.0.tar.gz"
+size = 166800
+
+[packages.sdist.hashes]
+sha256 = "22e9159288e2d8bca2fa6f6c31c34c9c66aec157f60e9e526f5d160d2516d60f"
+
+[[packages.wheels]]
+name = "vcs_versioning-2.6.0-py3-none-any.whl"
+upload-time = 2026-10-06 22:21:53.267565+00:00
+url = "https://files.pythonhosted.org/packages/73/1d/ad4064bf12f4503bf61e65d74c93c523672776d25ee0a06aaf42ae09ef3f/vcs_versioning-2.6.0-py3-none-any.whl"
+size = 123154
+
+[packages.wheels.hashes]
+sha256 = "f8bebd1302ebc12e67ceb30fc7dd698ec969414b6fa43b30c3f14ac9b1e72c41"
+
+[[packages]]
+name = "venusian"
+version = "3.1.1"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.7"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "venusian-3.1.1.tar.gz"
+upload-time = 2024-12-02 02:35:04.033357+00:00
+url = "https://files.pythonhosted.org/packages/70/4c/eefa68085c555dc11e6744b9c6fbe5966b1c9378c47267776a448923e9a5/venusian-3.1.1.tar.gz"
+size = 39269
+
+[packages.sdist.hashes]
+sha256 = "534fb3b355669283eb3954581931e5d1d071fce61d029d58f3219a5e3a6f0c41"
+
+[[packages.wheels]]
+name = "venusian-3.1.1-py3-none-any.whl"
+upload-time = 2024-12-02 02:35:03.056196+00:00
+url = "https://files.pythonhosted.org/packages/5a/4b/34d926eba40db81b204066a60b4efdc5d8867a8efcbfe44d69b634b1c907/venusian-3.1.1-py3-none-any.whl"
+size = 14026
+
+[packages.wheels.hashes]
+sha256 = "0845808a985976acbceaa1fbb871c7fac4fb28ae75453232970e9c2c2866dbf4"
+
+[[packages]]
+name = "waitress"
+version = "3.0.2"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.9.0"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "waitress-3.0.2.tar.gz"
+upload-time = 2024-11-16 20:02:35.195594+00:00
+url = "https://files.pythonhosted.org/packages/bf/cb/04ddb054f45faa306a230769e868c28b8065ea196891f09004ebace5b184/waitress-3.0.2.tar.gz"
+size = 179901
+
+[packages.sdist.hashes]
+sha256 = "682aaaf2af0c44ada4abfb70ded36393f0e307f4ab9456a215ce0020baefc31f"
+
+[[packages.wheels]]
+name = "waitress-3.0.2-py3-none-any.whl"
+upload-time = 2024-11-16 20:02:33.858165+00:00
+url = "https://files.pythonhosted.org/packages/8d/57/a27182528c90ef38d82b636a11f606b0cbb0e17588ed205435f8affe3368/waitress-3.0.2-py3-none-any.whl"
+size = 56232
+
+[packages.wheels.hashes]
+sha256 = "c56d67fd6e87c2ee598b76abdd4e96cfad1f24cacdea5078d382b1f9d7b5ed2e"
+
+[[packages]]
+name = "wcwidth"
+version = "0.9.2"
+marker = "\"release-news\" in dependency_groups or \"release-notes\" in dependency_groups or \"release-prepare\" in dependency_groups or \"release-validate\" in dependency_groups"
+requires-python = ">=3.9"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "wcwidth-0.9.2.tar.gz"
+upload-time = 2026-10-05 00:24:05.521972+00:00
+url = "https://files.pythonhosted.org/packages/f0/b4/7830542634bb2d3e62aa3b586a72d5b3b6c91c3168929e7000ef3fed041d/wcwidth-0.9.2.tar.gz"
+size = 955039
+
+[packages.sdist.hashes]
+sha256 = "ae0ef90b90f6af38b54f1fe6d58662ec33b3cb4b8391958a62416d654231727b"
+
+[[packages.wheels]]
+name = "wcwidth-0.9.2-cp310-abi3-macosx_11_0_arm64.whl"
+upload-time = 2026-10-05 00:23:27.049292+00:00
+url = "https://files.pythonhosted.org/packages/a0/07/cb6940e81134b7ed25fa312ee9ab536a63db0793b149f88a90e603ceace9/wcwidth-0.9.2-cp310-abi3-macosx_11_0_arm64.whl"
+size = 609960
+
+[packages.wheels.hashes]
+sha256 = "ae0800c5339423cc53d33a266ad264b42ba8aaa16d4464f6e6b1bee607f50b17"
+
+[[packages.wheels]]
+name = "wcwidth-0.9.2-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl"
+upload-time = 2026-10-05 00:23:32.448318+00:00
+url = "https://files.pythonhosted.org/packages/bc/f0/b8ef7758003d66b60f093695831a86dcc726aac01ee6446ffcbda27b61e3/wcwidth-0.9.2-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl"
+size = 771632
+
+[packages.wheels.hashes]
+sha256 = "674b518af28d38ee645ff97b74f5760abee5fad4bac74413bfc4b881ef2ce724"
+
+[[packages.wheels]]
+name = "wcwidth-0.9.2-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"
+upload-time = 2026-10-05 00:23:40.175985+00:00
+url = "https://files.pythonhosted.org/packages/db/6c/f940133c71427c208575910e981942bd78c98b1f7cd0d1425ca4b7457c04/wcwidth-0.9.2-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"
+size = 769763
+
+[packages.wheels.hashes]
+sha256 = "751bef0ab404b6a1dc028b56b4b85d46486be1c55833f80da533e42dc691f389"
+
+[[packages.wheels]]
+name = "wcwidth-0.9.2-cp310-abi3-win_amd64.whl"
+upload-time = 2026-10-05 00:23:57.489330+00:00
+url = "https://files.pythonhosted.org/packages/5a/d6/b0690f55ea0483530a18bac917fbadbf54f35122510446fc370f5f1c2453/wcwidth-0.9.2-cp310-abi3-win_amd64.whl"
+size = 597827
+
+[packages.wheels.hashes]
+sha256 = "2a9746de704242bd4fdaabb31dd46b82f694a56a8d21081ad89b679a89da9fec"
+
+[[packages.wheels]]
+name = "wcwidth-0.9.2-py3-none-any.whl"
+upload-time = 2026-10-05 00:23:21.097514+00:00
+url = "https://files.pythonhosted.org/packages/9c/b4/0bfa065af506540d9d558e3e5548cff00bc1f9b24e6e2a8512498e8628de/wcwidth-0.9.2-py3-none-any.whl"
+size = 301667
+
+[packages.wheels.hashes]
+sha256 = "89ca642c5bf0101157a09366be69fad0379db1f700ae39a920e103234573670e"
+
+[[packages]]
+name = "webob"
+version = "1.8.11"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+dependencies = [
+ { name = "legacy-cgi" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "webob-1.8.11.tar.gz"
+upload-time = 2026-08-02 06:26:26.063871+00:00
+url = "https://files.pythonhosted.org/packages/e6/92/9329872e36be90e25ba616ac6e9ee8c1be4326a1ea3fdffcdabd0eb48efb/webob-1.8.11.tar.gz"
+size = 286047
+
+[packages.sdist.hashes]
+sha256 = "aa8c27231070b135c025e567a9cd7eda03f4df71352ffaac740cb6a75f0f81a5"
+
+[[packages.wheels]]
+name = "webob-1.8.11-py2.py3-none-any.whl"
+upload-time = 2026-08-02 06:26:24.765058+00:00
+url = "https://files.pythonhosted.org/packages/c1/71/370a65bc7726a1cbf478445c898c7affe907aa42e2e9e5bb38319db74115/webob-1.8.11-py2.py3-none-any.whl"
+size = 118319
+
+[packages.wheels.hashes]
+sha256 = "4addd1d38d6a7fbe0eda22d45f25a40d74c8b290f3a99c0ac3d4023cf21f2da2"
+
+[[packages]]
+name = "zope-deprecation"
+version = "6.0"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.9"
+dependencies = [
+ { name = "setuptools" },
+]
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "zope_deprecation-6.0.tar.gz"
+upload-time = 2025-09-12 07:06:06.779436+00:00
+url = "https://files.pythonhosted.org/packages/56/05/8eaa04876e1fde656f1bfd8f62a4140d7ac23bcf16db67dd4036698dae1f/zope_deprecation-6.0.tar.gz"
+size = 24480
+
+[packages.sdist.hashes]
+sha256 = "18727ebda8e63a6d4bd28a290e8b46852e9f14473debb5cc40a0a2dccfadf15f"
+
+[[packages.wheels]]
+name = "zope_deprecation-6.0-py3-none-any.whl"
+upload-time = 2025-09-12 07:06:05.847612+00:00
+url = "https://files.pythonhosted.org/packages/e9/ed/da7f8b1c73caf989a0ff7096cc73c59e6c36f35a8f967c51104098602e2d/zope_deprecation-6.0-py3-none-any.whl"
+size = 9512
+
+[packages.wheels.hashes]
+sha256 = "ff72d51c88b516b9ddf2cfb826381cc49f99a6a89b7d35c97faca7bee3b46da6"
+
+[[packages]]
+name = "zope-interface"
+version = "8.7"
+marker = "\"project-runtime\" in dependency_groups"
+requires-python = ">=3.11"
+index = "https://pypi.org/simple/"
+
+[packages.sdist]
+name = "zope_interface-8.7.tar.gz"
+upload-time = 2026-10-15 07:25:14.851231+00:00
+url = "https://files.pythonhosted.org/packages/de/ff/a1f0021a26033da0df223fd05a7455d6d2881b67daf2c6dc897b4fe0a427/zope_interface-8.7.tar.gz"
+size = 266343
+
+[packages.sdist.hashes]
+sha256 = "0b47b62e8d0d99b24bcdd32f4f2120425e5019c3bee2ad69a0e1d75737487a96"
+
+[[packages.wheels]]
+name = "zope_interface-8.7-cp315-cp315-macosx_11_0_arm64.whl"
+upload-time = 2026-10-15 07:24:50.416265+00:00
+url = "https://files.pythonhosted.org/packages/ad/17/c6ae2f1265a9be806841df2890f2e12cbe16ef6287781ee06db3f4e37cef/zope_interface-8.7-cp315-cp315-macosx_11_0_arm64.whl"
+size = 219360
+
+[packages.wheels.hashes]
+sha256 = "a319373c6fb786f47d816ad16c8bda604438fd4a32ddc77af411d551ec210cd4"
+
+[[packages.wheels]]
+name = "zope_interface-8.7-cp315-cp315-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl"
+upload-time = 2026-10-15 07:24:54.401821+00:00
+url = "https://files.pythonhosted.org/packages/b3/86/9e545fe873140dc61c875f013e0d873ab006ca7f6ace933e6e9fd81d5e45/zope_interface-8.7-cp315-cp315-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl"
+size = 282835
+
+[packages.wheels.hashes]
+sha256 = "a0d84e36c426afb6469aa6c4d438d12e18394ace596f5698f835fc434bd0ae1d"
+
+[[packages.wheels]]
+name = "zope_interface-8.7-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl"
+upload-time = 2026-10-15 07:24:55.926299+00:00
+url = "https://files.pythonhosted.org/packages/6a/54/28590cfa4adcc21d5960c3ab2ed5c651b60c084a6d844c1cbafda57cb6d9/zope_interface-8.7-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl"
+size = 282798
+
+[packages.wheels.hashes]
+sha256 = "39299d2f03fb1eada8ee7f754a834d0a4e9d5421284ed7b0d9ea37a8fa0eb58e"
+
+[[packages.wheels]]
+name = "zope_interface-8.7-cp315-cp315-win_amd64.whl"
+upload-time = 2026-10-15 07:24:57.586532+00:00
+url = "https://files.pythonhosted.org/packages/2b/17/dbfbc44a870f9e87fac9d85d8d48ac49603baf6aaa59898fc7b6c5ca4d08/zope_interface-8.7-cp315-cp315-win_amd64.whl"
+size = 221568
+
+[packages.wheels.hashes]
+sha256 = "10f15d6b70842405755d6ef128d731ff14f2f655bad56b7fe5d19588c24d08bc"
+
+[tool.nab]
+nab-version = "0.0.22"
+created-at = 2026-10-24 06:24:06.081672+00:00
+command-line = [
+ "nab",
+ "lock",
+ "--no-cache",
+ "--groups",
+ "release-check",
+ "release-news",
+ "release-notes",
+ "release-prepare",
+ "release-validate",
+ "--output",
+ "pylock.toml",
+ "--upgrade",
+]
+input-path = "pyproject.toml"
+mode = "universal"
+python-specifier = ">=3.15,<3.16"
+platforms = [
+ "linux_x86_64",
+ "linux_aarch64",
+ "macos_arm64",
+ "windows_amd64",
+]
diff --git a/pyproject.toml b/pyproject.toml
index 63c0a45..9f9065b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,20 +1,19 @@
[build-system]
build-backend = "hatchling.build"
requires = [
+ "hatch-fancy-pypi-readme>=25.1",
"hatch-vcs>=0.5",
"hatchling>=1.32.4",
]
[project]
name = "devpi-process"
+import-names = [ "devpi_process" ]
description = "devpi process provides a programmatic API to create and use a devpi server process"
-readme.content-type = "text/markdown"
-readme.file = "README.md"
keywords = [
- "environments",
- "isolated",
+ "devpi",
+ "process",
"testing",
- "virtual",
]
license = "MIT"
maintainers = [
@@ -26,9 +25,7 @@ authors = [
requires-python = ">=3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
- "Framework :: tox",
"Intended Audience :: Developers",
- "License :: OSI Approved :: MIT License",
"Operating System :: MacOS :: MacOS X",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX",
@@ -43,12 +40,14 @@ classifiers = [
"Topic :: Utilities",
]
dynamic = [
+ "readme",
"version",
]
dependencies = [
"devpi-client>=7.3",
"devpi-server>=6.20.3",
]
+urls.Changelog = "https://github.com/tox-dev/devpi-process/blob/main/CHANGELOG.md"
urls.Homepage = "https://github.com/tox-dev/devpi-process#readme"
urls.Source = "https://github.com/tox-dev/devpi-process"
urls.Tracker = "https://github.com/tox-dev/devpi-process/issues"
@@ -78,11 +77,54 @@ pkg-meta = [
"twine>=7",
"uv>=0.12.22",
]
+release = [
+ "mdformat-gfm>=1",
+ "mdformat-ruff>=0.1.3",
+ "prek>=0.5",
+ "release-creator>=1",
+ "towncrier>=26.9",
+]
+release-check = [
+ "prek>=0.5",
+]
+release-news = [
+ "release-creator>=1",
+ "towncrier>=26.9",
+]
+release-notes = [
+ "release-creator>=1",
+]
+release-prepare = [
+ "prek>=0.5",
+ "release-creator>=1",
+ "towncrier>=26.9",
+]
+release-validate = [
+ "prek>=0.5",
+ "release-creator>=1",
+]
[tool.hatch]
version.source = "vcs"
+metadata.hooks.fancy-pypi-readme.content-type = "text/markdown"
+metadata.hooks.fancy-pypi-readme.fragments = [ { path = "README.md" } ]
+metadata.hooks.fancy-pypi-readme.substitutions = [
+ { pattern = '''(?x)
+ (?[^\]]+)\]\( # Link text, excluding images
+ (?PCHANGELOG\.md|CONTRIBUTING\.md) # Repository files linked from the README
+ \)
+ ''', replacement = '[\g