8000 Support free threaded Python versions like '3.13t' · Quansight-Labs/setup-python@ffbe519 · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on Mar 25, 2025. It is now read-only.

Commit ffbe519

Browse files
colesburyandfoy
authored andcommitted
Support free threaded Python versions like '3.13t'
Python wheels, pyenv, and a number of other tools use 't' in the Python version number to identify free threaded builds. For example, '3.13t', '3.14.0a1', '3.14t-dev'. This PR supports that syntax in `actions/setup-python`, strips the "t", and adds "-freethreading" to the architecture to select the correct Python version. See actions#771
1 parent 4237552 commit ffbe519

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

dist/setup/index.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99546,9 +99546,15 @@ function useCpythonVersion(version, architecture, updateEnvironment, checkLatest
9954699546
return __awaiter(this, void 0, void 0, function* () {
9954799547
var _a;
9954899548
let manifest = null;
99549-
const desugaredVersionSpec = desugarDevVersion(version);
99550-
let semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec, allowPreReleases);
99549+
const [desugaredVersionSpec, freethreaded] = desugarFreeThreadedVersion(version);
99550+
const desugaredVersionSpec2 = desugarDevVersion(desugaredVersionSpec);
99551+
let semanticVersionSpec = pythonVersionToSemantic(desugaredVersionSpec2, allowPreReleases);
9955199552
core.debug(`Semantic version spec of ${version} is ${semanticVersionSpec}`);
99553+
if (freethreaded) {
99554+
// Free threaded versions use an architecture suffix like `x64-freethreaded`
99555+
core.debug(`Using freethreaded version of ${semanticVersionSpec}`);
99556+
architecture += freethreaded;
99557+
}
9955299558
if (checkLatest) {
9955399559
manifest = yield installer.getManifest();
9955499560
const resolvedVersion = (_a = (yield installer.findReleaseFromManifest(semanticVersionSpec, architecture, manifest))) === null || _a === void 0 ? void 0 : _a.version;
@@ -99623,6 +99629,23 @@ function useCpythonVersion(version, architecture, updateEnvironment, checkLatest
9962399629
});
9962499630
}
9962599631
exports.useCpythonVersion = useCpythonVersion;
99632+
/* Identify freethreaded versions like, 3.13t, 3.13t-dev, 3.14.0a1t. Returns
99633+
* the version without the `t` and the architectures suffix, if freethreaded */
99634+
function desugarFreeThreadedVersion(versionSpec) {
99635+
const prereleaseVersion = /(\d+\.\d+\.\d+)(t)((?:a|b|rc)\d*)/g;
99636+
if (prereleaseVersion.test(versionSpec)) {
99637+
return [versionSpec.replace(prereleaseVersion, '$1$3'), '-freethreaded'];
99638+
}
99639+
const majorMinor = /^(\d+\.\d+)(t)$/;
99640+
if (majorMinor.test(versionSpec)) {
99641+
return [versionSpec.replace(majorMinor, '$1'), '-freethreaded'];
99642+
}
99643+
const devVersion = /^(\d+\.\d+)(t)(-dev)$/;
99644+
if (devVersion.test(versionSpec)) {
99645+
return [versionSpec.replace(devVersion, '$1$3'), '-freethreaded'];
99646+
}
99647+
return [versionSpec, ''];
99648+
}
9962699649
/** Convert versions like `3.8-dev` to a version like `~3.8.0-0`. */
9962799650
function desugarDevVersion(versionSpec) {
9962899651
const devVersion = /^(\d+)\.(\d+)-dev$/;

src/find-python.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,21 @@ export async function useCpythonVersion(
3838
allowPreReleases: boolean
3939
): Promise<InstalledVersion> {
4040
let manifest: tc.IToolRelease[] | null = null;
41-
const desugaredVersionSpec = desugarDevVersion(version);
41+
const [desugaredVersionSpec, freethreaded] =
42+
desugarFreeThreadedVersion(version);
43+
const desugaredVersionSpec2 = desugarDevVersion(desugaredVersionSpec);
4244
let semanticVersionSpec = pythonVersionToSemantic(
43-
desugaredVersionSpec,
45+
desugaredVersionSpec2,
4446
allowPreReleases
4547
);
4648
core.debug(`Semantic version spec of ${version} is ${semanticVersionSpec}`);
4749

50+
if (freethreaded) {
51+
// Free threaded versions use an architecture suffix like `x64-freethreaded`
52+
core.debug(`Using freethreaded version of ${semanticVersionSpec}`);
53+
architecture += freethreaded;
54+
}
55+
4856
if (checkLatest) {
4957
manifest = await installer.getManifest();
5058
const resolvedVersion = (
@@ -159,6 +167,24 @@ export async function useCpythonVersion(
159167
return {impl: 'CPython', version: installed};
160168
}
161169

170+
/* Identify freethreaded versions like, 3.13t, 3.13t-dev, 3.14.0a1t. Returns
171+
* the version without the `t` and the architectures suffix, if freethreaded */
172+
function desugarFreeThreadedVersion(versionSpec: string) {
173+
const prereleaseVersion = /(\d+\.\d+\.\d+)(t)((?:a|b|rc)\d*)/g;
174+
if (prereleaseVersion.test(versionSpec)) {
175+
return [versionSpec.replace(prereleaseVersion, '$1$3'), '-freethreaded'];
176+
}
177+
const majorMinor = /^(\d+\.\d+)(t)$/;
178+
if (majorMinor.test(versionSpec)) {
179+
return [versionSpec.replace(majorMinor, '$1'), '-freethreaded'];
180+
}
181+
const devVersion = /^(\d+\.\d+)(t)(-dev)$/;
182+
if (devVersion.test(versionSpec)) {
183+
return [versionSpec.replace(devVersion, '$1$3'), '-freethreaded'];
184+
}
185+
return [versionSpec, ''];
186+
}
187+
162188
/** Convert versions like `3.8-dev` to a version like `~3.8.0-0`. */
163189
function desugarDevVersion(versionSpec: string) {
164190
const devVersion = /^(\d+)\.(\d+)-dev$/;

0 commit comments

Comments
 (0)
0