Skip to content

Navigation Menu

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

Commit c437fe3

Browse filesBrowse files
[3.9] bpo-40592: shutil.which will not return None anymore if ; is the last char in PATHEXT (GH-20088) (GH-22912)
shutil.which will not return None anymore for empty str in PATHEXT Empty PATHEXT will now be defaulted to _WIN_DEFAULT_PATHEXT (cherry picked from commit da6f098) Co-authored-by: Christopher Marchfelder <marchfelder@googlemail.com>
1 parent f8d96b9 commit c437fe3
Copy full SHA for c437fe3

File tree

3 files changed

+24
-1
lines changed
Filter options

3 files changed

+24
-1
lines changed

‎Lib/shutil.py

Copy file name to clipboardExpand all lines: Lib/shutil.py
+6-1Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
_USE_CP_SENDFILE = hasattr(os, "sendfile") and sys.platform.startswith("linux")
5454
_HAS_FCOPYFILE = posix and hasattr(posix, "_fcopyfile") # macOS
5555

56+
# CMD defaults in Windows 10
57+
_WIN_DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC"
58+
5659
__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
5760
"copytree", "move", "rmtree", "Error", "SpecialFileError",
5861
"ExecError", "make_archive", "get_archive_formats",
@@ -1415,7 +1418,9 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
14151418
path.insert(0, curdir)
14161419

14171420
# PATHEXT is necessary to check on Windows.
1418-
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
1421+
pathext_source = os.getenv("PATHEXT") or _WIN_DEFAULT_PATHEXT
1422+
pathext = [ext for ext in pathext_source.split(os.pathsep) if ext]
1423+
14191424
if use_bytes:
14201425
pathext = [os.fsencode(ext) for ext in pathext]
14211426
# See if the given file matches any of the expected path extensions.

‎Lib/test/test_shutil.py

Copy file name to clipboardExpand all lines: Lib/test/test_shutil.py
+17Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,6 +1848,23 @@ def test_pathext(self):
18481848
rv = shutil.which(program, path=self.temp_dir)
18491849
self.assertEqual(rv, temp_filexyz.name)
18501850

1851+
# Issue 40592: See https://bugs.python.org/issue40592
1852+
@unittest.skipUnless(sys.platform == "win32", 'test specific to Windows')
1853+
def test_pathext_with_empty_str(self):
1854+
ext = ".xyz"
1855+
temp_filexyz = tempfile.NamedTemporaryFile(dir=self.temp_dir,
1856+
prefix="Tmp2", suffix=ext)
1857+
self.addCleanup(temp_filexyz.close)
1858+
1859+
# strip path and extension
1860+
program = os.path.basename(temp_filexyz.name)
1861+
program = os.path.splitext(program)[0]
1862+
1863+
with support.EnvironmentVarGuard() as env:
1864+
env['PATHEXT'] = f"{ext};" # note the ;
1865+
rv = shutil.which(program, path=self.temp_dir)
1866+
self.assertEqual(rv, temp_filexyz.name)
1867+
18511868

18521869
class TestWhichBytes(TestWhich):
18531870
def setUp(self):
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:func:`shutil.which` now ignores empty entries in :envvar:`PATHEXT` instead of treating them as a match.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.