Skip to content

Commit 5982d09

Browse files
ci: Run tests on Python 3.14t
1 parent 2944936 commit 5982d09

File tree

9 files changed

+327
-269
lines changed

9 files changed

+327
-269
lines changed

.github/workflows/test-integrations-ai.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
fail-fast: false
3131
matrix:
32-
python-version: ["3.8","3.9","3.10","3.11","3.12","3.13","3.14"]
32+
python-version: ["3.8","3.9","3.10","3.11","3.12","3.13","3.14","3.14t"]
3333
# python3.6 reached EOL and is no longer being supported on
3434
# new versions of hosted runners on Github Actions
3535
# ubuntu-20.04 is the last version that supported python3.6

.github/workflows/test-integrations-cloud.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
fail-fast: false
3131
matrix:
32-
python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13","3.14"]
32+
python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13","3.14","3.14t"]
3333
# python3.6 reached EOL and is no longer being supported on
3434
# new versions of hosted runners on Github Actions
3535
# ubuntu-20.04 is the last version that supported python3.6

.github/workflows/test-integrations-flags.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
fail-fast: false
3131
matrix:
32-
python-version: ["3.7","3.8","3.9","3.12","3.13","3.14"]
32+
python-version: ["3.7","3.8","3.9","3.12","3.13","3.14","3.14t"]
3333
# python3.6 reached EOL and is no longer being supported on
3434
# new versions of hosted runners on Github Actions
3535
# ubuntu-20.04 is the last version that supported python3.6

.github/workflows/test-integrations-graphql.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
fail-fast: false
3131
matrix:
32-
python-version: ["3.6","3.8","3.9","3.10","3.11","3.12","3.13","3.14"]
32+
python-version: ["3.6","3.8","3.9","3.10","3.11","3.12","3.13","3.14","3.14t"]
3333
# python3.6 reached EOL and is no longer being supported on
3434
# new versions of hosted runners on Github Actions
3535
# ubuntu-20.04 is the last version that supported python3.6

.github/workflows/test-integrations-network.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
fail-fast: false
3131
matrix:
32-
python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13","3.14"]
32+
python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13","3.14","3.14t"]
3333
# python3.6 reached EOL and is no longer being supported on
3434
# new versions of hosted runners on Github Actions
3535
# ubuntu-20.04 is the last version that supported python3.6

.github/workflows/test-integrations-web-1.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
strategy:
3030
fail-fast: false
3131
matrix:
32-
python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13","3.14"]
32+
python-version: ["3.6","3.7","3.8","3.9","3.10","3.11","3.12","3.13","3.14","3.14t"]
3333
# python3.6 reached EOL and is no longer being supported on
3434
# new versions of hosted runners on Github Actions
3535
# ubuntu-20.04 is the last version that supported python3.6

scripts/populate_tox/populate_tox.py

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import subprocess
1212
import sys
1313
import time
14+
from dataclasses import dataclass
1415
from bisect import bisect_left
1516
from collections import defaultdict
1617
from datetime import datetime, timedelta, timezone # noqa: F401
@@ -68,6 +69,27 @@
6869
}
6970

7071

72+
@dataclass(order=True)
73+
class ThreadedVersion:
74+
version: Version
75+
no_gil: bool
76+
77+
def __init__(self, version: str | Version, no_gil=False):
78+
self.version = Version(version) if isinstance(version, str) else version
79+
self.no_gil = no_gil
80+
81+
def __str__(self):
82+
version = f"py{self.version.major}.{self.version.minor}"
83+
if self.no_gil:
84+
version += "t"
85+
86+
return version
87+
88+
89+
# Free-threading is experimentally supported in 3.13, and officially supported in 3.14.
90+
MIN_FREE_THREADING_SUPPORT = ThreadedVersion("3.14")
91+
92+
7193
def _fetch_sdk_metadata() -> PackageMetadata:
7294
(dist,) = distributions(
7395
name="sentry-sdk", path=[Path(__file__).parent.parent.parent]
@@ -404,12 +426,18 @@ def supported_python_versions(
404426
return supported
405427

406428

407-
def pick_python_versions_to_test(python_versions: list[Version]) -> list[Version]:
429+
def pick_python_versions_to_test(
430+
python_versions: list[Version], has_free_threading_wheel: bool
431+
) -> list[Version]:
408432
"""
409433
Given a list of Python versions, pick those that make sense to test on.
410434
411435
Currently, this is the oldest, the newest, and the second newest Python
412436
version.
437+
438+
the free-threaded variant of the newest version is also selected if
439+
- a free-threaded wheel is distributed; and
440+
- the SDK supports free-threading on the newest supported version.
413441
"""
414442
filtered_python_versions = {
415443
python_versions[0],
@@ -421,7 +449,16 @@ def pick_python_versions_to_test(python_versions: list[Version]) -> list[Version
421449
except IndexError:
422450
pass
423451

424-
return sorted(filtered_python_versions)
452+
versions_to_test = sorted(
453+
ThreadedVersion(version) for version in filtered_python_versions
454+
)
455+
456+
if has_free_threading_wheel and versions_to_test[-1] >= MIN_FREE_THREADING_SUPPORT:
457+
versions_to_test.append(
458+
ThreadedVersion(versions_to_test[-1].version, no_gil=True)
459+
)
460+
461+
return versions_to_test
425462

426463

427464
def _parse_python_versions_from_classifiers(classifiers: list[str]) -> list[Version]:
@@ -475,12 +512,23 @@ def determine_python_versions(pypi_data: dict) -> Union[SpecifierSet, list[Versi
475512
return []
476513

477514

478-
def _render_python_versions(python_versions: list[Version]) -> str:
479-
return (
480-
"{"
481-
+ ",".join(f"py{version.major}.{version.minor}" for version in python_versions)
482-
+ "}"
483-
)
515+
def has_free_threading_wheel(pypi_data: dict) -> bool:
516+
for download in pypi_data["urls"]:
517+
print(download)
518+
519+
if download["packagetype"] == "bdist_wheel":
520+
abi_tag = download["filename"].removesuffix(".whl").split("-")[-2]
521+
522+
if abi_tag == "none" or (
523+
abi_tag.endswith("t") and abi_tag.startswith("cp314")
524+
):
525+
return True
526+
527+
return False
528+
529+
530+
def _render_python_versions(python_versions: list[ThreadedVersion]) -> str:
531+
return "{" + ",".join(str(version) for version in python_versions) + "}"
484532

485533

486534
def _render_dependencies(integration: str, releases: list[Version]) -> list[str]:
@@ -590,7 +638,8 @@ def _add_python_versions_to_release(
590638
determine_python_versions(release_pypi_data),
591639
target_python_versions,
592640
release,
593-
)
641+
),
642+
has_free_threading_wheel(release_pypi_data),
594643
)
595644

596645
release.rendered_python_versions = _render_python_versions(release.python_versions)
@@ -647,8 +696,16 @@ def _normalize_name(package: str) -> str:
647696
return package.lower().replace("-", "_")
648697

649698

699+
def _extract_wheel_info_to_cache(wheel: dict):
700+
return {
701+
"packagetype": wheel["packagetype"],
702+
"filename": wheel["filename"],
703+
}
704+
705+
650706
def _normalize_release(release: dict) -> dict:
651707
"""Filter out unneeded parts of the release JSON."""
708+
urls = [_extract_wheel_info_to_cache(wheel) for wheel in release["urls"]]
652709
normalized = {
653710
"info": {
654711
"classifiers": release["info"]["classifiers"],
@@ -657,6 +714,7 @@ def _normalize_release(release: dict) -> dict:
657714
"version": release["info"]["version"],
658715
"yanked": release["info"]["yanked"],
659716
},
717+
"urls": urls,
660718
}
661719
return normalized
662720

@@ -766,7 +824,7 @@ def main() -> dict[str, list]:
766824

767825
print(
768826
"Done generating tox.ini. Make sure to also update the CI YAML "
769-
"files to reflect the new test targets."
827+
"files by executing split_tox_gh_actions.py."
770828
)
771829

772830
return packages

0 commit comments

Comments
 (0)