Skip to content

Commit c804a04

Browse files
authored
fix: correctly match free-threaded python versions (#999)
in the case where nox is run given an explicit python version target to run on, nox locates Python interpreters by matching that interpreter string to a regex, that is then expanded to match the name of a Python executable by appending the numeric portions of the version to the word "python", its existence is verified with shutil.which(), and is then passed off to virtualenv as a target to use. However, if the explicit python version ends in "t" for a free-threaded python, such as "3.13t", the regex does not match, due to that "t" that's present which isn't included in the regex. This PR fixes the regex to also look for a "t" at the end for a free-threaded version name, and formats it into the interpreter name virtualenv will look for. There's a bit of a secondary issue which is that if you are trying to select for "3.13" non-free-threaded, but you have a free-threaded 3.13t in your path as well, that "python3.13" name matches in the free-threaded bin folder as well, but virtualenv seems to know how to make the right choice in this case. The only issue I could find regarding free-threading is #949 which vaguely claims that free-threading is working, however this patch is needed if you actually want to indicate the Python version. Fixes: #949
1 parent a4b43d5 commit c804a04

File tree

2 files changed

+5
-2
lines changed

2 files changed

+5
-2
lines changed

nox/virtualenv.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,10 +622,11 @@ def _resolved_interpreter(self) -> str:
622622

623623
# If this is just a X, X.Y, or X.Y.Z string, extract just the X / X.Y
624624
# part and add Python to the front of it.
625-
match = re.match(r"^(?P<xy_ver>\d(\.\d+)?)(\.\d+)?$", self.interpreter)
625+
match = re.match(r"^(?P<xy_ver>\d(\.\d+)?)(\.\d+)?(?P<t>t?)$", self.interpreter)
626626
if match:
627627
xy_version = match.group("xy_ver")
628-
cleaned_interpreter = f"python{xy_version}"
628+
t = match.group("t")
629+
cleaned_interpreter = f"python{xy_version}{t}"
629630

630631
# If the cleaned interpreter is on the PATH, go ahead and return it.
631632
if shutil.which(cleaned_interpreter):

tests/test_virtualenv.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,8 @@ def test__resolved_interpreter_none(
10971097
("3.6.2", "python3.6"),
10981098
("3.10", "python3.10"),
10991099
("2.7.15", "python2.7"),
1100+
("3.13t", "python3.13t"),
1101+
("3.14.1t", "python3.14t"),
11001102
],
11011103
)
11021104
@mock.patch("nox.virtualenv._PLATFORM", new="linux")

0 commit comments

Comments
 (0)