From: Itamar Oren Date: Wed, 4 Mar 2026 18:06:49 +0000 (-0800) Subject: gh-122941: Fix test_launcher sporadic failures via py.ini isolation (GH-145090) X-Git-Tag: v3.15.0a7~73 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6cdbd7bc5d4ee63459d03a944477ea8671a05198;p=thirdparty%2FPython%2Fcpython.git gh-122941: Fix test_launcher sporadic failures via py.ini isolation (GH-145090) Adds _PYLAUNCHER_INIDIR as a private variable since the launcher is deprecated and not getting new features. --- diff --git a/Lib/test/test_launcher.py b/Lib/test/test_launcher.py index caa1603c78eb..c522bc1c2c09 100644 --- a/Lib/test/test_launcher.py +++ b/Lib/test/test_launcher.py @@ -227,6 +227,8 @@ class RunPyMixin: "PYLAUNCHER_LIMIT_TO_COMPANY": "", **{k.upper(): v for k, v in (env or {}).items()}, } + if ini_dir := getattr(self, '_ini_dir', None): + env.setdefault("_PYLAUNCHER_INIDIR", ini_dir) if not argv: argv = [self.py_exe, *args] with subprocess.Popen( @@ -262,11 +264,14 @@ class RunPyMixin: return data def py_ini(self, content): - local_appdata = os.environ.get("LOCALAPPDATA") - if not local_appdata: - raise unittest.SkipTest("LOCALAPPDATA environment variable is " - "missing or empty") - return PreservePyIni(Path(local_appdata) / "py.ini", content) + ini_dir = getattr(self, '_ini_dir', None) + if not ini_dir: + local_appdata = os.environ.get("LOCALAPPDATA") + if not local_appdata: + raise unittest.SkipTest("LOCALAPPDATA environment variable is " + "missing or empty") + ini_dir = local_appdata + return PreservePyIni(Path(ini_dir) / "py.ini", content) @contextlib.contextmanager def script(self, content, encoding="utf-8"): @@ -302,6 +307,8 @@ class TestLauncher(unittest.TestCase, RunPyMixin): p = subprocess.check_output("reg query HKCU\\Software\\Python /s") #print(p.decode('mbcs')) + cls._ini_dir = tempfile.mkdtemp() + cls.addClassCleanup(shutil.rmtree, cls._ini_dir, ignore_errors=True) @classmethod def tearDownClass(cls): diff --git a/PC/launcher2.c b/PC/launcher2.c index 832935c5cc6c..4dd18c8eb546 100644 --- a/PC/launcher2.c +++ b/PC/launcher2.c @@ -922,6 +922,20 @@ _readIni(const wchar_t *section, const wchar_t *settingName, wchar_t *buffer, in { wchar_t iniPath[MAXLEN]; int n; + // Check for _PYLAUNCHER_INIDIR override (used for test isolation) + DWORD len = GetEnvironmentVariableW(L"_PYLAUNCHER_INIDIR", iniPath, MAXLEN); + if (len && len < MAXLEN) { + if (join(iniPath, MAXLEN, L"py.ini")) { + debug(L"# Reading from %s for %s/%s\n", iniPath, section, settingName); + n = GetPrivateProfileStringW(section, settingName, NULL, buffer, bufferLength, iniPath); + if (n) { + debug(L"# Found %s in %s\n", settingName, iniPath); + return n; + } + } + // When _PYLAUNCHER_INIDIR is set, skip the default locations + return 0; + } if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, iniPath)) && join(iniPath, MAXLEN, L"py.ini")) { debug(L"# Reading from %s for %s/%s\n", iniPath, section, settingName);