Issue #16993: shutil.which() now preserves the case of the path and extension

on Windows.
This commit is contained in:
Serhiy Storchaka 2013-01-21 15:00:27 +02:00
parent 85da624ebe
commit 014791f848
4 changed files with 15 additions and 9 deletions

View File

@ -335,7 +335,7 @@ Directory and files operations
directories. For example, on Windows::
>>> shutil.which("python")
'c:\\python33\\python.exe'
'C:\\Python33\\python.exe'
.. versionadded:: 3.3

View File

@ -1093,10 +1093,12 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
# See if the given file matches any of the expected path extensions.
# This will allow us to short circuit when given "python.exe".
matches = [cmd for ext in pathext if cmd.lower().endswith(ext.lower())]
# If it does match, only test that one, otherwise we have to try
# others.
files = [cmd] if matches else [cmd + ext.lower() for ext in pathext]
if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
files = [cmd]
else:
files = [cmd + ext for ext in pathext]
else:
# On other platforms you don't have things like PATHEXT to tell you
# what file suffixes are executable, so just pass on cmd as-is.
@ -1104,9 +1106,9 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
seen = set()
for dir in path:
dir = os.path.normcase(dir)
if not dir in seen:
seen.add(dir)
normdir = os.path.normcase(dir)
if not normdir in seen:
seen.add(normdir)
for thefile in files:
name = os.path.join(dir, thefile)
if _access_check(name, mode):

View File

@ -1269,12 +1269,13 @@ class TestShutil(unittest.TestCase):
class TestWhich(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.mkdtemp()
self.temp_dir = tempfile.mkdtemp(prefix="Tmp")
self.addCleanup(shutil.rmtree, self.temp_dir, True)
# Give the temp_file an ".exe" suffix for all.
# It's needed on Windows and not harmful on other platforms.
self.temp_file = tempfile.NamedTemporaryFile(dir=self.temp_dir,
suffix=".exe")
prefix="Tmp",
suffix=".Exe")
os.chmod(self.temp_file.name, stat.S_IXUSR)
self.addCleanup(self.temp_file.close)
self.dir, self.file = os.path.split(self.temp_file.name)
@ -1317,7 +1318,7 @@ class TestWhich(unittest.TestCase):
# Ask for the file without the ".exe" extension, then ensure that
# it gets found properly with the extension.
rv = shutil.which(self.temp_file.name[:-4], path=self.dir)
self.assertEqual(self.temp_file.name, rv)
self.assertEqual(rv, self.temp_file.name[:-4] + ".exe")
class TestMove(unittest.TestCase):

View File

@ -150,6 +150,9 @@ Core and Builtins
Library
-------
- Issue #16993: shutil.which() now preserves the case of the path and extension
on Windows.
- Issue #16992: On Windows in signal.set_wakeup_fd, validate the file
descriptor argument.