16
16
17
17
__all__ = ["filter" , "fnmatch" , "fnmatchcase" , "translate" ]
18
18
19
- # Build a thread-safe incrementing counter to help create unique regexp group
20
- # names across calls.
21
- from itertools import count
22
- _nextgroupnum = count ().__next__
23
- del count
24
-
25
19
def fnmatch (name , pat ):
26
20
"""Test whether FILENAME matches PATTERN.
27
21
@@ -149,17 +143,10 @@ def translate(pat):
149
143
# Now deal with STAR fixed STAR fixed ...
150
144
# For an interior `STAR fixed` pairing, we want to do a minimal
151
145
# .*? match followed by `fixed`, with no possibility of backtracking.
152
- # We can't spell that directly, but can trick it into working by matching
153
- # .*?fixed
154
- # in a lookahead assertion, save the matched part in a group, then
155
- # consume that group via a backreference. If the overall match fails,
156
- # the lookahead assertion won't try alternatives. So the translation is:
157
- # (?=(?P<name>.*?fixed))(?P=name)
158
- # Group names are created as needed: g0, g1, g2, ...
159
- # The numbers are obtained from _nextgroupnum() to ensure they're unique
160
- # across calls and across threads. This is because people rely on the
161
- # undocumented ability to join multiple translate() results together via
162
- # "|" to build large regexps matching "one of many" shell patterns.
146
+ # Atomic groups ("(?>...)") allow us to spell that directly.
147
+ # Note: people rely on the undocumented ability to join multiple
148
+ # translate() results together via "|" to build large regexps matching
149
+ # "one of many" shell patterns.
163
150
while i < n :
164
151
assert inp [i ] is STAR
165
152
i += 1
@@ -176,8 +163,7 @@ def translate(pat):
176
163
add (".*" )
177
164
add (fixed )
178
165
else :
179
- groupnum = _nextgroupnum ()
180
- add (f"(?=(?P<g{ groupnum } >.*?{ fixed } ))(?P=g{ groupnum } )" )
166
+ add (f"(?>.*?{ fixed } )" )
181
167
assert i == n
182
168
res = "" .join (res )
183
169
return fr'(?s:{ res } )\Z'
0 commit comments