diff options
author | Cheryl Sabella <cheryl.sabella@gmail.com> | 2019-02-13 11:25:10 (GMT) |
---|---|---|
committer | Victor Stinner <vstinner@redhat.com> | 2019-02-13 11:25:10 (GMT) |
commit | 5680f6546dcda550ad70eefa0a5ebf1375303307 (patch) | |
tree | a939a3f76aa23de3782692c486ec5bc69ea54fce /Lib/shutil.py | |
parent | cfd31f0af20f76849bbec6185efea01c72349f2a (diff) | |
download | cpython-5680f6546dcda550ad70eefa0a5ebf1375303307.zip cpython-5680f6546dcda550ad70eefa0a5ebf1375303307.tar.gz cpython-5680f6546dcda550ad70eefa0a5ebf1375303307.tar.bz2 |
bpo-18283: Add support for bytes to shutil.which (GH-11818)
Diffstat (limited to 'Lib/shutil.py')
-rw-r--r-- | Lib/shutil.py | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/Lib/shutil.py b/Lib/shutil.py index 8d0de72..065e08b 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -1279,6 +1279,15 @@ def get_terminal_size(fallback=(80, 24)): return os.terminal_size((columns, lines)) + +# Check that a given file can be accessed with the correct mode. +# Additionally check that `file` is not a directory, as on Windows +# directories pass the os.access check. +def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) + and not os.path.isdir(fn)) + + def which(cmd, mode=os.F_OK | os.X_OK, path=None): """Given a command, mode, and a PATH string, return the path which conforms to the given mode on the PATH, or None if there is no such @@ -1289,13 +1298,6 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None): path. """ - # Check that a given file can be accessed with the correct mode. - # Additionally check that `file` is not a directory, as on Windows - # directories pass the os.access check. - def _access_check(fn, mode): - return (os.path.exists(fn) and os.access(fn, mode) - and not os.path.isdir(fn)) - # If we're given a path with a directory part, look it up directly rather # than referring to PATH directories. This includes checking relative to the # current directory, e.g. ./script @@ -1304,19 +1306,31 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None): return cmd return None + use_bytes = isinstance(cmd, bytes) + if path is None: path = os.environ.get("PATH", os.defpath) if not path: return None - path = path.split(os.pathsep) + if use_bytes: + path = os.fsencode(path) + path = path.split(os.fsencode(os.pathsep)) + else: + path = os.fsdecode(path) + path = path.split(os.pathsep) if sys.platform == "win32": # The current directory takes precedence on Windows. - if not os.curdir in path: - path.insert(0, os.curdir) + curdir = os.curdir + if use_bytes: + curdir = os.fsencode(curdir) + if curdir not in path: + path.insert(0, curdir) # PATHEXT is necessary to check on Windows. pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + if use_bytes: + pathext = [os.fsencode(ext) for ext in pathext] # See if the given file matches any of the expected path extensions. # This will allow us to short circuit when given "python.exe". # If it does match, only test that one, otherwise we have to try |