From 3c8003e897410c74848b4ef4c635c929049af39f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Langa?= Date: Sat, 24 Oct 2026 13:06:48 -0700 Subject: [PATCH] [3.11] Fix Windows build regen with Python 3.15 as the host Python The windows-2022 GitHub runner image no longer ships Python 3.10, so PCbuild/find_python.bat fell through to NuGet and installed the latest pythonx86 package, which is now 3.15.1. Python 3.15 removed Loader.load_module(), which Python/makeopcodetargets.py used to import Lib/opcode.py, so the _RegenOpcodes target failed and broke every Windows CI build on this branch. Load Lib/opcode.py through importlib.util instead, and extend the py.exe search list in find_python.bat up to 3.14 so the build picks up the runner's preinstalled Python rather than whatever NuGet considers latest. Co-Authored-By: Claude Fable 5.1 --- PCbuild/find_python.bat | 2 +- Python/makeopcodetargets.py | 28 ++++++++++------------------ 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat index 6219f7c53cac53..8a97d3b1ea1909 100644 --- a/PCbuild/find_python.bat +++ b/PCbuild/find_python.bat @@ -42,7 +42,7 @@ @if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 9)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found @rem If py.exe finds a recent enough version, use that one -@for %%p in (3.10 3.9) do @py -%%p -EV >nul 2>&1 && (set PYTHON=py -%%p) && (set _Py_Python_Source=found %%p with py.exe) && goto :found +@for %%p in (3.14 3.13 3.12 3.11 3.10 3.9) do @py -%%p -EV >nul 2>&1 && (set PYTHON=py -%%p) && (set _Py_Python_Source=found %%p with py.exe) && goto :found @if NOT exist "%_Py_EXTERNALS_DIR%" mkdir "%_Py_EXTERNALS_DIR%" @set _Py_NUGET=%NUGET% diff --git a/Python/makeopcodetargets.py b/Python/makeopcodetargets.py index 3bf2e35ccb6dab..17a1fbede3eeea 100755 --- a/Python/makeopcodetargets.py +++ b/Python/makeopcodetargets.py @@ -3,28 +3,20 @@ (for compilers supporting computed gotos or "labels-as-values", such as gcc). """ +import importlib.util import os import sys -try: - from importlib.machinery import SourceFileLoader -except ImportError: - import imp - - def find_module(modname): - """Finds and returns a module in the local dist/checkout. - """ - modpath = os.path.join( - os.path.dirname(os.path.dirname(__file__)), "Lib") - return imp.load_module(modname, *imp.find_module(modname, [modpath])) -else: - def find_module(modname): - """Finds and returns a module in the local dist/checkout. - """ - modpath = os.path.join( - os.path.dirname(os.path.dirname(__file__)), "Lib", modname + ".py") - return SourceFileLoader(modname, modpath).load_module() +def find_module(modname): + """Finds and returns a module in the local dist/checkout. + """ + modpath = os.path.join( + os.path.dirname(os.path.dirname(__file__)), "Lib", modname + ".py") + spec = importlib.util.spec_from_file_location(modname, modpath) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module def write_contents(f):