mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
GH-113528: Deoptimise pathlib._abc.PurePathBase.parent
(#113530)
Replace use of `_from_parsed_parts()` with `with_segments()`, and move assignments to `_drv`, `_root`, _tail_cached` and `_str` slots into `PurePath`.
This commit is contained in:
parent
1e914ad89d
commit
37bd893a22
2 changed files with 63 additions and 42 deletions
|
@ -2,7 +2,6 @@ import functools
|
|||
import ntpath
|
||||
import posixpath
|
||||
import sys
|
||||
from _collections_abc import Sequence
|
||||
from errno import ENOENT, ENOTDIR, EBADF, ELOOP, EINVAL
|
||||
from itertools import chain
|
||||
from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
|
||||
|
@ -138,35 +137,6 @@ class UnsupportedOperation(NotImplementedError):
|
|||
pass
|
||||
|
||||
|
||||
class _PathParents(Sequence):
|
||||
"""This object provides sequence-like access to the logical ancestors
|
||||
of a path. Don't try to construct it yourself."""
|
||||
__slots__ = ('_path', '_drv', '_root', '_tail')
|
||||
|
||||
def __init__(self, path):
|
||||
self._path = path
|
||||
self._drv = path.drive
|
||||
self._root = path.root
|
||||
self._tail = path._tail
|
||||
|
||||
def __len__(self):
|
||||
return len(self._tail)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
if isinstance(idx, slice):
|
||||
return tuple(self[i] for i in range(*idx.indices(len(self))))
|
||||
|
||||
if idx >= len(self) or idx < -len(self):
|
||||
raise IndexError(idx)
|
||||
if idx < 0:
|
||||
idx += len(self)
|
||||
return self._path._from_parsed_parts(self._drv, self._root,
|
||||
self._tail[:-idx - 1])
|
||||
|
||||
def __repr__(self):
|
||||
return "<{}.parents>".format(type(self._path).__name__)
|
||||
|
||||
|
||||
class PurePathBase:
|
||||
"""Base class for pure path objects.
|
||||
|
||||
|
@ -442,21 +412,26 @@ class PurePathBase:
|
|||
@property
|
||||
def parent(self):
|
||||
"""The logical parent of the path."""
|
||||
drv = self.drive
|
||||
root = self.root
|
||||
tail = self._tail
|
||||
if not tail:
|
||||
return self
|
||||
path = self._from_parsed_parts(drv, root, tail[:-1])
|
||||
path._resolving = self._resolving
|
||||
return path
|
||||
path = str(self)
|
||||
parent = self.pathmod.dirname(path)
|
||||
if path != parent:
|
||||
parent = self.with_segments(parent)
|
||||
parent._resolving = self._resolving
|
||||
return parent
|
||||
return self
|
||||
|
||||
@property
|
||||
def parents(self):
|
||||
"""A sequence of this path's logical parents."""
|
||||
# The value of this property should not be cached on the path object,
|
||||
# as doing so would introduce a reference cycle.
|
||||
return _PathParents(self)
|
||||
dirname = self.pathmod.dirname
|
||||
path = str(self)
|
||||
parent = dirname(path)
|
||||
parents = []
|
||||
while path != parent:
|
||||
parents.append(self.with_segments(parent))
|
||||
path = parent
|
||||
parent = dirname(path)
|
||||
return tuple(parents)
|
||||
|
||||
def is_absolute(self):
|
||||
"""True if the path is absolute (has both a root and, if applicable,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue