Skip to content

Commit 31c9f3c

Browse files
authored
GH-127381: pathlib ABCs: remove PathBase.resolve() and absolute() (#127707)
Remove our implementation of POSIX path resolution in `PathBase.resolve()`. This functionality is rather fragile and isn't necessary in most cases. It depends on `PathBase.stat()`, which we're looking to remove. Also remove `PathBase.absolute()`. Many legitimate virtual filesystems lack the notion of a 'current directory', so it's wrong to include in the basic interface.
1 parent 0fc4063 commit 31c9f3c

File tree

3 files changed

+599
-731
lines changed

3 files changed

+599
-731
lines changed

Lib/pathlib/_abc.py

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
import functools
1515
import operator
16-
import posixpath
1716
from errno import EINVAL
1817
from glob import _GlobberBase, _no_recurse_symlinks
1918
from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
@@ -115,11 +114,6 @@ class PurePathBase:
115114
# The `_raw_paths` slot stores unjoined string paths. This is set in
116115
# the `__init__()` method.
117116
'_raw_paths',
118-
119-
# The '_resolving' slot stores a boolean indicating whether the path
120-
# is being processed by `PathBase.resolve()`. This prevents duplicate
121-
# work from occurring when `resolve()` calls `stat()` or `readlink()`.
122-
'_resolving',
123117
)
124118
parser = ParserBase()
125119
_globber = PathGlobber
@@ -130,7 +124,6 @@ def __init__(self, *args):
130124
raise TypeError(
131125
f"argument should be a str, not {type(arg).__name__!r}")
132126
self._raw_paths = list(args)
133-
self._resolving = False
134127

135128
def with_segments(self, *pathsegments):
136129
"""Construct a new path object from any number of path-like objects.
@@ -339,9 +332,7 @@ def parent(self):
339332
path = str(self)
340333
parent = self.parser.split(path)[0]
341334
if path != parent:
342-
parent = self.with_segments(parent)
343-
parent._resolving = self._resolving
344-
return parent
335+
return self.with_segments(parent)
345336
return self
346337

347338
@property
@@ -424,9 +415,6 @@ class PathBase(PurePathBase):
424415
"""
425416
__slots__ = ()
426417

427-
# Maximum number of symlinks to follow in resolve()
428-
_max_symlinks = 40
429-
430418
@classmethod
431419
def _unsupported_msg(cls, attribute):
432420
return f"{cls.__name__}.{attribute} is unsupported"
@@ -720,20 +708,6 @@ def walk(self, top_down=True, on_error=None, follow_symlinks=False):
720708
yield path, dirnames, filenames
721709
paths += [path.joinpath(d) for d in reversed(dirnames)]
722710

723-
def absolute(self):
724-
"""Return an absolute version of this path
725-
No normalization or symlink resolution is performed.
726-
727-
Use resolve() to resolve symlinks and remove '..' segments.
728-
"""
729-
if self.is_absolute():
730-
return self
731-
elif self.parser is not posixpath:
732-
raise UnsupportedOperation(self._unsupported_msg('absolute()'))
733-
else:
734-
# Treat the root directory as the current working directory.
735-
return self.with_segments('/', *self._raw_paths)
736-
737711
def expanduser(self):
738712
""" Return a new path with expanded ~ and ~user constructs
739713
(as returned by os.path.expanduser)
@@ -745,42 +719,6 @@ def readlink(self):
745719
Return the path to which the symbolic link points.
746720
"""
747721
raise UnsupportedOperation(self._unsupported_msg('readlink()'))
748-
readlink._supported = False
749-
750-
def resolve(self, strict=False):
751-
"""
752-
Make the path absolute, resolving all symlinks on the way and also
753-
normalizing it.
754-
"""
755-
if self._resolving:
756-
return self
757-
elif self.parser is not posixpath:
758-
raise UnsupportedOperation(self._unsupported_msg('resolve()'))
759-
760-
def raise_error(*args):
761-
raise OSError("Unsupported operation.")
762-
763-
getcwd = raise_error
764-
if strict or getattr(self.readlink, '_supported', True):
765-
def lstat(path_str):
766-
path = self.with_segments(path_str)
767-
path._resolving = True
768-
return path.stat(follow_symlinks=False)
769-
770-
def readlink(path_str):
771-
path = self.with_segments(path_str)
772-
path._resolving = True
773-
return str(path.readlink())
774-
else:
775-
# If the user has *not* overridden the `readlink()` method, then
776-
# symlinks are unsupported and (in non-strict mode) we can improve
777-
# performance by not calling `path.lstat()`.
778-
lstat = readlink = raise_error
779-
780-
return self.with_segments(posixpath._realpath(
781-
str(self.absolute()), strict, self.parser.sep,
782-
getcwd=getcwd, lstat=lstat, readlink=readlink,
783-
maxlinks=self._max_symlinks))
784722

785723
def symlink_to(self, target, target_is_directory=False):
786724
"""

0 commit comments

Comments
 (0)