mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
[3.9] bpo-43757: Make pathlib use os.path.realpath() to resolve symlinks in a path (GH-25264) (GH-135035)
Also adds a new "strict" argument to realpath() to avoid changing the default behaviour of pathlib while sharing the implementation.
(cherry-picked from commit baecfbd849)
Co-authored-by: Barney Gale <barney.gale@gmail.com>
This commit is contained in:
parent
03ac445b11
commit
00af9794dd
7 changed files with 192 additions and 124 deletions
|
|
@ -385,16 +385,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'.'
|
||||
|
|
@ -423,7 +423,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
|
||||
|
|
@ -434,10 +442,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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue