diff options
author | 2022-05-19 16:10:38 -0700 | |
---|---|---|
committer | 2022-05-19 16:10:38 -0700 | |
commit | a2ec09b7f56578f40132ee69a39c34a3f3ec5ec5 (patch) | |
tree | f797263b017276c20c6d4ccb4eb6905c23a916fb | |
parent | gh-92984: Explicitly disable incremental linking for Windows Release and PGO ... (diff) | |
download | cpython-a2ec09b7f56578f40132ee69a39c34a3f3ec5ec5.tar.gz cpython-a2ec09b7f56578f40132ee69a39c34a3f3ec5ec5.tar.bz2 cpython-a2ec09b7f56578f40132ee69a39c34a3f3ec5ec5.zip |
gh-92817: Fix precedence of options to py.exe launcher (GH-92988)
(cherry picked from commit 73473fdeac3ff9d75ac9d189bb8552b7459812f1)
Co-authored-by: Steve Dower <steve.dower@python.org>
-rw-r--r-- | Lib/test/test_launcher.py | 34 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Windows/2022-05-19-21-44-25.gh-issue-92817.Jrf-Kv.rst | 3 | ||||
-rw-r--r-- | PC/launcher2.c | 23 |
3 files changed, 49 insertions, 11 deletions
diff --git a/Lib/test/test_launcher.py b/Lib/test/test_launcher.py index 2e10c55e339..aeacbbecbfa 100644 --- a/Lib/test/test_launcher.py +++ b/Lib/test/test_launcher.py @@ -244,6 +244,17 @@ class RunPyMixin: finally: file.unlink() + @contextlib.contextmanager + def test_venv(self): + venv = Path.cwd() / "Scripts" + venv.mkdir(exist_ok=True, parents=True) + venv_exe = (venv / Path(sys.executable).name) + venv_exe.touch() + try: + yield venv_exe, {"VIRTUAL_ENV": str(venv.parent)} + finally: + shutil.rmtree(venv) + class TestLauncher(unittest.TestCase, RunPyMixin): @classmethod @@ -451,12 +462,8 @@ class TestLauncher(unittest.TestCase, RunPyMixin): self.assertEqual("PythonTestSuite/3.100", default) def test_virtualenv_in_list(self): - venv = Path.cwd() / "Scripts" - venv.mkdir(exist_ok=True, parents=True) - venv_exe = (venv / Path(sys.executable).name) - venv_exe.touch() - try: - data = self.run_py(["-0p"], env={"VIRTUAL_ENV": str(venv.parent)}) + with self.test_venv() as (venv_exe, env): + data = self.run_py(["-0p"], env=env) for line in data["stdout"].splitlines(): m = re.match(r"\s*\*\s+(.+)$", line) if m: @@ -465,7 +472,7 @@ class TestLauncher(unittest.TestCase, RunPyMixin): else: self.fail("did not find active venv path") - data = self.run_py(["-0"], env={"VIRTUAL_ENV": str(venv.parent)}) + data = self.run_py(["-0"], env=env) for line in data["stdout"].splitlines(): m = re.match(r"\s*\*\s+(.+)$", line) if m: @@ -473,8 +480,17 @@ class TestLauncher(unittest.TestCase, RunPyMixin): break else: self.fail("did not find active venv entry") - finally: - shutil.rmtree(venv) + + def test_virtualenv_with_env(self): + with self.test_venv() as (venv_exe, env): + data1 = self.run_py([], env={**env, "PY_PYTHON": "-3"}) + data2 = self.run_py(["-3"], env={**env, "PY_PYTHON": "-3"}) + # Compare stdout, because stderr goes via ascii + self.assertEqual(data1["stdout"].strip(), str(venv_exe)) + self.assertEqual(data1["SearchInfo.lowPriorityTag"], "True") + # Ensure passing the argument doesn't trigger the same behaviour + self.assertNotEqual(data2["stdout"].strip(), str(venv_exe)) + self.assertNotEqual(data2["SearchInfo.lowPriorityTag"], "True") def test_py_shebang(self): with self.py_ini(TEST_PY_COMMANDS): diff --git a/Misc/NEWS.d/next/Windows/2022-05-19-21-44-25.gh-issue-92817.Jrf-Kv.rst b/Misc/NEWS.d/next/Windows/2022-05-19-21-44-25.gh-issue-92817.Jrf-Kv.rst new file mode 100644 index 00000000000..16acba1d627 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-05-19-21-44-25.gh-issue-92817.Jrf-Kv.rst @@ -0,0 +1,3 @@ +Ensures that :file:`py.exe` will prefer an active virtual environment over +default tags specified with environment variables or through a +:file:`py.ini` file. diff --git a/PC/launcher2.c b/PC/launcher2.c index 35c932aa329..763bc138ed7 100644 --- a/PC/launcher2.c +++ b/PC/launcher2.c @@ -386,6 +386,12 @@ typedef struct { int tagLength; // if true, treats 'tag' as a non-PEP 514 filter bool oldStyleTag; + // if true, ignores 'tag' when a high priority environment is found + // gh-92817: This is currently set when a tag is read from configuration or + // the environment, rather than the command line or a shebang line, and the + // only currently possible high priority environment is an active virtual + // environment + bool lowPriorityTag; // if true, we had an old-style tag with '-64' suffix, and so do not // want to match tags like '3.x-32' bool exclude32Bit; @@ -475,6 +481,7 @@ dumpSearchInfo(SearchInfo *search) DEBUG_2(company, companyLength); DEBUG_2(tag, tagLength); DEBUG_BOOL(oldStyleTag); + DEBUG_BOOL(lowPriorityTag); DEBUG_BOOL(exclude32Bit); DEBUG_BOOL(only32Bit); DEBUG_BOOL(allowDefaults); @@ -965,6 +972,9 @@ checkDefaults(SearchInfo *search) if (!slash) { search->tag = tag; search->tagLength = n; + // gh-92817: allow a high priority env to be selected even if it + // doesn't match the tag + search->lowPriorityTag = true; } else { search->company = tag; search->companyLength = (int)(slash - tag); @@ -995,7 +1005,7 @@ typedef struct EnvironmentInfo { const wchar_t *executableArgs; const wchar_t *architecture; const wchar_t *displayName; - bool isActiveVenv; + bool highPriority; } EnvironmentInfo; @@ -1481,7 +1491,7 @@ virtualenvSearch(const SearchInfo *search, EnvironmentInfo **result) if (!env) { return RC_NO_MEMORY; } - env->isActiveVenv = true; + env->highPriority = true; env->internalSortKey = 20; exitCode = copyWstr(&env->displayName, L"Active venv"); if (exitCode) { @@ -1821,6 +1831,15 @@ _selectEnvironment(const SearchInfo *search, EnvironmentInfo *env, EnvironmentIn return 0; } + if (env->highPriority && search->lowPriorityTag) { + // This environment is marked high priority, and the search allows + // it to be selected even though a tag is specified, so select it + // gh-92817: this allows an active venv to be selected even when a + // default tag has been found in py.ini or the environment + *best = env; + return 0; + } + if (!search->oldStyleTag) { if (_companyMatches(search, env) && _tagMatches(search, env)) { // Because of how our sort tree is set up, we will walk up the |