diff options
author | Barney Gale <barney.gale@gmail.com> | 2021-04-28 16:50:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-28 16:50:17 +0100 |
commit | baecfbd849dbf42360d3a84af6cc13160838f24d (patch) | |
tree | 5d82a6504cd2859197e1bcd81ceaecef035a6aad /Lib/posixpath.py | |
parent | 859577c24981d6b36960d309f99f7fc810fe75c2 (diff) | |
download | cpython-baecfbd849dbf42360d3a84af6cc13160838f24d.tar.gz cpython-baecfbd849dbf42360d3a84af6cc13160838f24d.zip |
bpo-43757: Make pathlib use os.path.realpath() to resolve symlinks in a path (GH-25264)
Also adds a new "strict" argument to realpath() to avoid changing the default behaviour of pathlib while sharing the implementation.
Diffstat (limited to 'Lib/posixpath.py')
-rw-r--r-- | Lib/posixpath.py | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/Lib/posixpath.py b/Lib/posixpath.py index 62afbd0ccf0..259baa64b19 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -387,16 +387,16 @@ def abspath(path): # Return a canonical path (i.e. the absolute location of a file on the # filesystem). -def realpath(filename): +def realpath(filename, *, strict=False): """Return the canonical path of the specified filename, eliminating any symbolic links encountered in the path.""" filename = os.fspath(filename) - path, ok = _joinrealpath(filename[:0], filename, {}) + path, ok = _joinrealpath(filename[:0], filename, strict, {}) return abspath(path) # Join two paths, normalizing and eliminating any symbolic links # encountered in the second path. -def _joinrealpath(path, rest, seen): +def _joinrealpath(path, rest, strict, seen): if isinstance(path, bytes): sep = b'/' curdir = b'.' @@ -425,7 +425,15 @@ def _joinrealpath(path, rest, seen): path = pardir continue newpath = join(path, name) - if not islink(newpath): + try: + st = os.lstat(newpath) + except OSError: + if strict: + raise + is_link = False + else: + is_link = stat.S_ISLNK(st.st_mode) + if not is_link: path = newpath continue # Resolve the symbolic link @@ -436,10 +444,14 @@ def _joinrealpath(path, rest, seen): # use cached value continue # The symlink is not resolved, so we must have a symlink loop. - # Return already resolved part + rest of the path unchanged. - return join(newpath, rest), False + if strict: + # Raise OSError(errno.ELOOP) + os.stat(newpath) + else: + # Return already resolved part + rest of the path unchanged. + return join(newpath, rest), False seen[newpath] = None # not resolved symlink - path, ok = _joinrealpath(path, os.readlink(newpath), seen) + path, ok = _joinrealpath(path, os.readlink(newpath), strict, seen) if not ok: return join(path, rest), False seen[newpath] = path # resolved symlink |