diff options
author | Steve Dower <steve.dower@python.org> | 2022-11-02 18:38:40 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-02 18:38:40 (GMT) |
commit | 3d889dc0a0efa6fcbd984ece365c9ac08d2cd4a9 (patch) | |
tree | 48126e7aa2ca872aa5252d8c295bbc8b9db6d260 | |
parent | f520d720f667c87f7b70ed86ea58d73892d6b969 (diff) | |
download | cpython-3d889dc0a0efa6fcbd984ece365c9ac08d2cd4a9.zip cpython-3d889dc0a0efa6fcbd984ece365c9ac08d2cd4a9.tar.gz cpython-3d889dc0a0efa6fcbd984ece365c9ac08d2cd4a9.tar.bz2 |
gh-98790: When DLLs directory is missing on Windows, assume executable_dir contains PYD files instead (GH-98936)
-rw-r--r-- | Lib/test/test_embed.py | 20 | ||||
-rw-r--r-- | Lib/test/test_getpath.py | 23 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Windows/2022-11-01-00-37-13.gh-issue-98790.fpaPAx.rst | 2 | ||||
-rw-r--r-- | Modules/getpath.py | 28 |
4 files changed, 53 insertions, 20 deletions
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index f5cda15..8c92f49 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1492,17 +1492,11 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): if not MS_WINDOWS: paths[-1] = lib_dynload else: - # Include DLLs directory as well - paths.insert(1, '.\\DLLs') - for index, path in enumerate(paths): - if index == 0: - # Because we copy the DLLs into tmpdir as well, the zip file - # entry in sys.path will be there. For a regular venv, it will - # usually be in the home directory. - paths[index] = os.path.join(tmpdir, os.path.basename(path)) - else: - paths[index] = os.path.join(pyvenv_home, os.path.basename(path)) - paths[-1] = pyvenv_home + paths = [ + os.path.join(tmpdir, os.path.basename(paths[0])), + pyvenv_home, + os.path.join(pyvenv_home, "Lib"), + ] executable = self.test_exe base_executable = os.path.join(pyvenv_home, os.path.basename(executable)) @@ -1519,12 +1513,12 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): config['base_prefix'] = pyvenv_home config['prefix'] = pyvenv_home config['stdlib_dir'] = os.path.join(pyvenv_home, 'Lib') - config['use_frozen_modules'] = not support.Py_DEBUG + config['use_frozen_modules'] = int(not support.Py_DEBUG) else: # cannot reliably assume stdlib_dir here because it # depends too much on our build. But it ought to be found config['stdlib_dir'] = self.IGNORE_CONFIG - config['use_frozen_modules'] = not support.Py_DEBUG + config['use_frozen_modules'] = int(not support.Py_DEBUG) env = self.copy_paths_by_env(config) self.check_all_configs("test_init_compat_config", config, diff --git a/Lib/test/test_getpath.py b/Lib/test/test_getpath.py index 1e46cb5..12d5244 100644 --- a/Lib/test/test_getpath.py +++ b/Lib/test/test_getpath.py @@ -238,6 +238,29 @@ class MockGetPathTests(unittest.TestCase): actual = getpath(ns, expected) self.assertEqual(expected, actual) + def test_no_dlls_win32(self): + "Test a layout on Windows with no DLLs directory." + ns = MockNTNamespace( + argv0=r"C:\Python\python.exe", + real_executable=r"C:\Python\python.exe", + ) + ns.add_known_xfile(r"C:\Python\python.exe") + ns.add_known_file(r"C:\Python\Lib\os.py") + expected = dict( + executable=r"C:\Python\python.exe", + base_executable=r"C:\Python\python.exe", + prefix=r"C:\Python", + exec_prefix=r"C:\Python", + module_search_paths_set=1, + module_search_paths=[ + r"C:\Python\python98.zip", + r"C:\Python\Lib", + r"C:\Python", + ], + ) + actual = getpath(ns, expected) + self.assertEqual(expected, actual) + def test_normal_posix(self): "Test a 'standard' install layout on *nix" ns = MockPosixNamespace( diff --git a/Misc/NEWS.d/next/Windows/2022-11-01-00-37-13.gh-issue-98790.fpaPAx.rst b/Misc/NEWS.d/next/Windows/2022-11-01-00-37-13.gh-issue-98790.fpaPAx.rst new file mode 100644 index 0000000..e8c5ac4 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2022-11-01-00-37-13.gh-issue-98790.fpaPAx.rst @@ -0,0 +1,2 @@ +Assumes that a missing ``DLLs`` directory means that standard extension +modules are in the executable's directory. diff --git a/Modules/getpath.py b/Modules/getpath.py index e3558bc..90a6473 100644 --- a/Modules/getpath.py +++ b/Modules/getpath.py @@ -579,15 +579,28 @@ else: # Detect exec_prefix by searching from executable for the platstdlib_dir if PLATSTDLIB_LANDMARK and not exec_prefix: if executable_dir: - exec_prefix = search_up(executable_dir, PLATSTDLIB_LANDMARK, test=isdir) - if not exec_prefix: - if EXEC_PREFIX: - exec_prefix = EXEC_PREFIX - if not isdir(joinpath(exec_prefix, PLATSTDLIB_LANDMARK)): - warn('Could not find platform dependent libraries <exec_prefix>') + if os_name == 'nt': + # QUIRK: For compatibility and security, do not search for DLLs + # directory. The fallback below will cover it + exec_prefix = executable_dir + else: + exec_prefix = search_up(executable_dir, PLATSTDLIB_LANDMARK, test=isdir) + if not exec_prefix and EXEC_PREFIX: + exec_prefix = EXEC_PREFIX + if not exec_prefix or not isdir(joinpath(exec_prefix, PLATSTDLIB_LANDMARK)): + if os_name == 'nt': + # QUIRK: If DLLs is missing on Windows, don't warn, just assume + # that it's all the same as prefix. + # gh-98790: We set platstdlib_dir here to avoid adding "DLLs" into + # sys.path when it doesn't exist, which would give site-packages + # precedence over executable_dir, which is *probably* where our PYDs + # live. Ideally, whoever changes our layout will tell us what the + # layout is, but in the past this worked, so it should keep working. + platstdlib_dir = exec_prefix = prefix else: warn('Could not find platform dependent libraries <exec_prefix>') + # Fallback: assume exec_prefix == prefix if not exec_prefix: exec_prefix = prefix @@ -689,7 +702,8 @@ elif not pythonpath_was_set: pythonpath.append(platstdlib_dir) if stdlib_dir: pythonpath.append(stdlib_dir) - pythonpath.append(executable_dir) + if executable_dir not in pythonpath: + pythonpath.append(executable_dir) else: if stdlib_dir: pythonpath.append(stdlib_dir) |