diff --git a/Lib/glob.py b/Lib/glob.py index 72cf22299763f0..6b8c8a61b65308 100644 --- a/Lib/glob.py +++ b/Lib/glob.py @@ -318,12 +318,13 @@ def translate(pat, *, recursive=False, include_hidden=False, seps=None): return fr'(?s:{res})\Z' -@functools.lru_cache(maxsize=512) -def _compile_pattern(pat, sep, case_sensitive, recursive=True): +@functools.lru_cache(maxsize=1024) +def _compile_pattern(pat, sep, case_sensitive, recursive, include_hidden): """Compile given glob pattern to a re.Pattern object (observing case sensitivity).""" flags = re.NOFLAG if case_sensitive else re.IGNORECASE - regex = translate(pat, recursive=recursive, include_hidden=True, seps=sep) + regex = translate(pat, recursive=recursive, + include_hidden=include_hidden, seps=sep) return re.compile(regex, flags=flags).match @@ -331,11 +332,13 @@ class _Globber: """Class providing shell-style pattern matching and globbing. """ - def __init__(self, sep, case_sensitive, case_pedantic=False, recursive=False): + def __init__(self, sep, case_sensitive, + case_pedantic=False, recursive=False, include_hidden=False): self.sep = sep self.case_sensitive = case_sensitive self.case_pedantic = case_pedantic self.recursive = recursive + self.include_hidden = include_hidden # Low-level methods @@ -361,7 +364,8 @@ def add_slash(pathname): # High-level methods def compile(self, pat): - return _compile_pattern(pat, self.sep, self.case_sensitive, self.recursive) + return _compile_pattern(pat, self.sep, self.case_sensitive, + self.recursive, self.include_hidden) def selector(self, parts): """Returns a function that selects from a given path, walking and @@ -412,7 +416,7 @@ def wildcard_selector(self, part, parts): filtering by pattern. """ - match = None if part == '*' else self.compile(part) + match = None if self.include_hidden and part == '*' else self.compile(part) dir_only = bool(parts) if dir_only: select_next = self.selector(parts) @@ -460,7 +464,7 @@ def recursive_selector(self, part, parts): while parts and parts[-1] not in _special_parts: part += self.sep + parts.pop() - match = None if part == '**' else self.compile(part) + match = None if self.include_hidden and part == '**' else self.compile(part) dir_only = bool(parts) select_next = self.selector(parts) diff --git a/Lib/pathlib/_abc.py b/Lib/pathlib/_abc.py index b51ad6f46d292a..b7166b2b291eaf 100644 --- a/Lib/pathlib/_abc.py +++ b/Lib/pathlib/_abc.py @@ -402,7 +402,7 @@ def match(self, path_pattern, *, case_sensitive=None): return False if len(path_parts) > len(pattern_parts) and path_pattern.anchor: return False - globber = self._globber(sep, case_sensitive) + globber = self._globber(sep, case_sensitive, include_hidden=True) for path_part, pattern_part in zip(path_parts, pattern_parts): match = globber.compile(pattern_part) if match(path_part) is None: @@ -418,7 +418,8 @@ def full_match(self, pattern, *, case_sensitive=None): 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) + globber = self._globber(pattern.parser.sep, case_sensitive, + recursive=True, include_hidden=True) match = globber.compile(pattern._pattern_str) return match(self._pattern_str) is not None @@ -693,7 +694,8 @@ 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 glob._no_recurse_symlinks - globber = self._globber(self.parser.sep, case_sensitive, case_pedantic, recursive) + globber = self._globber(self.parser.sep, case_sensitive, + case_pedantic, recursive, include_hidden=True) return globber.selector(parts) def glob(self, pattern, *, case_sensitive=None, recurse_symlinks=True):