Issue #444582: shutil.which() respects relative paths.
diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst
index b581ce8..7156116 100644
--- a/Doc/library/shutil.rst
+++ b/Doc/library/shutil.rst
@@ -249,8 +249,8 @@
.. function:: which(cmd, mode=os.F_OK | os.X_OK, path=None)
- Return the full path to an executable which would be run if the given
- *cmd* was called. If no *cmd* would be called, return ``None``.
+ Return the path to an executable which would be run if the given *cmd*
+ was called. If no *cmd* would be called, return ``None``.
*mode* is a permission mask passed a to :func:`os.access`, by default
determining if the file exists and executable.
diff --git a/Lib/shutil.py b/Lib/shutil.py
index cb8d23f..8da46d1 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -1000,7 +1000,7 @@
seen = set()
for dir in path:
- dir = os.path.normcase(os.path.abspath(dir))
+ dir = os.path.normcase(dir)
if not dir in seen:
seen.add(dir)
for thefile in files:
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
index 96084ec..559f05b 100644
--- a/Lib/test/test_shutil.py
+++ b/Lib/test/test_shutil.py
@@ -1157,6 +1157,16 @@
rv = shutil.which(self.file, path=self.dir, mode=os.W_OK)
self.assertIsNone(rv)
+ def test_relative(self):
+ old_cwd = os.getcwd()
+ base_dir, tail_dir = os.path.split(self.dir)
+ os.chdir(base_dir)
+ try:
+ rv = shutil.which(self.file, path=tail_dir)
+ self.assertEqual(rv, os.path.join(tail_dir, self.file))
+ finally:
+ os.chdir(old_cwd)
+
def test_nonexistent_file(self):
# Return None when no matching executable file is found on the path.
rv = shutil.which("foo.exe", path=self.dir)