Skip to content

Commit c09307d

Browse files
committed
pythonGH-127456: pathlib ABCs: remove ParserBase.sep
Remove `ParserBase.sep`, which is the class's only non-method member. Instead, we compute the separator from `PathBase.__init_subclass__()` by calling `parser.join('a', 'a').strip('a')`, and store the result on the subclass as `cls._sep`. We also set `cls._case_sensitive` according to `parser.normcase('Aa') == 'Aa'`, which was previously done in a caching function.
1 parent 31c9f3c commit c09307d

2 files changed

Lines changed: 15 additions & 21 deletions

File tree

‎Lib/pathlib/_abc.py‎

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
resemble pathlib's PurePath and Path respectively.
1212
"""
1313

14-
import functools
1514
import operator
1615
from errno import EINVAL
1716
from glob import _GlobberBase, _no_recurse_symlinks
@@ -28,12 +27,6 @@ class UnsupportedOperation(NotImplementedError):
2827
pass
2928

3029

31-
@functools.cache
32-
def _is_case_sensitive(parser):
33-
return parser.normcase('Aa') == 'Aa'
34-
35-
36-
3730
class ParserBase:
3831
"""Base class for path parsers, which do low-level path manipulation.
3932
@@ -48,11 +41,6 @@ class ParserBase:
4841
def _unsupported_msg(cls, attribute):
4942
return f"{cls.__name__}.{attribute} is unsupported"
5043

51-
@property
52-
def sep(self):
53-
"""The character used to separate path components."""
54-
raise UnsupportedOperation(self._unsupported_msg('sep'))
55-
5644
def join(self, path, *paths):
5745
"""Join path segments."""
5846
raise UnsupportedOperation(self._unsupported_msg('join()'))
@@ -116,8 +104,16 @@ class PurePathBase:
116104
'_raw_paths',
117105
)
118106
parser = ParserBase()
107+
_sep = '/'
108+
_case_sensitive = True
119109
_globber = PathGlobber
120110

111+
def __init_subclass__(cls):
112+
super().__init_subclass__()
113+
if 'parser' in cls.__dict__:
114+
cls._sep = cls.parser.join('a', 'a').strip('a')
115+
cls._case_sensitive = cls.parser.normcase('Aa') == 'Aa'
116+
121117
def __init__(self, *args):
122118
for arg in args:
123119
if not isinstance(arg, str):
@@ -152,7 +148,7 @@ def __str__(self):
152148
def as_posix(self):
153149
"""Return the string representation of the path with forward (/)
154150
slashes."""
155-
return str(self).replace(self.parser.sep, '/')
151+
return str(self).replace(self._sep, '/')
156152

157153
@property
158154
def drive(self):
@@ -368,8 +364,8 @@ def match(self, path_pattern, *, case_sensitive=None):
368364
if not isinstance(path_pattern, PurePathBase):
369365
path_pattern = self.with_segments(path_pattern)
370366
if case_sensitive is None:
371-
case_sensitive = _is_case_sensitive(self.parser)
372-
sep = path_pattern.parser.sep
367+
case_sensitive = self._case_sensitive
368+
sep = path_pattern._sep
373369
path_parts = self.parts[::-1]
374370
pattern_parts = path_pattern.parts[::-1]
375371
if not pattern_parts:
@@ -393,8 +389,8 @@ def full_match(self, pattern, *, case_sensitive=None):
393389
if not isinstance(pattern, PurePathBase):
394390
pattern = self.with_segments(pattern)
395391
if case_sensitive is None:
396-
case_sensitive = _is_case_sensitive(self.parser)
397-
globber = self._globber(pattern.parser.sep, case_sensitive, recursive=True)
392+
case_sensitive = self._case_sensitive
393+
globber = self._globber(pattern._sep, case_sensitive, recursive=True)
398394
match = globber.compile(pattern._pattern_str)
399395
return match(self._pattern_str) is not None
400396

@@ -639,15 +635,15 @@ def iterdir(self):
639635

640636
def _glob_selector(self, parts, case_sensitive, recurse_symlinks):
641637
if case_sensitive is None:
642-
case_sensitive = _is_case_sensitive(self.parser)
638+
case_sensitive = self._case_sensitive
643639
case_pedantic = False
644640
else:
645641
# The user has expressed a case sensitivity choice, but we don't
646642
# know the case sensitivity of the underlying filesystem, so we
647643
# must use scandir() for everything, including non-wildcard parts.
648644
case_pedantic = True
649645
recursive = True if recurse_symlinks else _no_recurse_symlinks
650-
globber = self._globber(self.parser.sep, case_sensitive, case_pedantic, recursive)
646+
globber = self._globber(self._sep, case_sensitive, case_pedantic, recursive)
651647
return globber.selector(parts)
652648

653649
def glob(self, pattern, *, case_sensitive=None, recurse_symlinks=True):

‎Lib/test/test_pathlib/test_pathlib_abc.py‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ class ParserBaseTest(unittest.TestCase):
3838
def test_unsupported_operation(self):
3939
m = self.cls()
4040
e = UnsupportedOperation
41-
with self.assertRaises(e):
42-
m.sep
4341
self.assertRaises(e, m.join, 'foo')
4442
self.assertRaises(e, m.split, 'foo')
4543
self.assertRaises(e, m.splitdrive, 'foo')

0 commit comments

Comments
 (0)