mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
GH-113528: Speed up pathlib ABC tests. (#113788)
- Add `__slots__` to dummy path classes. - Return namedtuple rather than `os.stat_result` from `DummyPath.stat()`. - Reduce maximum symlink count in `DummyPathWithSymlinks.resolve()`.
This commit is contained in:
parent
bc71ae2b97
commit
b3dba18eab
2 changed files with 20 additions and 6 deletions
|
@ -10,9 +10,6 @@ from stat import S_ISDIR, S_ISLNK, S_ISREG, S_ISSOCK, S_ISBLK, S_ISCHR, S_ISFIFO
|
||||||
# Internals
|
# Internals
|
||||||
#
|
#
|
||||||
|
|
||||||
# Maximum number of symlinks to follow in PathBase.resolve()
|
|
||||||
_MAX_SYMLINKS = 40
|
|
||||||
|
|
||||||
# Reference for Windows paths can be found at
|
# Reference for Windows paths can be found at
|
||||||
# https://learn.microsoft.com/en-gb/windows/win32/fileio/naming-a-file .
|
# https://learn.microsoft.com/en-gb/windows/win32/fileio/naming-a-file .
|
||||||
_WIN_RESERVED_NAMES = frozenset(
|
_WIN_RESERVED_NAMES = frozenset(
|
||||||
|
@ -500,6 +497,9 @@ class PathBase(PurePathBase):
|
||||||
"""
|
"""
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
# Maximum number of symlinks to follow in resolve()
|
||||||
|
_max_symlinks = 40
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _unsupported(cls, method_name):
|
def _unsupported(cls, method_name):
|
||||||
msg = f"{cls.__name__}.{method_name}() is unsupported"
|
msg = f"{cls.__name__}.{method_name}() is unsupported"
|
||||||
|
@ -971,7 +971,7 @@ class PathBase(PurePathBase):
|
||||||
# Like Linux and macOS, raise OSError(errno.ELOOP) if too many symlinks are
|
# Like Linux and macOS, raise OSError(errno.ELOOP) if too many symlinks are
|
||||||
# encountered during resolution.
|
# encountered during resolution.
|
||||||
link_count += 1
|
link_count += 1
|
||||||
if link_count >= _MAX_SYMLINKS:
|
if link_count >= self._max_symlinks:
|
||||||
raise OSError(ELOOP, "Too many symbolic links in path", str(self))
|
raise OSError(ELOOP, "Too many symbolic links in path", str(self))
|
||||||
target, target_parts = next_path.readlink()._split_stack()
|
target, target_parts = next_path.readlink()._split_stack()
|
||||||
# If the symlink target is absolute (like '/etc/hosts'), set the current
|
# If the symlink target is absolute (like '/etc/hosts'), set the current
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import collections.abc
|
import collections
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
import errno
|
import errno
|
||||||
|
@ -43,6 +43,8 @@ class PurePathBaseTest(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
class DummyPurePath(PurePathBase):
|
class DummyPurePath(PurePathBase):
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not isinstance(other, DummyPurePath):
|
if not isinstance(other, DummyPurePath):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
@ -660,11 +662,18 @@ class DummyPathIO(io.BytesIO):
|
||||||
super().close()
|
super().close()
|
||||||
|
|
||||||
|
|
||||||
|
DummyPathStatResult = collections.namedtuple(
|
||||||
|
'DummyPathStatResult',
|
||||||
|
'st_mode st_ino st_dev st_nlink st_uid st_gid st_size st_atime st_mtime st_ctime')
|
||||||
|
|
||||||
|
|
||||||
class DummyPath(PathBase):
|
class DummyPath(PathBase):
|
||||||
"""
|
"""
|
||||||
Simple implementation of PathBase that keeps files and directories in
|
Simple implementation of PathBase that keeps files and directories in
|
||||||
memory.
|
memory.
|
||||||
"""
|
"""
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
_files = {}
|
_files = {}
|
||||||
_directories = {}
|
_directories = {}
|
||||||
_symlinks = {}
|
_symlinks = {}
|
||||||
|
@ -693,7 +702,7 @@ class DummyPath(PathBase):
|
||||||
st_mode = stat.S_IFLNK
|
st_mode = stat.S_IFLNK
|
||||||
else:
|
else:
|
||||||
raise FileNotFoundError(errno.ENOENT, "Not found", str(self))
|
raise FileNotFoundError(errno.ENOENT, "Not found", str(self))
|
||||||
return os.stat_result((st_mode, hash(str(self)), 0, 0, 0, 0, 0, 0, 0, 0))
|
return DummyPathStatResult(st_mode, hash(str(self)), 0, 0, 0, 0, 0, 0, 0, 0)
|
||||||
|
|
||||||
def open(self, mode='r', buffering=-1, encoding=None,
|
def open(self, mode='r', buffering=-1, encoding=None,
|
||||||
errors=None, newline=None):
|
errors=None, newline=None):
|
||||||
|
@ -1728,6 +1737,11 @@ class DummyPathTest(DummyPurePathTest):
|
||||||
|
|
||||||
|
|
||||||
class DummyPathWithSymlinks(DummyPath):
|
class DummyPathWithSymlinks(DummyPath):
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
# Reduce symlink traversal limit to make tests run faster.
|
||||||
|
_max_symlinks = 20
|
||||||
|
|
||||||
def readlink(self):
|
def readlink(self):
|
||||||
path = str(self.parent.resolve() / self.name)
|
path = str(self.parent.resolve() / self.name)
|
||||||
if path in self._symlinks:
|
if path in self._symlinks:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue