]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-98790: When DLLs directory is missing on Windows, assume executable_dir contains...
authorSteve Dower <steve.dower@python.org>
Wed, 2 Nov 2022 18:38:40 +0000 (18:38 +0000)
committerGitHub <noreply@github.com>
Wed, 2 Nov 2022 18:38:40 +0000 (18:38 +0000)
Lib/test/test_embed.py
Lib/test/test_getpath.py
Misc/NEWS.d/next/Windows/2022-11-01-00-37-13.gh-issue-98790.fpaPAx.rst [new file with mode: 0644]
Modules/getpath.py

index f5cda1519b65ab6d83c7e2b43857de9693bed7d5..8c92f495d1670418e040fe5737e38ec676957813 100644 (file)
@@ -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,
index 1e46cb5780c94234f7879aa7eb4a5c6e77d0d96a..12d52442c554a11b2f4cd3dcb493bcc8d17dcac5 100644 (file)
@@ -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 (file)
index 0000000..e8c5ac4
--- /dev/null
@@ -0,0 +1,2 @@
+Assumes that a missing ``DLLs`` directory means that standard extension
+modules are in the executable's directory.
index e3558bc49e389f68a970507c4e8a59d207bc4eee..90a6473f1e6ce734e412cfd5054e198ff69b23ad 100644 (file)
@@ -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)