@@ -25,6 +25,23 @@ def _is_case_sensitive(parser):
2525    return  parser .normcase ('Aa' ) ==  'Aa' 
2626
2727
28+ def  _explode_path (path ):
29+     """ 
30+     Split the path into a 2-tuple (anchor, parts), where *anchor* is the 
31+     uppermost parent of the path (equivalent to path.parents[-1]), and 
32+     *parts* is a reversed list of parts following the anchor. 
33+     """ 
34+     split  =  path .parser .split 
35+     path  =  str (path )
36+     parent , name  =  split (path )
37+     names  =  []
38+     while  path  !=  parent :
39+         names .append (name )
40+         path  =  parent 
41+         parent , name  =  split (path )
42+     return  path , names 
43+ 
44+ 
2845class  PathGlobber (_GlobberBase ):
2946    """ 
3047    Class providing shell-style globbing for path objects. 
@@ -50,7 +67,6 @@ class PurePathBase:
5067
5168    __slots__  =  ()
5269    parser  =  posixpath 
53-     _globber  =  PathGlobber 
5470
5571    def  with_segments (self , * pathsegments ):
5672        """Construct a new path object from any number of path-like objects. 
@@ -82,7 +98,7 @@ def root(self):
8298    @property  
8399    def  anchor (self ):
84100        """The concatenation of the drive and root, or ''.""" 
85-         return  self . _stack [0 ]
101+         return  _explode_path ( self ) [0 ]
86102
87103    @property  
88104    def  name (self ):
@@ -160,8 +176,8 @@ def relative_to(self, other, *, walk_up=False):
160176        """ 
161177        if  not  isinstance (other , PurePathBase ):
162178            other  =  self .with_segments (other )
163-         anchor0 , parts0  =  self . _stack 
164-         anchor1 , parts1  =  other . _stack 
179+         anchor0 , parts0  =  _explode_path ( self ) 
180+         anchor1 , parts1  =  _explode_path ( other ) 
165181        if  anchor0  !=  anchor1 :
166182            raise  ValueError (f"{ str (self )!r} { str (other )!r}  )
167183        while  parts0  and  parts1  and  parts0 [- 1 ] ==  parts1 [- 1 ]:
@@ -183,8 +199,8 @@ def is_relative_to(self, other):
183199        """ 
184200        if  not  isinstance (other , PurePathBase ):
185201            other  =  self .with_segments (other )
186-         anchor0 , parts0  =  self . _stack 
187-         anchor1 , parts1  =  other . _stack 
202+         anchor0 , parts0  =  _explode_path ( self ) 
203+         anchor1 , parts1  =  _explode_path ( other ) 
188204        if  anchor0  !=  anchor1 :
189205            return  False 
190206        while  parts0  and  parts1  and  parts0 [- 1 ] ==  parts1 [- 1 ]:
@@ -199,7 +215,7 @@ def is_relative_to(self, other):
199215    def  parts (self ):
200216        """An object providing sequence-like access to the 
201217        components in the filesystem path.""" 
202-         anchor , parts  =  self . _stack 
218+         anchor , parts  =  _explode_path ( self ) 
203219        if  anchor :
204220            parts .append (anchor )
205221        return  tuple (reversed (parts ))
@@ -224,23 +240,6 @@ def __rtruediv__(self, key):
224240        except  TypeError :
225241            return  NotImplemented 
226242
227-     @property  
228-     def  _stack (self ):
229-         """ 
230-         Split the path into a 2-tuple (anchor, parts), where *anchor* is the 
231-         uppermost parent of the path (equivalent to path.parents[-1]), and 
232-         *parts* is a reversed list of parts following the anchor. 
233-         """ 
234-         split  =  self .parser .split 
235-         path  =  str (self )
236-         parent , name  =  split (path )
237-         names  =  []
238-         while  path  !=  parent :
239-             names .append (name )
240-             path  =  parent 
241-             parent , name  =  split (path )
242-         return  path , names 
243- 
244243    @property  
245244    def  parent (self ):
246245        """The logical parent of the path.""" 
@@ -268,11 +267,6 @@ def is_absolute(self):
268267        a drive).""" 
269268        return  self .parser .isabs (str (self ))
270269
271-     @property  
272-     def  _pattern_str (self ):
273-         """The path expressed as a string, for use in pattern-matching.""" 
274-         return  str (self )
275- 
276270    def  match (self , path_pattern , * , case_sensitive = None ):
277271        """ 
278272        Return True if this path matches the given pattern. If the pattern is 
@@ -293,7 +287,7 @@ def match(self, path_pattern, *, case_sensitive=None):
293287            return  False 
294288        if  len (path_parts ) >  len (pattern_parts ) and  path_pattern .anchor :
295289            return  False 
296-         globber  =  self . _globber (sep , case_sensitive )
290+         globber  =  PathGlobber (sep , case_sensitive )
297291        for  path_part , pattern_part  in  zip (path_parts , pattern_parts ):
298292            match  =  globber .compile (pattern_part )
299293            if  match (path_part ) is  None :
@@ -309,9 +303,9 @@ def full_match(self, pattern, *, case_sensitive=None):
309303            pattern  =  self .with_segments (pattern )
310304        if  case_sensitive  is  None :
311305            case_sensitive  =  _is_case_sensitive (self .parser )
312-         globber  =  self . _globber (pattern .parser .sep , case_sensitive , recursive = True )
313-         match  =  globber .compile (pattern . _pattern_str )
314-         return  match (self . _pattern_str ) is  not None 
306+         globber  =  PathGlobber (pattern .parser .sep , case_sensitive , recursive = True )
307+         match  =  globber .compile (str ( pattern ) )
308+         return  match (str ( self ) ) is  not None 
315309
316310
317311
@@ -463,29 +457,25 @@ def iterdir(self):
463457        """ 
464458        raise  NotImplementedError 
465459
466-     def  _glob_selector (self , parts , case_sensitive , recurse_symlinks ):
467-         if  case_sensitive  is  None :
468-             case_sensitive  =  _is_case_sensitive (self .parser )
469-             case_pedantic  =  False 
470-         else :
471-             # The user has expressed a case sensitivity choice, but we don't 
472-             # know the case sensitivity of the underlying filesystem, so we 
473-             # must use scandir() for everything, including non-wildcard parts. 
474-             case_pedantic  =  True 
475-         recursive  =  True  if  recurse_symlinks  else  _no_recurse_symlinks 
476-         globber  =  self ._globber (self .parser .sep , case_sensitive , case_pedantic , recursive )
477-         return  globber .selector (parts )
478- 
479460    def  glob (self , pattern , * , case_sensitive = None , recurse_symlinks = True ):
480461        """Iterate over this subtree and yield all existing files (of any 
481462        kind, including directories) matching the given relative pattern. 
482463        """ 
483464        if  not  isinstance (pattern , PurePathBase ):
484465            pattern  =  self .with_segments (pattern )
485-         anchor , parts  =  pattern . _stack 
466+         anchor , parts  =  _explode_path ( pattern ) 
486467        if  anchor :
487468            raise  NotImplementedError ("Non-relative patterns are unsupported" )
488-         select  =  self ._glob_selector (parts , case_sensitive , recurse_symlinks )
469+         if  case_sensitive  is  None :
470+             case_sensitive  =  _is_case_sensitive (self .parser )
471+             case_pedantic  =  False 
472+         elif  case_sensitive  ==  _is_case_sensitive (self .parser ):
473+             case_pedantic  =  False 
474+         else :
475+             case_pedantic  =  True 
476+         recursive  =  True  if  recurse_symlinks  else  _no_recurse_symlinks 
477+         globber  =  PathGlobber (self .parser .sep , case_sensitive , case_pedantic , recursive )
478+         select  =  globber .selector (parts )
489479        return  select (self )
490480
491481    def  rglob (self , pattern , * , case_sensitive = None , recurse_symlinks = True ):
0 commit comments