Skip to content

feat: Add Python 3.14 support to build and validation#1921

Merged
joshuarli merged 68 commits intomainfrom
feat/python314-support
Feb 26, 2026
Merged

feat: Add Python 3.14 support to build and validation#1921
joshuarli merged 68 commits intomainfrom
feat/python314-support

Conversation

@phacops
Copy link
Contributor

@phacops phacops commented Feb 19, 2026

Add CPython 3.14 as a build target so wheels are produced and validated
for the new version.

Changes:

  • build.py / validate.py: Add (3, 14) to PYTHONS
  • docker/Dockerfile: Add cp314-cp314 to container PATH
  • docker/install-pythons: Add 3.14.3 checksums from the 20260211
    python-build-standalone release. Refactored RELEASE to RELEASE_BASE
    so the download URL is derived per-filename, allowing different Python
    versions to come from different upstream releases.
  • tests/validate_test.py: Update expected outputs to include python3.14

Agent transcript: https://claudescope.sentry.dev/share/jOjrpAXIIvZmY5-PXSVMhkNi3RsKK_SiCTPO_d0N4NU

@phacops phacops marked this pull request as ready for review February 19, 2026 23:57
@phacops phacops force-pushed the feat/python314-support branch from c8ebbe4 to 8389cfc Compare February 20, 2026 00:32
@phacops phacops changed the base branch from main to feat/add-python-314 February 20, 2026 00:34
Base automatically changed from feat/add-python-314 to main February 23, 2026 18:07
phacops and others added 6 commits February 23, 2026 13:51
Add CPython 3.14.3 to the Docker image for building wheels. Also
updates python-build-standalone from 20241016 to 20260211, bumping
existing Pythons (3.11.14, 3.12.12, 3.13.12) and pip/setuptools/wheel
to versions that support 3.14.

Co-Authored-By: Claude <noreply@anthropic.com>

Agent transcript: https://claudescope.sentry.dev/share/Al5MtqcQnkt1gm-jnx6oL_GOvYTH5jS74i_VDV3avDE
Don't build py314 packages yet — only add CPython 3.14 to the Docker
image so it's available for future use.

Co-Authored-By: Claude <noreply@anthropic.com>

Agent transcript: https://claudescope.sentry.dev/share/35z9K7seE_hEDSFU1UupeIa8FBtGyQqFv-mYa7W-Twk
Add CPython 3.14 as a build target so wheels are produced and validated
for the new version. The Docker image is updated to include 3.14.3 from
the 20260211 python-build-standalone release.

The install-pythons script now derives the release URL from the filename
so different Python versions can come from different releases without
needing a single shared release constant.

Co-Authored-By: Claude <noreply@anthropic.com>

Agent transcript: https://claudescope.sentry.dev/share/ItdjNNWB2P8_USprDnV0ADMt2jpcI2YSduF2v4j4JjU
Fix black formatting for RELEASE_BASE in install-pythons. Add
python_versions = <3.14 to backports-zstd==1.3.0 since it declares
Requires-Python >=3.9,<3.14.

Co-Authored-By: Claude <noreply@anthropic.com>

Agent transcript: https://claudescope.sentry.dev/share/Gq-buso0ranTB4rLKkb9Ep55pUCG5IeGtJFnQTv7yyA
CMake 4.x removed compatibility with cmake_minimum_required < 3.5.
The crc32c 1.1.2 CMakeLists.txt requires an older minimum, so pass
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 to allow it to configure.

Co-Authored-By: Claude <noreply@anthropic.com>

Agent transcript: https://claudescope.sentry.dev/share/5oWxVqqxe2DCIZCs6tjes9XF-wSB8MtKsfb_DMH9VhI
@joshuarli joshuarli force-pushed the feat/python314-support branch from 51eb981 to e617d49 Compare February 23, 2026 21:51
joshuarli and others added 3 commits February 23, 2026 15:28
Remove --source-deps-only from librdkafka configure so it uses
system-installed libraries. The bundled source deps (zlib 1.2.13 etc.)
fail to build: on Linux due to broken perl/shasum from the custom
libxcrypt, and on macOS due to Xcode 16 SDK incompatibilities.

Add libcurl4-openssl-dev, libsasl2-dev, and libzstd-dev to the
Docker image so all librdkafka deps are available as system packages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The examples fail to link when using system libcurl because its static
lib has many transitive deps (libpsl, libgssapi, libidn2, libbrotli)
that aren't provided. We only need the library itself, not examples.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Top-level make install also tries to build examples, which fails due
to libcurl static linking transitive deps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@joshuarli
Copy link
Member

might have to shelve building grpcio for later - bit tricky

objectstore-client==0.0.1 has python_versions = >=3.13.1 but
validate.py was trying to validate it on python3.11 and python3.12,
causing pip install to fail. Now validate.py reads the python_versions
specifier and skips Python versions that don't match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
name: dist-linux-${{ matrix.arch }}
path: dist/*
macos:
needs: [image]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

macOS job unnecessarily depends on Docker image build

Medium Severity

The macos job declares needs: [image], but the image job only builds Linux Docker containers. The macOS job installs Python natively via uv and never uses Docker. This unnecessary dependency means if the Docker image build fails, the macOS job is skipped. Since collect-and-deploy requires both linux and macos, a Docker-only failure would block the entire deployment, including perfectly valid macOS wheels.

Fix in Cursor Fix in Web

packages.ini Outdated
[grpcio==1.73.1]
python_versions = <3.14
[grpcio==1.75.1]
python_versions = <3.14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grpcio 1.75.1 incorrectly restricted from Python 3.14

High Severity

grpcio==1.75.1 has python_versions = <3.14 but PYTHON-3.14-UPGRADE.md explicitly states "grpcio==1.75.1 succeeds everywhere" and categorizes these grpcio issues as "NOT Python 3.14 incompatibilities," noting they "were NOT marked with python_versions = <3.14." Since grpcio is a C extension requiring per-version wheels, this restriction prevents building any 3.14 wheel for the latest grpcio, blocking Python 3.14 users from installing it.

Additional Locations (1)

Fix in Cursor Fix in Web

Move the image-building job into the upgrade-python skill as a
temporary step only needed during Python upgrades. The production
workflow now uses pre-built :latest images directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
[grpcio-status==1.73.1]
python_versions = <3.14
[grpcio-status==1.75.1]
python_versions = <3.14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pure Python grpcio-status 1.75.1 incorrectly restricted from 3.14

Low Severity

grpcio-status==1.75.1 has python_versions = <3.14 added, but its corresponding binary dependency grpcio==1.75.1 has no such restriction (it builds fine on 3.14). grpcio-status is a pure Python package (py3-none-any wheel) with no native code, so it inherently works on Python 3.14. It's also absent from PYTHON-3.14-UPGRADE.md as a failed package. The restriction appears to have been applied uniformly to all grpcio-status versions without noticing that grpcio==1.75.1 doesn't need it. This causes Python 3.14 validation to be skipped for this wheel.

Fix in Cursor Fix in Web

[grpcio-status==1.73.1]
python_versions = <3.14
[grpcio-status==1.75.1]
python_versions = <3.14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary Python 3.14 restriction on grpcio-status 1.75.1

Low Severity

grpcio-status==1.75.1 is marked with python_versions = <3.14, but grpcio==1.75.1 (its primary binary dependency) has no such restriction and the PYTHON-3.14-UPGRADE.md explicitly notes "grpcio==1.75.1 succeeds everywhere." grpcio-status is a pure Python package (py3-none-any) and isn't listed among any upgrade failures. This restriction unnecessarily prevents validation on Python 3.14, unlike the other grpcio-status versions (1.67.0, 1.72.0rc1, 1.73.1) whose corresponding grpcio versions are correctly restricted.

Fix in Cursor Fix in Web

@joshuarli joshuarli self-requested a review February 25, 2026 23:13
Copy link
Member

@joshuarli joshuarli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i've updated this to use uv's pythons and remove our python-build-standalone workarounds

there's quite a few important packages that won't build on 3.14 yet - will followup in time

- {arch: arm64, os: ubuntu-24.04-arm}
runs-on: ${{ matrix.os }}
container: ghcr.io/getsentry/pypi-manylinux-${{ matrix.arch }}-ci
container: ghcr.io/getsentry/pypi-manylinux-${{ matrix.arch }}-ci:${{ github.head_ref == 'feat/python314-support' && '8df7dad534f8988425df12271307b7dd936fd644'' || 'latest' }}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra single-quote corrupts container image tag expression

High Severity

The container tag expression has a double single-quote ('') after the commit SHA: '8df7dad534f8988425df12271307b7dd936fd644''. In GitHub Actions expression syntax, '' inside a single-quoted string is an escaped literal single-quote, which means the string is NOT closed at the intended position. The parser treats everything after the SHA — including || and latest — as part of the string literal, resulting in either a malformed expression or a completely wrong container tag. This affects every workflow run because the expression must parse correctly regardless of short-circuit evaluation.

Fix in Cursor Fix in Web

[grpcio-status==1.73.1]
python_versions = <3.14
[grpcio-status==1.75.1]
python_versions = <3.14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grpcio-status 1.75.1 unnecessarily restricted from Python 3.14

Low Severity

grpcio-status==1.75.1 is marked with python_versions = <3.14, but grpcio==1.75.1 (its primary dependency) has no such restriction and builds fine on Python 3.14. grpcio-status is a pure Python package with no native code, so it has no 3.14 incompatibility. It's also not listed in PYTHON-3.14-UPGRADE.md as a failure. This restriction unnecessarily skips validation on Python 3.14.

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable autofix in the Cursor dashboard.

[grpcio-status==1.73.1]
python_versions = <3.14
[grpcio-status==1.75.1]
python_versions = <3.14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pure Python grpcio-status 1.75.1 unnecessarily restricted from 3.14

Medium Severity

grpcio-status==1.75.1 is marked with python_versions = <3.14, but it's a pure Python package (py3-none-any wheel) and its main dependency grpcio==1.75.1 has no such restriction (line 891). The PYTHON-3.14-UPGRADE.md failure document doesn't list grpcio-status as a failure at all. This prevents building and validating this package for Python 3.14 unnecessarily.

Fix in Cursor Fix in Web

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix prepared fixes for both issues found in the latest run.

  • ✅ Fixed: Incorrect Python 3.14 restriction on grpcio-status 1.75.1
    • Removed the erroneous python_versions = <3.14 line from grpcio-status==1.75.1 in packages.ini so it can be built on Python 3.14.
  • ✅ Fixed: Hardcoded branch name and SHA in container reference
    • Replaced the branch-conditional container expression with an unconditional :latest tag in .github/workflows/build.yml.

Create PR

Or push these changes by commenting:

@cursor push 6a741522b1
Preview (6a741522b1)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -17,7 +17,7 @@
         - {arch: amd64, os: ubuntu-latest}
         - {arch: arm64, os: ubuntu-24.04-arm}
     runs-on: ${{ matrix.os }}
-    container: ghcr.io/getsentry/pypi-manylinux-${{ matrix.arch }}-ci:${{ github.head_ref == 'feat/python314-support' && '769374905268e37a20b467d487926b78d56eb96c' || 'latest' }}
+    container: ghcr.io/getsentry/pypi-manylinux-${{ matrix.arch }}-ci:latest
     steps:
     - uses: actions/checkout@v3
     - run: python3 -um build --pypi-url https://pypi.devinfra.sentry.io

diff --git a/packages.ini b/packages.ini
--- a/packages.ini
+++ b/packages.ini
@@ -907,7 +907,6 @@
 [grpcio-status==1.73.1]
 python_versions = <3.14
 [grpcio-status==1.75.1]
-python_versions = <3.14
 
 [h11==0.9.0]
 [h11==0.12.0]
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

[grpcio-status==1.73.1]
python_versions = <3.14
[grpcio-status==1.75.1]
python_versions = <3.14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect Python 3.14 restriction on grpcio-status 1.75.1

Medium Severity

grpcio-status==1.75.1 has python_versions = <3.14 added, but grpcio==1.75.1 has no such restriction (it builds fine on 3.14). grpcio-status is a pure Python package with no native extensions — it just depends on grpcio, protobuf, and googleapis-common-protos. Since its matching grpcio version works on 3.14, there's no reason to exclude grpcio-status==1.75.1 from Python 3.14. This looks like a mechanical copy from the other grpcio-status versions where the corresponding grpcio versions genuinely needed the restriction.

Fix in Cursor Fix in Web

- {arch: arm64, os: ubuntu-24.04-arm}
runs-on: ${{ matrix.os }}
container: ghcr.io/getsentry/pypi-manylinux-${{ matrix.arch }}-ci
container: ghcr.io/getsentry/pypi-manylinux-${{ matrix.arch }}-ci:${{ github.head_ref == 'feat/python314-support' && '769374905268e37a20b467d487926b78d56eb96c' || 'latest' }}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded branch name and SHA in container reference

Low Severity

The container reference embeds a branch-specific condition (github.head_ref == 'feat/python314-support') and a hardcoded image SHA. After this PR merges, github.head_ref is empty for push events to main, so the condition is always false and the SHA is dead code. This is temporary scaffolding from the upgrade process that needs to be cleaned up to just use 'latest' unconditionally.

Fix in Cursor Fix in Web

@joshuarli joshuarli merged commit 49f3f5d into main Feb 26, 2026
19 checks passed
@joshuarli joshuarli deleted the feat/python314-support branch February 26, 2026 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants