Skip to content

Commit c7f6d87

Browse files
committed
Lookahead to ignore path separators in ranges which span path separators in fnmatch._translate
1 parent 4820018 commit c7f6d87

File tree

3 files changed

+16
-53
lines changed

3 files changed

+16
-53
lines changed

Lib/fnmatch.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ def _translate(pat, star, question_mark):
8787
res = []
8888
add = res.append
8989
star_indices = []
90+
inside_range=False
9091

9192
i, n = 0, len(pat)
9293
while i < n:
@@ -135,18 +136,31 @@ def _translate(pat, star, question_mark):
135136
if chunks[k-1][-1] > chunks[k][0]:
136137
chunks[k-1] = chunks[k-1][:-1] + chunks[k][1:]
137138
del chunks[k]
139+
140+
if len(chunks)>1:
141+
char_range=set(range(ord(chunks[0][-1]), ord(chunks[-1][0])))
142+
143+
question_mark_char=question_mark.replace('\\', '').replace('[', '').replace(']', '').replace('^', '')
144+
question_mark_char=set(map(ord, question_mark_char))
145+
146+
if question_mark_char.intersection(char_range):
147+
inside_range=True
148+
138149
# Escape backslashes and hyphens for set difference (--).
139150
# Hyphens that create ranges shouldn't be escaped.
140151
stuff = '-'.join(s.replace('\\', r'\\').replace('-', r'\-')
141152
for s in chunks)
153+
142154
i = j+1
143155
if not stuff:
144156
# Empty range: never match.
145157
add('(?!)')
146158
elif stuff == '!':
147159
# Negated empty range: match any character.
148-
add('.')
160+
add(question_mark)
149161
else:
162+
if question_mark != '.' and inside_range:
163+
add(f'(?={question_mark})')
150164
# Escape set operations (&&, ~~ and ||).
151165
stuff = _re_setops_sub(r'\\\1', stuff)
152166
if stuff[0] == '!':

Lib/glob.py

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -263,55 +263,6 @@ def escape(pathname):
263263
_dir_open_flags = os.O_RDONLY | getattr(os, 'O_DIRECTORY', 0)
264264
_no_recurse_symlinks = object()
265265

266-
def escape_regex_range_including_seps(pat, seps):
267-
"""Escape ranges containing seperators in a path
268-
"""
269-
pat = list(pat)
270-
ordinal_seps=set(map(ord, seps))
271-
272-
insideRange = False
273-
ds=[]
274-
275-
buf=''
276-
idx1=0
277-
idx2=0
278-
rangeIncludesSep=False
279-
280-
for path_idx, path_ch in enumerate(pat):
281-
if path_idx > 0:
282-
if path_ch == '[' and pat[path_idx-1] != '\\':
283-
insideRange = True
284-
idx1=path_idx
285-
continue
286-
if path_ch == ']' and pat[path_idx-1] != '\\':
287-
insideRange = False
288-
idx2=path_idx+1
289-
290-
if insideRange:
291-
buf+=path_ch
292-
if path_ch == '-':
293-
glob_range = list(range(ord(pat[path_idx-1]), ord(pat[path_idx+1])))
294-
if ordinal_seps.intersection(glob_range):
295-
rangeIncludesSep = True
296-
297-
elif len(buf)>0:
298-
ds.append([idx1, idx2, rangeIncludesSep])
299-
300-
buf=''
301-
idx1=1
302-
idx2=2
303-
rangeIncludesSep=False
304-
305-
for ds_idx, ds_elem in enumerate(ds):
306-
idx1=ds_elem[0]
307-
idx2=ds_elem[1]
308-
rangeIncludesSep=ds_elem[2]
309-
if rangeIncludesSep:
310-
pat.insert(idx1, '\\')
311-
pat.insert(idx2, '\\')
312-
313-
return ''.join(pat)
314-
315266
def translate(pat, *, recursive=False, include_hidden=False, seps=None):
316267
"""Translate a pathname with shell wildcards to a regular expression.
317268
@@ -369,7 +320,6 @@ def translate(pat, *, recursive=False, include_hidden=False, seps=None):
369320
results.append(any_sep)
370321

371322
res = ''.join(results)
372-
res=escape_regex_range_including_seps(res, seps=seps)
373323
return fr'(?s:{res})\Z'
374324

375325

Lib/test/test_glob.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,7 @@ def fn(pat):
514514
self.assertEqual(fn('foo/bar\\baz'), r'(?s:foo[/\\]bar[/\\]baz)\Z')
515515
self.assertEqual(fn('**/*'), r'(?s:(?:.+[/\\])?[^/\\]+)\Z')
516516

517-
self.assertEqual(fn('foo[%-0]bar'), r'(?s:foo\[%-0\]bar)\Z')
518-
self.assertEqual(fn('foo[U-d]bar'), r'(?s:foo\[U-d\]bar)\Z')
517+
self.assertEqual(fn('foo[%-0]bar'), r'(?s:foo(?=[^/\\])[%-0]bar)\Z')
519518

520519

521520
if __name__ == "__main__":

0 commit comments

Comments
 (0)