8000 Restore `_PreciseSelector` · barneygale/cpython@d097f8c · GitHub
[go: up one dir, main page]

Skip to content

Commit d097f8c

Browse files
committed
Restore _PreciseSelector
1 parent c411cfa commit d097f8c

File tree

1 file changed

+45
-25
lines changed

1 file changed

+45
-25
lines changed

Lib/pathlib.py

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def _is_case_sensitive(flavour):
6767
#
6868

6969
@functools.lru_cache()
70-
def _make_selector(pattern_parts, case_sensitive):
70+
def _make_selector(pattern_parts, flavour, case_sensitive):
7171
pat = pattern_parts[0]
7272
child_parts = pattern_parts[1:]
7373
if not pat:
@@ -78,19 +78,21 @@ def _make_selector(pattern_parts, case_sensitive):
7878
cls = _ParentSelector
7979
elif '**' in pat:
8080
raise ValueError("Invalid pattern: '**' can only be an entire path component")
81-
else:
81+
elif _is_wildcard_pattern(pat) or case_sensitive != _is_case_sensitive(flavour):
8282
cls = _WildcardSelector
83-
return cls(pat, child_parts, case_sensitive)
83+
else:
84+
cls = _PreciseSelector
85+
return cls(pat, child_parts, flavour, case_sensitive)
8486

8587

8688
class _Selector:
8789
"""A selector matches a specific glob pattern part against the children
8890
of a given path."""
8991

90-
def __init__(self, child_parts, case_sensitive):
92+
def __init__(self, child_parts, flavour, case_sensitive):
9193
self.child_parts = child_parts
9294
if child_parts:
93-
self.successor = _make_selector(child_parts, case_sensitive)
95+
self.successor = _make_selector(child_parts, flavour, case_sensitive)
9496
self.dironly = True
9597
else:
9698
self.successor = _TerminatingSelector()
@@ -100,37 +102,55 @@ def select_from(self, parent_path):
100102
"""Iterate over all child paths of `parent_path` matched by this
101103
selector. This can contain parent_path itself."""
102104
path_cls = type(parent_path)
105+
is_dir = path_cls.is_dir
106+
exists = path_cls.exists
103107
scandir = path_cls._scandir
104-
if not parent_path.is_dir():
108+
if not is_dir(parent_path):
105109
return iter([])
106-
return self._select_from(parent_path, scandir)
110+
return self._select_from(parent_path, is_dir, exists, scandir)
107111

108112

109113
class _TerminatingSelector:
110114

111-
def _select_from(self, parent_path, scandir):
115+
def _select_from(self, parent_path, is_dir, exists, scandir):
112116
yield parent_path
113117

114118

115119
class _ParentSelector(_Selector):
116120

117-
def __init__(self, name, child_parts, case_sensitive):
118-
_Selector.__init__(self, child_parts, case_sensitive)
121+
def __init__(self, name, child_parts, flavour, case_sensitive):
122+
_Selector.__init__(self, child_parts, flavour, case_sensitive)
119123

120-
def _select_from(self, parent_path, scandir):
124+
def _select_from(self, parent_path, is_dir, exists, scandir):
121125
path = parent_path._make_child_relpath('..')
122-
for p in self.successor._select_from(path, scandir):
126+
for p in self.successor._select_from(path, is_dir, exists, scandir):
123127
yield p
124128

125129

130+
class _PreciseSelector(_Selector):
131+
132+
def __init__(self, name, child_parts, flavour, case_sensitive):
133+
self.name = name
134+
_Selector.__init__(self, child_parts, flavour, case_sensitive)
135+
136+
def _select_from(self, parent_path, is_dir, exists, scandir):
137+
try:
138+
path = parent_path._make_child_relpath(self.name)
139+
if (is_dir if self.dironly else exists)(path):
140+
for p in self.successor._select_from(path, is_dir, exists, scandir):
141+
yield p
142+
except PermissionError:
143+
return
144+
145+
126146
class _WildcardSelector(_Selector):
127147

128-
def __init__(self, pat, child_parts, case_sensitive):
148+
def __init__(self, pat, child_parts, flavour, case_sensitive):
129149
flags = re.NOFLAG if case_sensitive else re.IGNORECASE
130150
self.match = re.compile(fnmatch.translate(pat), flags=flags).fullmatch
131-
_Selector.__init__(self, child_parts, case_sensitive)
151+
_Selector.__init__(self, child_parts, flavour, case_sensitive)
132152

133-
def _select_from(self, parent_path, scandir):
153+
def _select_from(self, parent_path, is_dir, exists, scandir):
134154
try:
135155
# We must close the scandir() object before proceeding to
136156
# avoid exhausting file descriptors when globbing deep trees.
@@ -151,18 +171,18 @@ def _select_from(self, parent_path, scandir):
151171
name = entry.name
152172
if self.match(name):
153173
path = parent_path._make_child_relpath(name)
154-
for p in self.successor._select_from(path, scandir):
174+
for p in self.successor._select_from(path, is_dir, exists, scandir):
155175
yield p
156176
except PermissionError:
157177
return
158178

159179

160180
class _RecursiveWildcardSelector(_Selector):
161181

162-
def __init__(self, pat, child_parts, case_sensitive):
163-
_Selector.__init__(self, child_parts, case_sensitive)
182+
def __init__(self, pat, child_parts, flavour, case_sensitive):
183+
_Selector.__init__(self, child_parts, flavour, case_sensitive)
164184

165-
def _iterate_directories(self, parent_path, scandir):
185+
def _iterate_directories(self, parent_path, is_dir, scandir):
166186
yield parent_path
167187
try:
168188
# We must close the scandir() object before proceeding to
@@ -178,18 +198,18 @@ def _iterate_directories(self, parent_path, scandir):
178198
raise
179199
if entry_is_dir and not entry.is_symlink():
180200
path = parent_path._make_child_relpath(entry.name)
181-
for p in self._iterate_directories(path, scandir):
201+
for p in self._iterate_directories(path, is_dir, scandir):
182202
yield p
183203
except PermissionError:
184204
return
185205

186-
def _select_from(self, parent_path, scandir):
206+
def _select_from(self, parent_path, is_dir, exists, scandir):
187207
try:
188208
yielded = set()
189209
try:
190210
successor_select = self.successor._select_from
191-
for starting_point in self._iterate_directories(parent_path, scandir):
192-
for p in successor_select(starting_point, scandir):
211+
for starting_point in self._iterate_directories(parent_path, is_dir, scandir):
212+
for p in successor_select(starting_point, is_dir, exists, scandir):
193213
if p not in yielded:
194214
yield p
195215
yielded.add(p)
@@ -839,7 +859,7 @@ def glob(self, pattern, *, case_sensitive=None):
839859
pattern_parts.append('')
840860
if case_sensitive is None:
841861
case_sensitive = _is_case_sensitive(self._flavour)
842-
selector = _make_selector(tuple(pattern_parts), case_sensitive)
862+
selector = _make_selector(tuple(pattern_parts), self._flavour, case_sensitive)
843863
for p in selector.select_from(self):
844864
yield p
845865

@@ -856,7 +876,7 @@ def rglob(self, pattern, *, case_sensitive=None):
856876
pattern_parts.append('')
857877
if case_sensitive is None:
858878
case_sensitive = _is_case_sensitive(self._flavour)
859-
selector = _make_selector(("**",) + tuple(pattern_parts), case_sensitive)
879+
selector = _make_selector(("**",) + tuple(pattern_parts), self._flavour, case_sensitive)
860880
for p in selector.select_from(self):
861881
yield p
862882

0 commit comments

Comments
 (0)
0