Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

gh-98790: When DLLs directory is missing on Windows, assume executable_dir contains PYD files instead #98936

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 7 additions & 13 deletions 20 Lib/test/test_embed.py
Original file line number Diff line number Diff line change
Expand Up @@ -1484,17 +1484,11 @@ def test_init_pyvenv_cfg(self):
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))
Expand All @@ -1511,12 +1505,12 @@ def test_init_pyvenv_cfg(self):
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,
Expand Down
23 changes: 23 additions & 0 deletions 23 Lib/test/test_getpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,29 @@ def test_buildtree_pythonhome_win32(self):
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(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Assumes that a missing ``DLLs`` directory means that standard extension
modules are in the executable's directory.
28 changes: 21 additions & 7 deletions 28 Modules/getpath.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,15 +579,28 @@ def search_up(prefix, *landmarks, test=isfile):
# 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
Expand Down Expand Up @@ -689,7 +702,8 @@ def search_up(prefix, *landmarks, test=isfile):
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)
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.