https://github.com/python/cpython/commit/0e2184aca0dabfe7009f1316c75d443085e2b3d6 commit: 0e2184aca0dabfe7009f1316c75d443085e2b3d6 branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: zooba <[email protected]> date: 2026-05-15T14:12:05Z summary:
[3.15] gh-149786: Fixes venvlauncher builds on Windows free-threaded (GH-149847) (cherry picked from commit 1c5fe21eb2a65190c04bb3f4c0931d76f5ccf415) Co-authored-by: Steve Dower <[email protected]> files: A Misc/NEWS.d/next/Windows/2026-05-14-22-09-46.gh-issue-149786.UI-HZM.rst M Lib/test/test_venv.py M PC/layout/support/options.py M PC/layout/support/pymanager.py M PCbuild/python.vcxproj M PCbuild/pythonw.vcxproj M PCbuild/venvlauncher.vcxproj M PCbuild/venvwlauncher.vcxproj diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index a42787f261bfe8..9d2960664abfad 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -301,9 +301,9 @@ def test_sysconfig(self): self.assertEqual(out.strip(), expected, err) for attr, expected in ( ('executable', self.envpy()), - # Usually compare to sys.executable, but if we're running in our own - # venv then we really need to compare to our base executable - ('_base_executable', sys._base_executable), + # Usually compare to sys.prefix, but if we're running in our own + # venv then we really need to compare to our base prefix + ('base_prefix', sys.base_prefix), ): with self.subTest(attr): cmd[2] = f'import sys; print(sys.{attr})' @@ -916,10 +916,10 @@ def test_venvwlauncher(self): exename = exename.replace("python", "pythonw") envpyw = os.path.join(self.env_dir, self.bindir, exename) try: - subprocess.check_call([envpyw, "-c", "import sys; " - "assert sys._base_executable.endswith('%s')" % exename]) + subprocess.check_call([envpyw, "-c", "import fnmatch, sys; " + "assert fnmatch.fnmatch(sys._base_executable, '**/pythonw*.exe')"]) except subprocess.CalledProcessError: - self.fail("venvwlauncher.exe did not run %s" % exename) + self.fail("venvwlauncher.exe did not run pythonw.exe") @requireVenvCreate diff --git a/Misc/NEWS.d/next/Windows/2026-05-14-22-09-46.gh-issue-149786.UI-HZM.rst b/Misc/NEWS.d/next/Windows/2026-05-14-22-09-46.gh-issue-149786.UI-HZM.rst new file mode 100644 index 00000000000000..64ca91a01f41af --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2026-05-14-22-09-46.gh-issue-149786.UI-HZM.rst @@ -0,0 +1 @@ +Fixes virtual environment launchers on Windows free-threaded builds. diff --git a/PC/layout/support/options.py b/PC/layout/support/options.py index 3a6e00f720f01f..f67d8ba04d9070 100644 --- a/PC/layout/support/options.py +++ b/PC/layout/support/options.py @@ -112,6 +112,7 @@ def public(f): "venv", "dev", "html-doc", + "alias", "install-json", "builddetails-json", ], @@ -128,6 +129,7 @@ def public(f): "html-doc", "symbols", "tests", + "alias", "install-test-json", "builddetails-json", ], diff --git a/PC/layout/support/pymanager.py b/PC/layout/support/pymanager.py index 831d49ea3f9b46..f6316e0295c74a 100644 --- a/PC/layout/support/pymanager.py +++ b/PC/layout/support/pymanager.py @@ -66,8 +66,9 @@ def calculate_install_json(ns, *, for_embed=False, for_test=False): if ns.include_freethreaded: # Free-threaded distro comes with a tag suffix TAG_SUFFIX = "t" - TARGET = f"python{VER_MAJOR}.{VER_MINOR}t.exe" - TARGETW = f"pythonw{VER_MAJOR}.{VER_MINOR}t.exe" + if not ns.include_alias: + TARGET = f"python{VER_MAJOR}.{VER_MINOR}t.exe" + TARGETW = f"pythonw{VER_MAJOR}.{VER_MINOR}t.exe" DISPLAY_TAGS.append("free-threaded") FILE_SUFFIX = f"t-{ns.arch}" diff --git a/PCbuild/python.vcxproj b/PCbuild/python.vcxproj index 70dabaa3c8bc02..417ede34c54af3 100644 --- a/PCbuild/python.vcxproj +++ b/PCbuild/python.vcxproj @@ -135,6 +135,14 @@ set PYTHONPATH=$(PySourcePath)Lib "$(OutDir)$(PyExeName)$(PyDebugExt).exe" "$(PySourcePath)PC\validate_ucrtbase.py" $(UcrtName)' ContinueOnError="true" /> </Target> + <Target Name="CopyFreethreadedBinary" AfterTargets="AfterBuild" + Condition="$(DisableGil) == 'true' and $(Configuration) != 'PGInstrument'"> + <Message Text="Duplicating $(TargetPath) to $(PyExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe for free-threaded compatibility" /> + <Copy SourceFiles="$(TargetPath)" + DestinationFiles="$(OutDir)\$(PyExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe" + SkipUnchangedFiles="true" + UseHardLinksIfPossible="true" /> + </Target> <Target Name="GeneratePythonBat" AfterTargets="AfterBuild"> <PropertyGroup> <_Content>@rem This script invokes the most recently built Python with all arguments diff --git a/PCbuild/pythonw.vcxproj b/PCbuild/pythonw.vcxproj index c6a5b8ce90a0d9..244cdf622ad915 100644 --- a/PCbuild/pythonw.vcxproj +++ b/PCbuild/pythonw.vcxproj @@ -115,4 +115,12 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> + <Target Name="CopyFreethreadedBinary" AfterTargets="AfterBuild" + Condition="$(DisableGil) == 'true' and $(Configuration) != 'PGInstrument'"> + <Message Text="Duplicating $(TargetPath) to $(PyWExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe for free-threaded compatibility" /> + <Copy SourceFiles="$(TargetPath)" + DestinationFiles="$(OutDir)\$(PyWExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe" + SkipUnchangedFiles="true" + UseHardLinksIfPossible="true" /> + </Target> </Project> \ No newline at end of file diff --git a/PCbuild/venvlauncher.vcxproj b/PCbuild/venvlauncher.vcxproj index abaf3a979af268..a2e8ffa82b10eb 100644 --- a/PCbuild/venvlauncher.vcxproj +++ b/PCbuild/venvlauncher.vcxproj @@ -89,10 +89,13 @@ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="pyproject.props" /> </ImportGroup> - <PropertyGroup Label="UserMacros" /> + <PropertyGroup Label="UserMacros"> + <ExeName>$(PyExeName)$(PyDebugExt).exe</ExeName> + <ExeName Condition="$(DisableGil) == 'true'">$(PyExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe</ExeName> + </PropertyGroup> <ItemDefinitionGroup> <ClCompile> - <PreprocessorDefinitions>EXENAME=L"$(PyExeName)$(PyDebugExt).exe";_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>EXENAME=L"$(ExeName)";_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> </ClCompile> <ResourceCompile> diff --git a/PCbuild/venvwlauncher.vcxproj b/PCbuild/venvwlauncher.vcxproj index c58280deb8abeb..f2aaf83fe2b378 100644 --- a/PCbuild/venvwlauncher.vcxproj +++ b/PCbuild/venvwlauncher.vcxproj @@ -89,10 +89,13 @@ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="pyproject.props" /> </ImportGroup> - <PropertyGroup Label="UserMacros" /> + <PropertyGroup Label="UserMacros"> + <ExeName>$(PyWExeName)$(PyDebugExt).exe</ExeName> + <ExeName Condition="$(DisableGil) == 'true'">$(PyWExeName)$(MajorVersionNumber).$(MinorVersionNumber)t$(PyDebugExt).exe</ExeName> + </PropertyGroup> <ItemDefinitionGroup> <ClCompile> - <PreprocessorDefinitions>EXENAME=L"$(PyWExeName)$(PyDebugExt).exe";_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>EXENAME=L"$(ExeName)";_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> </ClCompile> <ResourceCompile> _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
