From 02a05174d2c530739f22890a81eab7142380ae79 Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 30 Sep 2026 10:33:26 -0400 Subject: [PATCH 1/2] chore(py-sdk): raise the Python floor to 3.10 Python 3.9 is end-of-life, and the patched anyio (4.14.2+) and pytest (9.0.3+) releases both require 3.10 or newer. Moves requires-python, the CI job, and the scan-only requirements-lock.txt to 3.10 (anyio 4.15.1, pytest 9.1.1). --- .github/workflows/ci.yml | 4 ++-- README.md | 2 +- docs/ARCHITECTURE.md | 2 +- packages/py-sdk/README.md | 2 +- packages/py-sdk/pyproject.toml | 3 +-- packages/py-sdk/requirements-lock.txt | 31 +++++++++++---------------- 6 files changed, 18 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68ed119d..f7bec814 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: '3.10' - name: Install dependencies run: pip install -e ".[dev]" diff --git a/README.md b/README.md index c2abcdde..9d1d9d6a 100644 --- a/README.md +++ b/README.md @@ -376,7 +376,7 @@ language-specific form. | SDK | Minimum Version | |:----|:----------------| | JavaScript/TypeScript | Node.js 16+ | -| Python | Python 3.9+ | +| Python | Python 3.10+ | | PHP | PHP 8.1+ | | Go | Go 1.21+ | | Java | Java 11+ | diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 7f94d208..feb41d61 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -113,7 +113,7 @@ Each SDK organizes types by module: ### Test Workflows (`.github/workflows/ci.yml`) Runs on push to `main`/`develop` and all PRs. Per-SDK jobs with language-specific setup: - JS: Node 22, `npm ci && npm run build && npm test` -- Python: 3.9, `pip install -e ".[dev]" && pytest -v` +- Python: 3.10, `pip install -e ".[dev]" && pytest -v` - Go: 1.21, `go mod tidy && go test -v ./...` - PHP: 8.1, `composer install && composer test && composer phpstan` - Java: JDK 11 (Temurin), `mvn test -B` diff --git a/packages/py-sdk/README.md b/packages/py-sdk/README.md index f294bb86..bb9f17a8 100644 --- a/packages/py-sdk/README.md +++ b/packages/py-sdk/README.md @@ -1120,7 +1120,7 @@ scopes: List[str] = [SCOPE_ORG_READ, SCOPE_AUDIT_READ] ## Requirements -- Python 3.9+ +- Python 3.10+ - httpx (async HTTP client) --- diff --git a/packages/py-sdk/pyproject.toml b/packages/py-sdk/pyproject.toml index 13d5c124..47997d57 100644 --- a/packages/py-sdk/pyproject.toml +++ b/packages/py-sdk/pyproject.toml @@ -3,7 +3,7 @@ name = "turbodocx-sdk" version = "0.8.0" description = "TurboDocx Python SDK - Digital signatures, document generation, and AI-powered workflows" readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" license = {text = "MIT"} authors = [ {name = "TurboDocx", email = "team@turbodocx.com"} @@ -24,7 +24,6 @@ classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/packages/py-sdk/requirements-lock.txt b/packages/py-sdk/requirements-lock.txt index a667e788..1f244e2d 100644 --- a/packages/py-sdk/requirements-lock.txt +++ b/packages/py-sdk/requirements-lock.txt @@ -5,40 +5,33 @@ # so py-sdk had zero vulnerability detection. Every other ecosystem here has a lockfile; # this is Python's. # -# RESOLVED FOR PYTHON 3.9 -- the version CI runs and the floor pyproject declares. -# Do NOT regenerate on a newer interpreter: 3.10+ resolves a different tree (pytest 9.x, -# anyio 4.14) that cannot install on 3.9, which would make this file describe an -# environment we never actually build. +# RESOLVED FOR PYTHON 3.10 -- the version CI runs and the floor pyproject declares. +# Do NOT regenerate on a newer interpreter: a newer Python can resolve a tree that does not +# install on the floor, which would make this file describe an environment we never build. # # NOT the install path. CI still runs `pip install -e ".[dev]"` against the declared # ranges, so an upstream breaking change still surfaces. This file exists to be scanned. # -# KNOWN, EXPECTED ALERT: pytest==8.4.2 carries GHSA-6w46-j5rx-g56g (tmpdir handling). -# It is unfixable while we support Python 3.9 -- the patched pytest 9.0.3 requires >=3.10. -# It is a dev/test dependency, never shipped to consumers. Closing it means dropping -# Python 3.9 (bump requires-python and the CI matrix); until that call is made, treat this -# alert as accepted rather than actionable. -# # UNVERIFIED: whether Dependabot will also *update* this file is untested -- it maintains # lockfiles it resolves from a manifest it installs with, and nothing installs from this # one. If security-update PRs never appear, regenerate by hand: -# pip install --dry-run --ignore-installed --python-version 3.9 --only-binary=:all: \ +# pip install --dry-run --ignore-installed --python-version 3.10 --only-binary=:all: \ # --report r.json "httpx>=0.28.1" "typing_extensions>=4.0.0" "pytest>=7.0.0" \ # "pytest-asyncio>=0.21.0" "pytest-httpx>=0.21.0" -Pygments==2.20.0 -anyio==4.12.1 +anyio==4.15.1 backports.asyncio.runner==1.2.0 certifi==2026.7.22 exceptiongroup==1.3.1 h11==0.16.0 httpcore==1.0.9 httpx==0.28.1 -idna==3.18 -iniconfig==2.1.0 -packaging==26.2 +idna==3.20 +iniconfig==2.3.0 +packaging==26.3 pluggy==1.6.0 -pytest==8.4.2 -pytest-asyncio==1.2.0 -pytest-httpx==0.35.0 +Pygments==2.21.0 +pytest-asyncio==1.4.0 +pytest-httpx==0.36.2 +pytest==9.1.1 tomli==2.4.1 typing_extensions==4.16.0 From 7ab2090dcaae8ca69b9fb589511b26069b5d2b9e Mon Sep 17 00:00:00 2001 From: Nicolas Fry Date: Wed, 30 Sep 2026 12:54:28 -0400 Subject: [PATCH 2/2] chore(py-sdk): keep the 3.9 floor; resolve the scan lockfile for 3.10 and test both Reverts the requires-python / README floor change. anyio is unpinned (via httpx), so 3.10+ installs already get the patched release and 3.9 installs cannot get one from any release of ours. The scan-only requirements-lock.txt stays resolved for 3.10 (anyio 4.15.1, pytest 9.1.1), and CI now runs the Python suite on 3.9 and 3.10. --- .github/workflows/ci.yml | 8 ++++++-- README.md | 2 +- docs/ARCHITECTURE.md | 2 +- packages/py-sdk/README.md | 2 +- packages/py-sdk/pyproject.toml | 3 ++- packages/py-sdk/requirements-lock.txt | 12 +++++++++--- 6 files changed, 20 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7bec814..45e5873b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,13 +35,17 @@ jobs: defaults: run: working-directory: packages/py-sdk + strategy: + matrix: + # 3.9 is the declared floor; 3.10 is what requirements-lock.txt is resolved for. + python-version: ['3.9', '3.10'] steps: - uses: actions/checkout@v4 - - name: Set up Python 3.10 + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: ${{ matrix.python-version }} - name: Install dependencies run: pip install -e ".[dev]" diff --git a/README.md b/README.md index 9d1d9d6a..c2abcdde 100644 --- a/README.md +++ b/README.md @@ -376,7 +376,7 @@ language-specific form. | SDK | Minimum Version | |:----|:----------------| | JavaScript/TypeScript | Node.js 16+ | -| Python | Python 3.10+ | +| Python | Python 3.9+ | | PHP | PHP 8.1+ | | Go | Go 1.21+ | | Java | Java 11+ | diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index feb41d61..7f94d208 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -113,7 +113,7 @@ Each SDK organizes types by module: ### Test Workflows (`.github/workflows/ci.yml`) Runs on push to `main`/`develop` and all PRs. Per-SDK jobs with language-specific setup: - JS: Node 22, `npm ci && npm run build && npm test` -- Python: 3.10, `pip install -e ".[dev]" && pytest -v` +- Python: 3.9, `pip install -e ".[dev]" && pytest -v` - Go: 1.21, `go mod tidy && go test -v ./...` - PHP: 8.1, `composer install && composer test && composer phpstan` - Java: JDK 11 (Temurin), `mvn test -B` diff --git a/packages/py-sdk/README.md b/packages/py-sdk/README.md index bb9f17a8..f294bb86 100644 --- a/packages/py-sdk/README.md +++ b/packages/py-sdk/README.md @@ -1120,7 +1120,7 @@ scopes: List[str] = [SCOPE_ORG_READ, SCOPE_AUDIT_READ] ## Requirements -- Python 3.10+ +- Python 3.9+ - httpx (async HTTP client) --- diff --git a/packages/py-sdk/pyproject.toml b/packages/py-sdk/pyproject.toml index 47997d57..13d5c124 100644 --- a/packages/py-sdk/pyproject.toml +++ b/packages/py-sdk/pyproject.toml @@ -3,7 +3,7 @@ name = "turbodocx-sdk" version = "0.8.0" description = "TurboDocx Python SDK - Digital signatures, document generation, and AI-powered workflows" readme = "README.md" -requires-python = ">=3.10" +requires-python = ">=3.9" license = {text = "MIT"} authors = [ {name = "TurboDocx", email = "team@turbodocx.com"} @@ -24,6 +24,7 @@ classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/packages/py-sdk/requirements-lock.txt b/packages/py-sdk/requirements-lock.txt index 1f244e2d..194446d3 100644 --- a/packages/py-sdk/requirements-lock.txt +++ b/packages/py-sdk/requirements-lock.txt @@ -5,9 +5,15 @@ # so py-sdk had zero vulnerability detection. Every other ecosystem here has a lockfile; # this is Python's. # -# RESOLVED FOR PYTHON 3.10 -- the version CI runs and the floor pyproject declares. -# Do NOT regenerate on a newer interpreter: a newer Python can resolve a tree that does not -# install on the floor, which would make this file describe an environment we never build. +# RESOLVED FOR PYTHON 3.10, which is NOT the floor. pyproject still declares >=3.9 and CI +# tests both. 3.10 is used here because it is the oldest Python that can install the patched +# releases of two packages in this tree: anyio (4.13+ dropped 3.9; the fixes for +# GHSA-82r6-8w77-94w6 and GHSA-5p39-cfhj-2xmp are in 4.14.2) and pytest (9.x dropped 3.9; +# GHSA-6w46-j5rx-g56g is fixed in 9.0.3). A 3.9 install resolves anyio 4.12.1 and +# pytest 8.4.2 instead, and no release of ours can change that: anyio comes in unpinned +# through httpx, and upstream publishes no patched build for 3.9. Resolving for 3.9 would +# only make this file report advisories that every 3.10+ install already avoids. +# Do NOT regenerate on a newer interpreter than 3.10 without a reason. # # NOT the install path. CI still runs `pip install -e ".[dev]"` against the declared # ranges, so an upstream breaking change still surfaces. This file exists to be scanned.