Skip to content

Commit 23cdbfa

Browse files
bpo-32775: Fix regular expression warnings in fnmatch. (python#5583)
fnmatch.translate() no longer produces patterns which contain set operations. Sets starting with '[' or containing '--', '&&', '~~' or '||' will be interpreted differently in regular expressions in future versions. Currently they emit warnings. fnmatch.translate() now avoids producing patterns containing such sets by accident.
1 parent feaefc7 commit 23cdbfa

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

Lib/fnmatch.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,30 @@ def translate(pat):
9797
if j >= n:
9898
res = res + '\\['
9999
else:
100-
stuff = pat[i:j].replace('\\','\\\\')
100+
stuff = pat[i:j]
101+
if '--' not in stuff:
102+
stuff = stuff.replace('\\', r'\\')
103+
else:
104+
chunks = []
105+
k = i+2 if pat[i] == '!' else i+1
106+
while True:
107+
k = pat.find('-', k, j)
108+
if k < 0:
109+
break
110+
chunks.append(pat[i:k])
111+
i = k+1
112+
k = k+3
113+
chunks.append(pat[i:j])
114+
# Escape backslashes and hyphens for set difference (--).
115+
# Hyphens that create ranges shouldn't be escaped.
116+
stuff = '-'.join(s.replace('\\', r'\\').replace('-', r'\-')
117+
for s in chunks)
118+
# Escape set operations (&&, ~~ and ||).
119+
stuff = re.sub(r'([&~|])', r'\\\1', stuff)
101120
i = j+1
102121
if stuff[0] == '!':
103122
stuff = '^' + stuff[1:]
104-
elif stuff[0] == '^':
123+
elif stuff[0] in ('^', '['):
105124
stuff = '\\' + stuff
106125
res = '%s[%s]' % (res, stuff)
107126
else:

Lib/test/test_fnmatch.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import unittest
44
import os
5+
import warnings
56

67
from fnmatch import fnmatch, fnmatchcase, translate, filter
78

@@ -83,6 +84,17 @@ def test_sep(self):
8384
check('usr/bin', 'usr\\bin', normsep)
8485
check('usr\\bin', 'usr\\bin')
8586

87+
def test_warnings(self):
88+
with warnings.catch_warnings():
89+
warnings.simplefilter('error', Warning)
90+
check = self.check_match
91+
check('[', '[[]')
92+
check('&', '[a&&b]')
93+
check('|', '[a||b]')
94+
check('~', '[a~~b]')
95+
check(',', '[a-z+--A-Z]')
96+
check('.', '[a-z--/A-Z]')
97+
8698

8799
class TranslateTestCase(unittest.TestCase):
88100

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
:func:`fnmatch.translate()` no longer produces patterns which contain set
2+
operations. Sets starting with '[' or containing '--', '&&', '~~' or '||'
3+
will be interpreted differently in regular expressions in future versions.
4+
Currently they emit warnings. fnmatch.translate() now avoids producing
5+
patterns containing such sets by accident.

0 commit comments

Comments
 (0)