Skip to content

Commit 418d60a

Browse files
[3.6] bpo-30298: Weaken the condition of deprecation warnings for inline modifiers. (GH-1490) (#1525)
Now allowed several subsequential inline modifiers at the start of the pattern (e.g. '(?i)(?s)...'). In verbose mode whitespaces and comments now are allowed before and between inline modifiers (e.g. '(?x) (?i) (?s)...').. (cherry picked from commit 305ccbe)
1 parent 03b8a37 commit 418d60a

File tree

3 files changed

+56
-21
lines changed

3 files changed

+56
-21
lines changed

Lib/sre_parse.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ def _parse_sub(source, state, verbose, nested=True):
412412
sourcematch = source.match
413413
start = source.tell()
414414
while True:
415-
itemsappend(_parse(source, state, verbose))
415+
itemsappend(_parse(source, state, verbose, not nested and not items))
416416
if not sourcematch("|"):
417417
break
418418

@@ -466,7 +466,7 @@ def _parse_sub_cond(source, state, condgroup, verbose):
466466
subpattern.append((GROUPREF_EXISTS, (condgroup, item_yes, item_no)))
467467
return subpattern
468468

469-
def _parse(source, state, verbose):
469+
def _parse(source, state, verbose, first=False):
470470
# parse a simple pattern
471471
subpattern = SubPattern(state)
472472

@@ -730,10 +730,9 @@ def _parse(source, state, verbose):
730730
state.checklookbehindgroup(condgroup, source)
731731
elif char in FLAGS or char == "-":
732732
# flags
733-
pos = source.pos
734733
flags = _parse_flags(source, state, char)
735734
if flags is None: # global flags
736-
if pos != 3: # "(?x"
735+
if not first or subpattern:
737736
import warnings
738737
warnings.warn(
739738
'Flags not at the start of the expression %s%s' % (
@@ -742,6 +741,8 @@ def _parse(source, state, verbose):
742741
),
743742
DeprecationWarning, stacklevel=7
744743
)
744+
if (state.flags & SRE_FLAG_VERBOSE) and not verbose:
745+
raise Verbose
745746
continue
746747
add_flags, del_flags = flags
747748
group = None
@@ -795,9 +796,6 @@ def _parse_flags(source, state, char):
795796
msg = "unknown flag" if char.isalpha() else "missing -, : or )"
796797
raise source.error(msg, len(char))
797798
if char == ")":
798-
if ((add_flags & SRE_FLAG_VERBOSE) and
799-
not (state.flags & SRE_FLAG_VERBOSE)):
800-
raise Verbose
801799
state.flags |= add_flags
802800
return None
803801
if add_flags & GLOBAL_FLAGS:

Lib/test/test_re.py

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,32 +1303,43 @@ def test_inline_flags(self):
13031303
upper_char = '\u1ea0' # Latin Capital Letter A with Dot Below
13041304
lower_char = '\u1ea1' # Latin Small Letter A with Dot Below
13051305

1306-
p = re.compile(upper_char, re.I | re.U)
1307-
q = p.match(lower_char)
1306+
p = re.compile('.' + upper_char, re.I | re.S)
1307+
q = p.match('\n' + lower_char)
13081308
self.assertTrue(q)
13091309

1310-
p = re.compile(lower_char, re.I | re.U)
1311-
q = p.match(upper_char)
1310+
p = re.compile('.' + lower_char, re.I | re.S)
1311+
q = p.match('\n' + upper_char)
13121312
self.assertTrue(q)
13131313

1314-
p = re.compile('(?i)' + upper_char, re.U)
1315-
q = p.match(lower_char)
1314+
p = re.compile('(?i).' + upper_char, re.S)
1315+
q = p.match('\n' + lower_char)
13161316
self.assertTrue(q)
13171317

1318-
p = re.compile('(?i)' + lower_char, re.U)
1319-
q = p.match(upper_char)
1318+
p = re.compile('(?i).' + lower_char, re.S)
1319+
q = p.match('\n' + upper_char)
13201320
self.assertTrue(q)
13211321

1322-
p = re.compile('(?iu)' + upper_char)
1323-
q = p.match(lower_char)
1322+
p = re.compile('(?is).' + upper_char)
1323+
q = p.match('\n' + lower_char)
13241324
self.assertTrue(q)
13251325

1326-
p = re.compile('(?iu)' + lower_char)
1327-
q = p.match(upper_char)
1326+
p = re.compile('(?is).' + lower_char)
1327+
q = p.match('\n' + upper_char)
13281328
self.assertTrue(q)
13291329

1330-
self.assertTrue(re.match('(?ixu) ' + upper_char, lower_char))
1331-
self.assertTrue(re.match('(?ixu) ' + lower_char, upper_char))
1330+
p = re.compile('(?s)(?i).' + upper_char)
1331+
q = p.match('\n' + lower_char)
1332+
self.assertTrue(q)
1333+
1334+
p = re.compile('(?s)(?i).' + lower_char)
1335+
q = p.match('\n' + upper_char)
1336+
self.assertTrue(q)
1337+
1338+
self.assertTrue(re.match('(?ix) ' + upper_char, lower_char))
1339+
self.assertTrue(re.match('(?ix) ' + lower_char, upper_char))
1340+
self.assertTrue(re.match(' (?i) ' + upper_char, lower_char, re.X))
1341+
self.assertTrue(re.match('(?x) (?i) ' + upper_char, lower_char))
1342+
self.assertTrue(re.match(' (?x) (?i) ' + upper_char, lower_char, re.X))
13321343

13331344
p = upper_char + '(?i)'
13341345
with self.assertWarns(DeprecationWarning) as warns:
@@ -1346,6 +1357,26 @@ def test_inline_flags(self):
13461357
'Flags not at the start of the expression %s (truncated)' % p[:20]
13471358
)
13481359

1360+
with self.assertWarns(DeprecationWarning):
1361+
self.assertTrue(re.match('(?s).(?i)' + upper_char, '\n' + lower_char))
1362+
with self.assertWarns(DeprecationWarning):
1363+
self.assertTrue(re.match('(?i) ' + upper_char + ' (?x)', lower_char))
1364+
with self.assertWarns(DeprecationWarning):
1365+
self.assertTrue(re.match(' (?x) (?i) ' + upper_char, lower_char))
1366+
with self.assertWarns(DeprecationWarning):
1367+
self.assertTrue(re.match('^(?i)' + upper_char, lower_char))
1368+
with self.assertWarns(DeprecationWarning):
1369+
self.assertTrue(re.match('$|(?i)' + upper_char, lower_char))
1370+
with self.assertWarns(DeprecationWarning):
1371+
self.assertTrue(re.match('(?:(?i)' + upper_char + ')', lower_char))
1372+
with self.assertWarns(DeprecationWarning):
1373+
self.assertTrue(re.fullmatch('(^)?(?(1)(?i)' + upper_char + ')',
1374+
lower_char))
1375+
with self.assertWarns(DeprecationWarning):
1376+
self.assertTrue(re.fullmatch('($)?(?(1)|(?i)' + upper_char + ')',
1377+
lower_char))
1378+
1379+
13491380
def test_dollar_matches_twice(self):
13501381
"$ matches the end of string, and just before the terminating \n"
13511382
pattern = re.compile('$')

Misc/NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ Core and Builtins
3636
Library
3737
-------
3838

39+
- bpo-30298: Weaken the condition of deprecation warnings for inline modifiers.
40+
Now allowed several subsequential inline modifiers at the start of the
41+
pattern (e.g. ``'(?i)(?s)...'``). In verbose mode whitespaces and comments
42+
now are allowed before and between inline modifiers (e.g.
43+
``'(?x) (?i) (?s)...'``).
44+
3945
- bpo-29990: Fix range checking in GB18030 decoder. Original patch by Ma Lin.
4046

4147
- Revert bpo-26293 for zipfile breakage. See also bpo-29094.

0 commit comments

Comments
 (0)