diff options
author | Barney Gale <barney.gale@gmail.com> | 2023-05-02 21:51:18 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-02 21:51:18 (GMT) |
commit | 47770a1e91d096fd1c689eb0c78b0f9e76b43639 (patch) | |
tree | 31b43ddb067af17f1313afb8528289cdce94c681 /Lib | |
parent | 1f5384434dce013b5dcf7e7ea3ec5312d13bba72 (diff) | |
download | cpython-47770a1e91d096fd1c689eb0c78b0f9e76b43639.zip cpython-47770a1e91d096fd1c689eb0c78b0f9e76b43639.tar.gz cpython-47770a1e91d096fd1c689eb0c78b0f9e76b43639.tar.bz2 |
GH-104104: Optimize `pathlib.Path.glob()` by avoiding repeated calls to `os.path.normcase()` (GH-104105)
Use `re.IGNORECASE` to implement case-insensitive matching. This
restores behaviour from before GH-31691.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/pathlib.py | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 8eb0894..61e7f3e 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -59,6 +59,9 @@ def _is_wildcard_pattern(pat): # be looked up directly as a file. return "*" in pat or "?" in pat or "[" in pat +def _is_case_sensitive(flavour): + return flavour.normcase('Aa') == 'Aa' + # # Globbing helpers # @@ -100,15 +103,14 @@ class _Selector: is_dir = path_cls.is_dir exists = path_cls.exists scandir = path_cls._scandir - normcase = path_cls._flavour.normcase if not is_dir(parent_path): return iter([]) - return self._select_from(parent_path, is_dir, exists, scandir, normcase) + return self._select_from(parent_path, is_dir, exists, scandir) class _TerminatingSelector: - def _select_from(self, parent_path, is_dir, exists, scandir, normcase): + def _select_from(self, parent_path, is_dir, exists, scandir): yield parent_path @@ -118,11 +120,11 @@ class _PreciseSelector(_Selector): self.name = name _Selector.__init__(self, child_parts, flavour) - def _select_from(self, parent_path, is_dir, exists, scandir, normcase): + def _select_from(self, parent_path, is_dir, exists, scandir): try: path = parent_path._make_child_relpath(self.name) if (is_dir if self.dironly else exists)(path): - for p in self.successor._select_from(path, is_dir, exists, scandir, normcase): + for p in self.successor._select_from(path, is_dir, exists, scandir): yield p except PermissionError: return @@ -131,10 +133,11 @@ class _PreciseSelector(_Selector): class _WildcardSelector(_Selector): def __init__(self, pat, child_parts, flavour): - self.match = re.compile(fnmatch.translate(flavour.normcase(pat))).fullmatch + flags = re.NOFLAG if _is_case_sensitive(flavour) else re.IGNORECASE + self.match = re.compile(fnmatch.translate(pat), flags=flags).fullmatch _Selector.__init__(self, child_parts, flavour) - def _select_from(self, parent_path, is_dir, exists, scandir, normcase): + def _select_from(self, parent_path, is_dir, exists, scandir): try: # We must close the scandir() object before proceeding to # avoid exhausting file descriptors when globbing deep trees. @@ -153,9 +156,9 @@ class _WildcardSelector(_Selector): raise continue name = entry.name - if self.match(normcase(name)): + if self.match(name): path = parent_path._make_child_relpath(name) - for p in self.successor._select_from(path, is_dir, exists, scandir, normcase): + for p in self.successor._select_from(path, is_dir, exists, scandir): yield p except PermissionError: return @@ -187,13 +190,13 @@ class _RecursiveWildcardSelector(_Selector): except PermissionError: return - def _select_from(self, parent_path, is_dir, exists, scandir, normcase): + def _select_from(self, parent_path, is_dir, exists, scandir): try: yielded = set() try: successor_select = self.successor._select_from for starting_point in self._iterate_directories(parent_path, is_dir, scandir): - for p in successor_select(starting_point, is_dir, exists, scandir, normcase): + for p in successor_select(starting_point, is_dir, exists, scandir): if p not in yielded: yield p yielded.add(p) |