diff -r b6ebc726d5fe Lib/re.py --- a/Lib/re.py Sat Jul 06 13:25:44 2013 +0200 +++ b/Lib/re.py Sat Jul 06 16:37:09 2013 +0400 @@ -120,6 +120,7 @@ import sys import sre_compile +import sre_constants import sre_parse import functools @@ -167,6 +168,8 @@ if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.""" + if isinstance(count, sre_constants.Flags): + raise TypeError("count argument does not accept flags, use flags argument") return _compile(pattern, flags).sub(repl, string, count) def subn(pattern, repl, string, count=0, flags=0): @@ -178,6 +181,8 @@ callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.""" + if isinstance(count, sre_constants.Flags): + raise TypeError("count argument does not accept flags, use flags argument") return _compile(pattern, flags).subn(repl, string, count) def split(pattern, string, maxsplit=0, flags=0): @@ -188,6 +193,8 @@ list. If maxsplit is nonzero, at most maxsplit splits occur, and the remainder of the string is returned as the final element of the list.""" + if isinstance(maxsplit, sre_constants.Flags): + raise TypeError("maxsplit argument does not accept flags, use flags argument") return _compile(pattern, flags).split(string, maxsplit) def findall(pattern, string, flags=0): diff -r b6ebc726d5fe Lib/sre_constants.py --- a/Lib/sre_constants.py Sat Jul 06 13:25:44 2013 +0200 +++ b/Lib/sre_constants.py Sat Jul 06 16:37:09 2013 +0400 @@ -16,6 +16,7 @@ MAGIC = 20031017 from _sre import MAXREPEAT +from enum import IntEnum # SRE standard exception (access as sre.error) # should this really be here? @@ -200,15 +201,26 @@ } # flags -SRE_FLAG_TEMPLATE = 1 # template mode (disable backtracking) -SRE_FLAG_IGNORECASE = 2 # case insensitive -SRE_FLAG_LOCALE = 4 # honour system locale -SRE_FLAG_MULTILINE = 8 # treat target as multiline string -SRE_FLAG_DOTALL = 16 # treat target as a single string -SRE_FLAG_UNICODE = 32 # use unicode "locale" -SRE_FLAG_VERBOSE = 64 # ignore whitespace and comments -SRE_FLAG_DEBUG = 128 # debugging -SRE_FLAG_ASCII = 256 # use ascii "locale" +class Flags(IntEnum): + SRE_FLAG_TEMPLATE = 1 # template mode (disable backtracking) + SRE_FLAG_IGNORECASE = 2 # case insensitive + SRE_FLAG_LOCALE = 4 # honour system locale + SRE_FLAG_MULTILINE = 8 # treat target as multiline string + SRE_FLAG_DOTALL = 16 # treat target as a single string + SRE_FLAG_UNICODE = 32 # use unicode "locale" + SRE_FLAG_VERBOSE = 64 # ignore whitespace and comments + SRE_FLAG_DEBUG = 128 # debugging + SRE_FLAG_ASCII = 256 # use ascii "locale" + +SRE_FLAG_TEMPLATE = Flags.SRE_FLAG_TEMPLATE +SRE_FLAG_IGNORECASE = Flags.SRE_FLAG_IGNORECASE +SRE_FLAG_LOCALE = Flags.SRE_FLAG_LOCALE +SRE_FLAG_MULTILINE = Flags.SRE_FLAG_MULTILINE +SRE_FLAG_DOTALL = Flags.SRE_FLAG_DOTALL +SRE_FLAG_UNICODE = Flags.SRE_FLAG_UNICODE +SRE_FLAG_VERBOSE = Flags.SRE_FLAG_VERBOSE +SRE_FLAG_DEBUG = Flags.SRE_FLAG_DEBUG +SRE_FLAG_ASCII = Flags.SRE_FLAG_ASCII # flags for INFO primitive SRE_INFO_PREFIX = 1 # has prefix diff -r b6ebc726d5fe Lib/test/test_re.py --- a/Lib/test/test_re.py Sat Jul 06 13:25:44 2013 +0200 +++ b/Lib/test/test_re.py Sat Jul 06 16:37:09 2013 +0400 @@ -1040,6 +1040,19 @@ with self.assertRaisesRegex(sre_constants.error, '\?foo'): re.compile('(?P)') + def test_argument_not_flags(self): + # Issue 11957: Common mistake to pass flags argument in a wrong position to sub, subn and split + self.assertRaises(TypeError, re.sub, r'', '', '', re.U) + self.assertRaises(TypeError, re.subn, r'', '', '', re.U) + self.assertRaises(TypeError, re.split, r'', '', re.U) + + def test_ints_can_be_passed_as_flags(self): + # Issue 11957: Common mistake to pass flags argument in a wrong position to sub, subn and split + # Checking for backward compatibility + self.assertEqual(re.sub(r'', '', '', 0, int(re.U)), '') + self.assertEqual(re.subn(r'', '', '', 0, int(re.U)), ('', 1)) + self.assertEqual(re.split(r'', '', 0, int(re.U)), ['']) + def run_re_tests(): from test.re_tests import tests, SUCCEED, FAIL, SYNTAX_ERROR