1111resemble pathlib's PurePath and Path respectively.
1212"""
1313
14- import functools
1514import operator
1615from errno import EINVAL
1716from 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-
3730class 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 ):
0 commit comments