mirror of
https://github.com/python/cpython.git
synced 2025-08-10 03:49:18 +00:00
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.
This commit is contained in:
parent
0fc4063747
commit
31c9f3ced2
3 changed files with 599 additions and 731 deletions
|
@ -13,7 +13,6 @@ resemble pathlib's PurePath and Path respectively.
|
|||
|
||||
import functools
|
||||
import operator
|
||||
import posixpath
|
||||
from errno import EINVAL
|
||||
from glob import _GlobberBase, _no_recurse_symlinks
|
||||
from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
|
||||
|
@ -115,11 +114,6 @@ class PurePathBase:
|
|||
# The `_raw_paths` slot stores unjoined string paths. This is set in
|
||||
# the `__init__()` method.
|
||||
'_raw_paths',
|
||||
|
||||
# The '_resolving' slot stores a boolean indicating whether the path
|
||||
# is being processed by `PathBase.resolve()`. This prevents duplicate
|
||||
# work from occurring when `resolve()` calls `stat()` or `readlink()`.
|
||||
'_resolving',
|
||||
)
|
||||
parser = ParserBase()
|
||||
_globber = PathGlobber
|
||||
|
@ -130,7 +124,6 @@ class PurePathBase:
|
|||
raise TypeError(
|
||||
f"argument should be a str, not {type(arg).__name__!r}")
|
||||
self._raw_paths = list(args)
|
||||
self._resolving = False
|
||||
|
||||
def with_segments(self, *pathsegments):
|
||||
"""Construct a new path object from any number of path-like objects.
|
||||
|
@ -339,9 +332,7 @@ class PurePathBase:
|
|||
path = str(self)
|
||||
parent = self.parser.split(path)[0]
|
||||
if path != parent:
|
||||
parent = self.with_segments(parent)
|
||||
parent._resolving = self._resolving
|
||||
return parent
|
||||
return self.with_segments(parent)
|
||||
return self
|
||||
|
||||
@property
|
||||
|
@ -424,9 +415,6 @@ class PathBase(PurePathBase):
|
|||
"""
|
||||
__slots__ = ()
|
||||
|
||||
# Maximum number of symlinks to follow in resolve()
|
||||
_max_symlinks = 40
|
||||
|
||||
@classmethod
|
||||
def _unsupported_msg(cls, attribute):
|
||||
return f"{cls.__name__}.{attribute} is unsupported"
|
||||
|
@ -720,20 +708,6 @@ class PathBase(PurePathBase):
|
|||
yield path, dirnames, filenames
|
||||
paths += [path.joinpath(d) for d in reversed(dirnames)]
|
||||
|
||||
def absolute(self):
|
||||
"""Return an absolute version of this path
|
||||
No normalization or symlink resolution is performed.
|
||||
|
||||
Use resolve() to resolve symlinks and remove '..' segments.
|
||||
"""
|
||||
if self.is_absolute():
|
||||
return self
|
||||
elif self.parser is not posixpath:
|
||||
raise UnsupportedOperation(self._unsupported_msg('absolute()'))
|
||||
else:
|
||||
# Treat the root directory as the current working directory.
|
||||
return self.with_segments('/', *self._raw_paths)
|
||||
|
||||
def expanduser(self):
|
||||
""" Return a new path with expanded ~ and ~user constructs
|
||||
(as returned by os.path.expanduser)
|
||||
|
@ -745,42 +719,6 @@ class PathBase(PurePathBase):
|
|||
Return the path to which the symbolic link points.
|
||||
"""
|
||||
raise UnsupportedOperation(self._unsupported_msg('readlink()'))
|
||||
readlink._supported = False
|
||||
|
||||
def resolve(self, strict=False):
|
||||
"""
|
||||
Make the path absolute, resolving all symlinks on the way and also
|
||||
normalizing it.
|
||||
"""
|
||||
if self._resolving:
|
||||
return self
|
||||
elif self.parser is not posixpath:
|
||||
raise UnsupportedOperation(self._unsupported_msg('resolve()'))
|
||||
|
||||
def raise_error(*args):
|
||||
raise OSError("Unsupported operation.")
|
||||
|
||||
getcwd = raise_error
|
||||
if strict or getattr(self.readlink, '_supported', True):
|
||||
def lstat(path_str):
|
||||
path = self.with_segments(path_str)
|
||||
path._resolving = True
|
||||
return path.stat(follow_symlinks=False)
|
||||
|
||||
def readlink(path_str):
|
||||
path = self.with_segments(path_str)
|
||||
path._resolving = True
|
||||
return str(path.readlink())
|
||||
else:
|
||||
# If the user has *not* overridden the `readlink()` method, then
|
||||
# symlinks are unsupported and (in non-strict mode) we can improve
|
||||
# performance by not calling `path.lstat()`.
|
||||
lstat = readlink = raise_error
|
||||
|
||||
return self.with_segments(posixpath._realpath(
|
||||
str(self.absolute()), strict, self.parser.sep,
|
||||
getcwd=getcwd, lstat=lstat, readlink=readlink,
|
||||
maxlinks=self._max_symlinks))
|
||||
|
||||
def symlink_to(self, target, target_is_directory=False):
|
||||
"""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue