Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 014791f

Browse files
Issue #16993: shutil.which() now preserves the case of the path and extension
on Windows.
1 parent 85da624 commit 014791f

4 files changed

Lines changed: 15 additions & 9 deletions

File tree

Doc/library/shutil.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ Directory and files operations
335335
directories. For example, on Windows::
336336

337337
>>> shutil.which("python")
338-
'c:\\python33\\python.exe'
338+
'C:\\Python33\\python.exe'
339339

340340
.. versionadded:: 3.3
341341

Lib/shutil.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,20 +1093,22 @@ def _access_check(fn, mode):
10931093
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
10941094
# See if the given file matches any of the expected path extensions.
10951095
# This will allow us to short circuit when given "python.exe".
1096-
matches = [cmd for ext in pathext if cmd.lower().endswith(ext.lower())]
10971096
# If it does match, only test that one, otherwise we have to try
10981097
# others.
1099-
files = [cmd] if matches else [cmd + ext.lower() for ext in pathext]
1098+
if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
1099+
files = [cmd]
1100+
else:
1101+
files = [cmd + ext for ext in pathext]
11001102
else:
11011103
# On other platforms you don't have things like PATHEXT to tell you
11021104
# what file suffixes are executable, so just pass on cmd as-is.
11031105
files = [cmd]
11041106

11051107
seen = set()
11061108
for dir in path:
1107-
dir = os.path.normcase(dir)
1108-
if not dir in seen:
1109-
seen.add(dir)
1109+
normdir = os.path.normcase(dir)
1110+
if not normdir in seen:
1111+
seen.add(normdir)
11101112
for thefile in files:
11111113
name = os.path.join(dir, thefile)
11121114
if _access_check(name, mode):

Lib/test/test_shutil.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,12 +1269,13 @@ def test_copytree_return_value(self):
12691269
class TestWhich(unittest.TestCase):
12701270

12711271
def setUp(self):
1272-
self.temp_dir = tempfile.mkdtemp()
1272+
self.temp_dir = tempfile.mkdtemp(prefix="Tmp")
12731273
self.addCleanup(shutil.rmtree, self.temp_dir, True)
12741274
# Give the temp_file an ".exe" suffix for all.
12751275
# It's needed on Windows and not harmful on other platforms.
12761276
self.temp_file = tempfile.NamedTemporaryFile(dir=self.temp_dir,
1277-
suffix=".exe")
1277+
prefix="Tmp",
1278+
suffix=".Exe")
12781279
os.chmod(self.temp_file.name, stat.S_IXUSR)
12791280
self.addCleanup(self.temp_file.close)
12801281
self.dir, self.file = os.path.split(self.temp_file.name)
@@ -1317,7 +1318,7 @@ def test_pathext_checking(self):
13171318
# Ask for the file without the ".exe" extension, then ensure that
13181319
# it gets found properly with the extension.
13191320
rv = shutil.which(self.temp_file.name[:-4], path=self.dir)
1320-
self.assertEqual(self.temp_file.name, rv)
1321+
self.assertEqual(rv, self.temp_file.name[:-4] + ".exe")
13211322

13221323

13231324
class TestMove(unittest.TestCase):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ Core and Builtins
150150
Library
151151
-------
152152

153+
- Issue #16993: shutil.which() now preserves the case of the path and extension
154+
on Windows.
155+
153156
- Issue #16992: On Windows in signal.set_wakeup_fd, validate the file
154157
descriptor argument.
155158

0 commit comments

Comments
 (0)