diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py index f68685f21d6d79..28483f554a26c4 100644 --- a/Lib/pathlib/_abc.py +++ b/Lib/pathlib/_abc.py @@ -11,7 +11,6 @@ resemble pathlib's PurePath and Path respectively. """ -import functools import operator import posixpath from errno import EINVAL @@ -29,11 +28,6 @@ class UnsupportedOperation(NotImplementedError): pass -@functools.cache -def _is_case_sensitive(parser): - return parser.normcase('Aa') == 'Aa' - - class PathGlobber(_GlobberBase): """ Class providing shell-style globbing for path objects. @@ -64,8 +58,16 @@ class PurePathBase: '_raw_paths', ) parser = posixpath + _sep = '/' + _case_sensitive = True _globber = PathGlobber + def __init_subclass__(cls): + super().__init_subclass__() + if 'parser' in cls.__dict__: + cls._sep = cls.parser.join('a', 'a').strip('a') + cls._case_sensitive = cls.parser.normcase('Aa') == 'Aa' + def __init__(self, *args): for arg in args: if not isinstance(arg, str): @@ -100,7 +102,7 @@ def __str__(self): def as_posix(self): """Return the string representation of the path with forward (/) slashes.""" - return str(self).replace(self.parser.sep, '/') + return str(self).replace(self._sep, '/') @property def drive(self): @@ -316,8 +318,8 @@ def match(self, path_pattern, *, case_sensitive=None): if not isinstance(path_pattern, PurePathBase): path_pattern = self.with_segments(path_pattern) if case_sensitive is None: - case_sensitive = _is_case_sensitive(self.parser) - sep = path_pattern.parser.sep + case_sensitive = self._case_sensitive + sep = path_pattern._sep path_parts = self.parts[::-1] pattern_parts = path_pattern.parts[::-1] if not pattern_parts: @@ -341,8 +343,8 @@ def full_match(self, pattern, *, case_sensitive=None): if not isinstance(pattern, PurePathBase): pattern = self.with_segments(pattern) if case_sensitive is None: - case_sensitive = _is_case_sensitive(self.parser) - globber = self._globber(pattern.parser.sep, case_sensitive, recursive=True) + case_sensitive = self._case_sensitive + globber = self._globber(pattern._sep, case_sensitive, recursive=True) match = globber.compile(pattern._pattern_str) return match(self._pattern_str) is not None @@ -587,7 +589,7 @@ def iterdir(self): def _glob_selector(self, parts, case_sensitive, recurse_symlinks): if case_sensitive is None: - case_sensitive = _is_case_sensitive(self.parser) + case_sensitive = self._case_sensitive case_pedantic = False else: # The user has expressed a case sensitivity choice, but we don't @@ -595,7 +597,7 @@ def _glob_selector(self, parts, case_sensitive, recurse_symlinks): # must use scandir() for everything, including non-wildcard parts. case_pedantic = True recursive = True if recurse_symlinks else _no_recurse_symlinks - globber = self._globber(self.parser.sep, case_sensitive, case_pedantic, recursive) + globber = self._globber(self._sep, case_sensitive, case_pedantic, recursive) return globber.selector(parts) def glob(self, pattern, *, case_sensitive=None, recurse_symlinks=True): diff --git a/Lib/pathlib/_types.py b/Lib/pathlib/_types.py index 60df94d0b46049..6548c7d4fb6855 100644 --- a/Lib/pathlib/_types.py +++ b/Lib/pathlib/_types.py @@ -13,7 +13,6 @@ class Parser(Protocol): subclass references its path parser via a 'parser' class attribute. """ - sep: str def join(self, path: str, *paths: str) -> str: ... def split(self, path: str) -> tuple[str, str]: ... def splitdrive(self, path: str) -> tuple[str, str]: ...