Skip to content

Commit

Permalink
Process pattern as a stack.
Browse files Browse the repository at this point in the history
  • Loading branch information
barneygale committed Jan 20, 2024
1 parent 3eb53bc commit 980e4f3
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 18 deletions.
5 changes: 3 additions & 2 deletions Lib/pathlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,8 @@ def as_uri(self):
return prefix + quote_from_bytes(os.fsencode(path))

@property
def _pattern_parts(self):
"""List of path components, to be used with patterns in glob()."""
def _pattern_stack(self):
"""Stack of path components, to be used with patterns in glob()."""
parts = self._tail.copy()
pattern = self._raw_path
if pattern.endswith('**'):
Expand All @@ -483,6 +483,7 @@ def _pattern_parts(self):
elif pattern[-1] in (self.pathmod.sep, self.pathmod.altsep):
# GH-65238: pathlib doesn't preserve trailing slash. Add it back.
parts.append('')
parts.reverse()
return parts


Expand Down
29 changes: 13 additions & 16 deletions Lib/pathlib/_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,9 +428,9 @@ def is_absolute(self):
return self.pathmod.isabs(self._raw_path)

@property
def _pattern_parts(self):
"""List of path components, to be used with patterns in glob()."""
return list(self.parts)
def _pattern_stack(self):
"""Stack of path components, to be used with patterns in glob()."""
return self._stack[1]

def match(self, path_pattern, *, case_sensitive=None):
"""
Expand Down Expand Up @@ -738,8 +738,6 @@ def glob(self, pattern, *, case_sensitive=None, follow_symlinks=None):
elif not pattern.parts:
raise ValueError("Unacceptable pattern: {!r}".format(pattern))

pattern_parts = pattern._pattern_parts

if case_sensitive is None:
# TODO: evaluate case-sensitivity of each directory in _select_children().
case_sensitive = _is_case_sensitive(self.pathmod)
Expand All @@ -751,26 +749,25 @@ def glob(self, pattern, *, case_sensitive=None, follow_symlinks=None):
# build a `re.Pattern` object. This pattern is used to filter the
# recursive walk. As a result, pattern parts following a '**' wildcard
# do not perform any filesystem access, which can be much faster!
filter_paths = follow_symlinks is not None and '..' not in pattern_parts
stack = pattern._pattern_stack
filter_paths = follow_symlinks is not None and '..' not in stack
deduplicate_paths = False
sep = self.pathmod.sep
paths = iter([self.joinpath('')] if self.is_dir() else [])
part_idx = 0
while part_idx < len(pattern_parts):
part = pattern_parts[part_idx]
part_idx += 1
while stack:
part = stack.pop()
if part == '':
# Trailing slash.
pass
elif part == '..':
paths = (path._make_child_relpath('..') for path in paths)
elif part == '**':
# Consume adjacent '**' components.
while part_idx < len(pattern_parts) and pattern_parts[part_idx] == '**':
part_idx += 1
while stack and stack[-1] == '**':
stack.pop()

if filter_paths and part_idx < len(pattern_parts) and pattern_parts[part_idx] != '':
dir_only = pattern_parts[-1] == ''
if filter_paths and stack and stack[-1] != '':
dir_only = stack[0] == ''
paths = _select_recursive(paths, dir_only, follow_symlinks)

# Filter out paths that don't match pattern.
Expand All @@ -779,7 +776,7 @@ def glob(self, pattern, *, case_sensitive=None, follow_symlinks=None):
paths = (path for path in paths if match(str(path), prefix_len))
return paths

dir_only = part_idx < len(pattern_parts)
dir_only = bool(stack)
paths = _select_recursive(paths, dir_only, follow_symlinks)
if deduplicate_paths:
# De-duplicate if we've already seen a '**' component.
Expand All @@ -788,7 +785,7 @@ def glob(self, pattern, *, case_sensitive=None, follow_symlinks=None):
elif '**' in part:
raise ValueError("Invalid pattern: '**' can only be an entire path component")
else:
dir_only = part_idx < len(pattern_parts)
dir_only = bool(stack)
match = _compile_pattern(part, sep, case_sensitive)
paths = _select_children(paths, dir_only, follow_symlinks, match)
return paths
Expand Down

0 comments on commit 980e4f3

Please sign in to comment.