diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-10-21 17:37:15 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-21 17:37:15 (GMT) |
commit | 10ecbadb799ddf3393d1fc80119a3db14724d381 (patch) | |
tree | cc60337c59e1c2e32a7f1564e68faf02cb8ececc /Lib/pathlib.py | |
parent | 1e73945470644202262e1ddee2b49e2708a29794 (diff) | |
download | cpython-10ecbadb799ddf3393d1fc80119a3db14724d381.zip cpython-10ecbadb799ddf3393d1fc80119a3db14724d381.tar.gz cpython-10ecbadb799ddf3393d1fc80119a3db14724d381.tar.bz2 |
bpo-31202: Preserve case of literal parts in Path.glob() on Windows. (GH-16860)
Diffstat (limited to 'Lib/pathlib.py')
-rw-r--r-- | Lib/pathlib.py | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 7bd66c1..67b94e0 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -187,6 +187,9 @@ class _WindowsFlavour(_Flavour): def casefold_parts(self, parts): return [p.lower() for p in parts] + def compile_pattern(self, pattern): + return re.compile(fnmatch.translate(pattern), re.IGNORECASE).fullmatch + def resolve(self, path, strict=False): s = str(path) if not s: @@ -309,6 +312,9 @@ class _PosixFlavour(_Flavour): def casefold_parts(self, parts): return parts + def compile_pattern(self, pattern): + return re.compile(fnmatch.translate(pattern)).fullmatch + def resolve(self, path, strict=False): sep = self.sep accessor = path._accessor @@ -446,7 +452,7 @@ _normal_accessor = _NormalAccessor() # Globbing helpers # -def _make_selector(pattern_parts): +def _make_selector(pattern_parts, flavour): pat = pattern_parts[0] child_parts = pattern_parts[1:] if pat == '**': @@ -457,7 +463,7 @@ def _make_selector(pattern_parts): cls = _WildcardSelector else: cls = _PreciseSelector - return cls(pat, child_parts) + return cls(pat, child_parts, flavour) if hasattr(functools, "lru_cache"): _make_selector = functools.lru_cache()(_make_selector) @@ -467,10 +473,10 @@ class _Selector: """A selector matches a specific glob pattern part against the children of a given path.""" - def __init__(self, child_parts): + def __init__(self, child_parts, flavour): self.child_parts = child_parts if child_parts: - self.successor = _make_selector(child_parts) + self.successor = _make_selector(child_parts, flavour) self.dironly = True else: self.successor = _TerminatingSelector() @@ -496,9 +502,9 @@ class _TerminatingSelector: class _PreciseSelector(_Selector): - def __init__(self, name, child_parts): + def __init__(self, name, child_parts, flavour): self.name = name - _Selector.__init__(self, child_parts) + _Selector.__init__(self, child_parts, flavour) def _select_from(self, parent_path, is_dir, exists, scandir): try: @@ -512,13 +518,12 @@ class _PreciseSelector(_Selector): class _WildcardSelector(_Selector): - def __init__(self, pat, child_parts): - self.pat = re.compile(fnmatch.translate(pat)) - _Selector.__init__(self, child_parts) + def __init__(self, pat, child_parts, flavour): + self.match = flavour.compile_pattern(pat) + _Selector.__init__(self, child_parts, flavour) def _select_from(self, parent_path, is_dir, exists, scandir): try: - cf = parent_path._flavour.casefold entries = list(scandir(parent_path)) for entry in entries: entry_is_dir = False @@ -529,8 +534,7 @@ class _WildcardSelector(_Selector): raise if not self.dironly or entry_is_dir: name = entry.name - casefolded = cf(name) - if self.pat.match(casefolded): + if self.match(name): path = parent_path._make_child_relpath(name) for p in self.successor._select_from(path, is_dir, exists, scandir): yield p @@ -541,8 +545,8 @@ class _WildcardSelector(_Selector): class _RecursiveWildcardSelector(_Selector): - def __init__(self, pat, child_parts): - _Selector.__init__(self, child_parts) + def __init__(self, pat, child_parts, flavour): + _Selector.__init__(self, child_parts, flavour) def _iterate_directories(self, parent_path, is_dir, scandir): yield parent_path @@ -1118,11 +1122,10 @@ class Path(PurePath): """ if not pattern: raise ValueError("Unacceptable pattern: {!r}".format(pattern)) - pattern = self._flavour.casefold(pattern) drv, root, pattern_parts = self._flavour.parse_parts((pattern,)) if drv or root: raise NotImplementedError("Non-relative patterns are unsupported") - selector = _make_selector(tuple(pattern_parts)) + selector = _make_selector(tuple(pattern_parts), self._flavour) for p in selector.select_from(self): yield p @@ -1131,11 +1134,10 @@ class Path(PurePath): directories) matching the given relative pattern, anywhere in this subtree. """ - pattern = self._flavour.casefold(pattern) drv, root, pattern_parts = self._flavour.parse_parts((pattern,)) if drv or root: raise NotImplementedError("Non-relative patterns are unsupported") - selector = _make_selector(("**",) + tuple(pattern_parts)) + selector = _make_selector(("**",) + tuple(pattern_parts), self._flavour) for p in selector.select_from(self): yield p |