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

Commit fe064f4

Browse filesBrowse files
peanutlordmiss-islington
authored andcommitted
bpo-40592: shutil.which will not return None anymore if ; is the last char in PATHEXT (pythonGH-20088)
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 cd894b1 commit fe064f4
Copy full SHA for fe064f4

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",
@@ -1400,7 +1403,9 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
14001403
path.insert(0, curdir)
14011404

14021405
# PATHEXT is necessary to check on Windows.
1403-
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
1406+
pathext_source = os.getenv("PATHEXT") or _WIN_DEFAULT_PATHEXT
1407+
pathext = [ext for ext in pathext_source.split(os.pathsep) if ext]
1408+
14041409
if use_bytes:
14051410
pathext = [os.fsencode(ext) for ext in pathext]
14061411
# 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
@@ -1830,6 +1830,23 @@ def test_pathext(self):
18301830
rv = shutil.which(program, path=self.temp_dir)
18311831
self.assertEqual(rv, temp_filexyz.name)
18321832

1833+
# Issue 40592: See https://bugs.python.org/issue40592
1834+
@unittest.skipUnless(sys.platform == "win32", 'test specific to Windows')
1835+
def test_pathext_with_empty_str(self):
1836+
ext = ".xyz"
1837+
temp_filexyz = tempfile.NamedTemporaryFile(dir=self.temp_dir,
1838+
prefix="Tmp2", suffix=ext)
1839+
self.addCleanup(temp_filexyz.close)
1840+
1841+
# strip path and extension
1842+
program = os.path.basename(temp_filexyz.name)
1843+
program = os.path.splitext(program)[0]
1844+
1845+
with os_helper.EnvironmentVarGuard() as env:
1846+
env['PATHEXT'] = f"{ext};" # note the ;
1847+
rv = shutil.which(program, path=self.temp_dir)
1848+
self.assertEqual(rv, temp_filexyz.name)
1849+
18331850

18341851
class TestWhichBytes(TestWhich):
18351852
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.