Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
test_regex.py4541 linesDownload Raw Back to tests
1from weakref import proxy
2import copy
3import pickle
4import regex
5import string
6import sys
7import unittest
8
9# String subclasses for issue 18468.
10class StrSubclass(str):
11    def __getitem__(self, index):
12        return StrSubclass(super().__getitem__(index))
13
14class BytesSubclass(bytes):
15    def __getitem__(self, index):
16        return BytesSubclass(super().__getitem__(index))
17
18class RegexTests(unittest.TestCase):
19    PATTERN_CLASS = "<class '_regex.Pattern'>"
20    FLAGS_WITH_COMPILED_PAT = "cannot process flags argument with a compiled pattern"
21    INVALID_GROUP_REF = "invalid group reference"
22    MISSING_GT = "missing >"
23    BAD_GROUP_NAME = "bad character in group name"
24    MISSING_GROUP_NAME = "missing group name"
25    MISSING_LT = "missing <"
26    UNKNOWN_GROUP_I = "unknown group"
27    UNKNOWN_GROUP = "unknown group"
28    BAD_ESCAPE = r"bad escape \(end of pattern\)"
29    BAD_OCTAL_ESCAPE = r"bad escape \\"
30    BAD_SET = "unterminated character set"
31    STR_PAT_ON_BYTES = "cannot use a string pattern on a bytes-like object"
32    BYTES_PAT_ON_STR = "cannot use a bytes pattern on a string-like object"
33    STR_PAT_BYTES_TEMPL = "expected str instance, bytes found"
34    BYTES_PAT_STR_TEMPL = "expected a bytes-like object, str found"
35    BYTES_PAT_UNI_FLAG = "cannot use UNICODE flag with a bytes pattern"
36    MIXED_FLAGS = "ASCII, LOCALE and UNICODE flags are mutually incompatible"
37    MISSING_RPAREN = "missing \\)"
38    TRAILING_CHARS = "unbalanced parenthesis"
39    BAD_CHAR_RANGE = "bad character range"
40    NOTHING_TO_REPEAT = "nothing to repeat"
41    MULTIPLE_REPEAT = "multiple repeat"
42    OPEN_GROUP = "cannot refer to an open group"
43    DUPLICATE_GROUP = "duplicate group"
44    CANT_TURN_OFF = "bad inline flags: cannot turn flags off"
45    UNDEF_CHAR_NAME = "undefined character name"
46
47    def assertTypedEqual(self, actual, expect, msg=None):
48        self.assertEqual(actual, expect, msg)
49
50        def recurse(actual, expect):
51            if isinstance(expect, (tuple, list)):
52                for x, y in zip(actual, expect):
53                    recurse(x, y)
54            else:
55                self.assertIs(type(actual), type(expect), msg)
56
57        recurse(actual, expect)
58
59    def test_weakref(self):
60        s = 'QabbbcR'
61        x = regex.compile('ab+c')
62        y = proxy(x)
63        if x.findall('QabbbcR') != y.findall('QabbbcR'):
64            self.fail()
65
66    def test_search_star_plus(self):
67        self.assertEqual(regex.search('a*', 'xxx').span(0), (0, 0))
68        self.assertEqual(regex.search('x*', 'axx').span(), (0, 0))
69        self.assertEqual(regex.search('x+', 'axx').span(0), (1, 3))
70        self.assertEqual(regex.search('x+', 'axx').span(), (1, 3))
71        self.assertEqual(regex.search('x', 'aaa'), None)
72        self.assertEqual(regex.match('a*', 'xxx').span(0), (0, 0))
73        self.assertEqual(regex.match('a*', 'xxx').span(), (0, 0))
74        self.assertEqual(regex.match('x*', 'xxxa').span(0), (0, 3))
75        self.assertEqual(regex.match('x*', 'xxxa').span(), (0, 3))
76        self.assertEqual(regex.match('a+', 'xxx'), None)
77
78    def bump_num(self, matchobj):
79        int_value = int(matchobj[0])
80        return str(int_value + 1)
81
82    def test_basic_regex_sub(self):
83        self.assertEqual(regex.sub("(?i)b+", "x", "bbbb BBBB"), 'x x')
84        self.assertEqual(regex.sub(r'\d+', self.bump_num, '08.2 -2 23x99y'),
85          '9.3 -3 24x100y')
86        self.assertEqual(regex.sub(r'\d+', self.bump_num, '08.2 -2 23x99y', 3),
87          '9.3 -3 23x99y')
88
89        self.assertEqual(regex.sub('.', lambda m: r"\n", 'x'), "\\n")
90        self.assertEqual(regex.sub('.', r"\n", 'x'), "\n")
91
92        self.assertEqual(regex.sub('(?P<a>x)', r'\g<a>\g<a>', 'xx'), 'xxxx')
93        self.assertEqual(regex.sub('(?P<a>x)', r'\g<a>\g<1>', 'xx'), 'xxxx')
94        self.assertEqual(regex.sub('(?P<unk>x)', r'\g<unk>\g<unk>', 'xx'),
95          'xxxx')
96        self.assertEqual(regex.sub('(?P<unk>x)', r'\g<1>\g<1>', 'xx'), 'xxxx')
97
98        self.assertEqual(regex.sub('a', r'\t\n\v\r\f\a\b', 'a'), "\t\n\v\r\f\a\b")
99        self.assertEqual(regex.sub('a', '\t\n\v\r\f\a', 'a'), "\t\n\v\r\f\a")
100        self.assertEqual(regex.sub('a', '\t\n\v\r\f\a', 'a'), chr(9) + chr(10)
101          + chr(11) + chr(13) + chr(12) + chr(7))
102
103        self.assertEqual(regex.sub(r'^\s*', 'X', 'test'), 'Xtest')
104
105        self.assertEqual(regex.sub(r"x", r"\x0A", "x"), "\n")
106        self.assertEqual(regex.sub(r"x", r"\u000A", "x"), "\n")
107        self.assertEqual(regex.sub(r"x", r"\U0000000A", "x"), "\n")
108        self.assertEqual(regex.sub(r"x", r"\N{LATIN CAPITAL LETTER A}",
109          "x"), "A")
110
111        self.assertEqual(regex.sub(br"x", br"\x0A", b"x"), b"\n")
112
113    def test_bug_449964(self):
114        # Fails for group followed by other escape.
115        self.assertEqual(regex.sub(r'(?P<unk>x)', r'\g<1>\g<1>\b', 'xx'),
116          "xx\bxx\b")
117
118    def test_bug_449000(self):
119        # Test for sub() on escaped characters.
120        self.assertEqual(regex.sub(r'\r\n', r'\n', 'abc\r\ndef\r\n'),
121          "abc\ndef\n")
122        self.assertEqual(regex.sub('\r\n', r'\n', 'abc\r\ndef\r\n'),
123          "abc\ndef\n")
124        self.assertEqual(regex.sub(r'\r\n', '\n', 'abc\r\ndef\r\n'),
125          "abc\ndef\n")
126        self.assertEqual(regex.sub('\r\n', '\n', 'abc\r\ndef\r\n'),
127          "abc\ndef\n")
128
129    def test_bug_1661(self):
130        # Verify that flags do not get silently ignored with compiled patterns
131        pattern = regex.compile('.')
132        self.assertRaisesRegex(ValueError, self.FLAGS_WITH_COMPILED_PAT,
133          lambda: regex.match(pattern, 'A', regex.I))
134        self.assertRaisesRegex(ValueError, self.FLAGS_WITH_COMPILED_PAT,
135          lambda: regex.search(pattern, 'A', regex.I))
136        self.assertRaisesRegex(ValueError, self.FLAGS_WITH_COMPILED_PAT,
137          lambda: regex.findall(pattern, 'A', regex.I))
138        self.assertRaisesRegex(ValueError, self.FLAGS_WITH_COMPILED_PAT,
139          lambda: regex.compile(pattern, regex.I))
140
141    def test_bug_3629(self):
142        # A regex that triggered a bug in the sre-code validator
143        self.assertEqual(repr(type(regex.compile("(?P<quote>)(?(quote))"))),
144          self.PATTERN_CLASS)
145
146    def test_sub_template_numeric_escape(self):
147        # Bug 776311 and friends.
148        self.assertEqual(regex.sub('x', r'\0', 'x'), "\0")
149        self.assertEqual(regex.sub('x', r'\000', 'x'), "\000")
150        self.assertEqual(regex.sub('x', r'\001', 'x'), "\001")
151        self.assertEqual(regex.sub('x', r'\008', 'x'), "\0" + "8")
152        self.assertEqual(regex.sub('x', r'\009', 'x'), "\0" + "9")
153        self.assertEqual(regex.sub('x', r'\111', 'x'), "\111")
154        self.assertEqual(regex.sub('x', r'\117', 'x'), "\117")
155
156        self.assertEqual(regex.sub('x', r'\1111', 'x'), "\1111")
157        self.assertEqual(regex.sub('x', r'\1111', 'x'), "\111" + "1")
158
159        self.assertEqual(regex.sub('x', r'\00', 'x'), '\x00')
160        self.assertEqual(regex.sub('x', r'\07', 'x'), '\x07')
161        self.assertEqual(regex.sub('x', r'\08', 'x'), "\0" + "8")
162        self.assertEqual(regex.sub('x', r'\09', 'x'), "\0" + "9")
163        self.assertEqual(regex.sub('x', r'\0a', 'x'), "\0" + "a")
164
165        self.assertEqual(regex.sub('x', r'\400', 'x'), "\u0100")
166        self.assertEqual(regex.sub('x', r'\777', 'x'), "\u01FF")
167        self.assertEqual(regex.sub(b'x', br'\400', b'x'), b"\x00")
168        self.assertEqual(regex.sub(b'x', br'\777', b'x'), b"\xFF")
169
170        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
171          regex.sub('x', r'\1', 'x'))
172        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
173          regex.sub('x', r'\8', 'x'))
174        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
175          regex.sub('x', r'\9', 'x'))
176        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
177          regex.sub('x', r'\11', 'x'))
178        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
179          regex.sub('x', r'\18', 'x'))
180        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
181          regex.sub('x', r'\1a', 'x'))
182        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
183          regex.sub('x', r'\90', 'x'))
184        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
185          regex.sub('x', r'\99', 'x'))
186        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
187          regex.sub('x', r'\118', 'x')) # r'\11' + '8'
188        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
189          regex.sub('x', r'\11a', 'x'))
190        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
191          regex.sub('x', r'\181', 'x')) # r'\18' + '1'
192        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
193          regex.sub('x', r'\800', 'x')) # r'\80' + '0'
194
195        # In Python 2.3 (etc), these loop endlessly in sre_parser.py.
196        self.assertEqual(regex.sub('(((((((((((x)))))))))))', r'\11', 'x'),
197          'x')
198        self.assertEqual(regex.sub('((((((((((y))))))))))(.)', r'\118', 'xyz'),
199          'xz8')
200        self.assertEqual(regex.sub('((((((((((y))))))))))(.)', r'\11a', 'xyz'),
201          'xza')
202
203    def test_qualified_re_sub(self):
204        self.assertEqual(regex.sub('a', 'b', 'aaaaa'), 'bbbbb')
205        self.assertEqual(regex.sub('a', 'b', 'aaaaa', 1), 'baaaa')
206
207    def test_bug_114660(self):
208        self.assertEqual(regex.sub(r'(\S)\s+(\S)', r'\1 \2', 'hello  there'),
209          'hello there')
210
211    def test_bug_462270(self):
212        # Test for empty sub() behaviour, see SF bug #462270
213        if sys.version_info >= (3, 7, 0):
214            self.assertEqual(regex.sub('(?V0)x*', '-', 'abxd'), '-a-b--d-')
215        else:
216            self.assertEqual(regex.sub('(?V0)x*', '-', 'abxd'), '-a-b-d-')
217        self.assertEqual(regex.sub('(?V1)x*', '-', 'abxd'), '-a-b--d-')
218        self.assertEqual(regex.sub('x+', '-', 'abxd'), 'ab-d')
219
220    def test_bug_14462(self):
221        # chr(255) is a valid identifier in Python 3.
222        group_name = '\xFF'
223        self.assertEqual(regex.search(r'(?P<' + group_name + '>a)',
224          'abc').group(group_name), 'a')
225
226    def test_symbolic_refs(self):
227        self.assertRaisesRegex(regex.error, self.MISSING_GT, lambda:
228          regex.sub('(?P<a>x)', r'\g<a', 'xx'))
229        self.assertRaisesRegex(regex.error, self.MISSING_GROUP_NAME, lambda:
230          regex.sub('(?P<a>x)', r'\g<', 'xx'))
231        self.assertRaisesRegex(regex.error, self.MISSING_LT, lambda:
232          regex.sub('(?P<a>x)', r'\g', 'xx'))
233        self.assertRaisesRegex(regex.error, self.BAD_GROUP_NAME, lambda:
234          regex.sub('(?P<a>x)', r'\g<a a>', 'xx'))
235        self.assertRaisesRegex(regex.error, self.BAD_GROUP_NAME, lambda:
236          regex.sub('(?P<a>x)', r'\g<1a1>', 'xx'))
237        self.assertRaisesRegex(IndexError, self.UNKNOWN_GROUP_I, lambda:
238          regex.sub('(?P<a>x)', r'\g<ab>', 'xx'))
239
240        # The new behaviour of unmatched but valid groups is to treat them like
241        # empty matches in the replacement template, like in Perl.
242        self.assertEqual(regex.sub('(?P<a>x)|(?P<b>y)', r'\g<b>', 'xx'), '')
243        self.assertEqual(regex.sub('(?P<a>x)|(?P<b>y)', r'\2', 'xx'), '')
244
245        # The old behaviour was to raise it as an IndexError.
246        self.assertRaisesRegex(regex.error, self.BAD_GROUP_NAME, lambda:
247          regex.sub('(?P<a>x)', r'\g<-1>', 'xx'))
248
249    def test_re_subn(self):
250        self.assertEqual(regex.subn("(?i)b+", "x", "bbbb BBBB"), ('x x', 2))
251        self.assertEqual(regex.subn("b+", "x", "bbbb BBBB"), ('x BBBB', 1))
252        self.assertEqual(regex.subn("b+", "x", "xyz"), ('xyz', 0))
253        self.assertEqual(regex.subn("b*", "x", "xyz"), ('xxxyxzx', 4))
254        self.assertEqual(regex.subn("b*", "x", "xyz", 2), ('xxxyz', 2))
255
256    def test_re_split(self):
257        self.assertEqual(regex.split(":", ":a:b::c"), ['', 'a', 'b', '', 'c'])
258        if sys.version_info >= (3, 7, 0):
259            self.assertEqual(regex.split(":*", ":a:b::c"), ['', '', 'a', '',
260              'b', '', 'c', ''])
261            self.assertEqual(regex.split("(:*)", ":a:b::c"), ['', ':', '', '',
262              'a', ':', '', '', 'b', '::', '', '', 'c', '', ''])
263            self.assertEqual(regex.split("(?::*)", ":a:b::c"), ['', '', 'a',
264              '', 'b', '', 'c', ''])
265            self.assertEqual(regex.split("(:)*", ":a:b::c"), ['', ':', '',
266              None, 'a', ':', '', None, 'b', ':', '', None, 'c', None, ''])
267        else:
268            self.assertEqual(regex.split(":*", ":a:b::c"), ['', 'a', 'b', 'c'])
269            self.assertEqual(regex.split("(:*)", ":a:b::c"), ['', ':', 'a',
270              ':', 'b', '::', 'c'])
271            self.assertEqual(regex.split("(?::*)", ":a:b::c"), ['', 'a', 'b',
272              'c'])
273            self.assertEqual(regex.split("(:)*", ":a:b::c"), ['', ':', 'a',
274              ':', 'b', ':', 'c'])
275        self.assertEqual(regex.split("([b:]+)", ":a:b::c"), ['', ':', 'a',
276          ':b::', 'c'])
277        self.assertEqual(regex.split("(b)|(:+)", ":a:b::c"), ['', None, ':',
278          'a', None, ':', '', 'b', None, '', None, '::', 'c'])
279        self.assertEqual(regex.split("(?:b)|(?::+)", ":a:b::c"), ['', 'a', '',
280          '', 'c'])
281
282        self.assertEqual(regex.split("x", "xaxbxc"), ['', 'a', 'b', 'c'])
283        self.assertEqual([m for m in regex.splititer("x", "xaxbxc")], ['', 'a',
284          'b', 'c'])
285
286        self.assertEqual(regex.split("(?r)x", "xaxbxc"), ['c', 'b', 'a', ''])
287        self.assertEqual([m for m in regex.splititer("(?r)x", "xaxbxc")], ['c',
288          'b', 'a', ''])
289
290        self.assertEqual(regex.split("(x)|(y)", "xaxbxc"), ['', 'x', None, 'a',
291          'x', None, 'b', 'x', None, 'c'])
292        self.assertEqual([m for m in regex.splititer("(x)|(y)", "xaxbxc")],
293          ['', 'x', None, 'a', 'x', None, 'b', 'x', None, 'c'])
294
295        self.assertEqual(regex.split("(?r)(x)|(y)", "xaxbxc"), ['c', 'x', None,
296          'b', 'x', None, 'a', 'x', None, ''])
297        self.assertEqual([m for m in regex.splititer("(?r)(x)|(y)", "xaxbxc")],
298          ['c', 'x', None, 'b', 'x', None, 'a', 'x', None, ''])
299
300        self.assertEqual(regex.split(r"(?V1)\b", "a b c"), ['', 'a', ' ', 'b',
301          ' ', 'c', ''])
302        self.assertEqual(regex.split(r"(?V1)\m", "a b c"), ['', 'a ', 'b ',
303          'c'])
304        self.assertEqual(regex.split(r"(?V1)\M", "a b c"), ['a', ' b', ' c',
305          ''])
306
307    def test_qualified_re_split(self):
308        self.assertEqual(regex.split(":", ":a:b::c", 2), ['', 'a', 'b::c'])
309        self.assertEqual(regex.split(':', 'a:b:c:d', 2), ['a', 'b', 'c:d'])
310        self.assertEqual(regex.split("(:)", ":a:b::c", 2), ['', ':', 'a', ':',
311          'b::c'])
312
313        if sys.version_info >= (3, 7, 0):
314            self.assertEqual(regex.split("(:*)", ":a:b::c", 2), ['', ':', '',
315              '', 'a:b::c'])
316        else:
317            self.assertEqual(regex.split("(:*)", ":a:b::c", 2), ['', ':', 'a',
318              ':', 'b::c'])
319
320    def test_re_findall(self):
321        self.assertEqual(regex.findall(":+", "abc"), [])
322        self.assertEqual(regex.findall(":+", "a:b::c:::d"), [':', '::', ':::'])
323        self.assertEqual(regex.findall("(:+)", "a:b::c:::d"), [':', '::',
324          ':::'])
325        self.assertEqual(regex.findall("(:)(:*)", "a:b::c:::d"), [(':', ''),
326          (':', ':'), (':', '::')])
327
328        self.assertEqual(regex.findall(r"\((?P<test>.{0,5}?TEST)\)",
329          "(MY TEST)"), ["MY TEST"])
330        self.assertEqual(regex.findall(r"\((?P<test>.{0,3}?TEST)\)",
331          "(MY TEST)"), ["MY TEST"])
332        self.assertEqual(regex.findall(r"\((?P<test>.{0,3}?T)\)", "(MY T)"),
333          ["MY T"])
334
335        self.assertEqual(regex.findall(r"[^a]{2}[A-Z]", "\n  S"), ['  S'])
336        self.assertEqual(regex.findall(r"[^a]{2,3}[A-Z]", "\n  S"), ['\n  S'])
337        self.assertEqual(regex.findall(r"[^a]{2,3}[A-Z]", "\n   S"), ['   S'])
338
339        self.assertEqual(regex.findall(r"X(Y[^Y]+?){1,2}( |Q)+DEF",
340          "XYABCYPPQ\nQ DEF"), [('YPPQ\n', ' ')])
341
342        self.assertEqual(regex.findall(r"(\nTest(\n+.+?){0,2}?)?\n+End",
343          "\nTest\nxyz\nxyz\nEnd"), [('\nTest\nxyz\nxyz', '\nxyz')])
344
345    def test_bug_117612(self):
346        self.assertEqual(regex.findall(r"(a|(b))", "aba"), [('a', ''), ('b',
347          'b'), ('a', '')])
348
349    def test_re_match(self):
350        self.assertEqual(regex.match('a', 'a')[:], ('a',))
351        self.assertEqual(regex.match('(a)', 'a')[:], ('a', 'a'))
352        self.assertEqual(regex.match(r'(a)', 'a')[0], 'a')
353        self.assertEqual(regex.match(r'(a)', 'a')[1], 'a')
354        self.assertEqual(regex.match(r'(a)', 'a').group(1, 1), ('a', 'a'))
355
356        pat = regex.compile('((a)|(b))(c)?')
357        self.assertEqual(pat.match('a')[:], ('a', 'a', 'a', None, None))
358        self.assertEqual(pat.match('b')[:], ('b', 'b', None, 'b', None))
359        self.assertEqual(pat.match('ac')[:], ('ac', 'a', 'a', None, 'c'))
360        self.assertEqual(pat.match('bc')[:], ('bc', 'b', None, 'b', 'c'))
361        self.assertEqual(pat.match('bc')[:], ('bc', 'b', None, 'b', 'c'))
362
363        # A single group.
364        m = regex.match('(a)', 'a')
365        self.assertEqual(m.group(), 'a')
366        self.assertEqual(m.group(0), 'a')
367        self.assertEqual(m.group(1), 'a')
368        self.assertEqual(m.group(1, 1), ('a', 'a'))
369
370        pat = regex.compile('(?:(?P<a1>a)|(?P<b2>b))(?P<c3>c)?')
371        self.assertEqual(pat.match('a').group(1, 2, 3), ('a', None, None))
372        self.assertEqual(pat.match('b').group('a1', 'b2', 'c3'), (None, 'b',
373          None))
374        self.assertEqual(pat.match('ac').group(1, 'b2', 3), ('a', None, 'c'))
375
376    def test_re_groupref_exists(self):
377        self.assertEqual(regex.match(r'^(\()?([^()]+)(?(1)\))$', '(a)')[:],
378          ('(a)', '(', 'a'))
379        self.assertEqual(regex.match(r'^(\()?([^()]+)(?(1)\))$', 'a')[:], ('a',
380          None, 'a'))
381        self.assertEqual(regex.match(r'^(\()?([^()]+)(?(1)\))$', 'a)'), None)
382        self.assertEqual(regex.match(r'^(\()?([^()]+)(?(1)\))$', '(a'), None)
383        self.assertEqual(regex.match('^(?:(a)|c)((?(1)b|d))$', 'ab')[:], ('ab',
384          'a', 'b'))
385        self.assertEqual(regex.match('^(?:(a)|c)((?(1)b|d))$', 'cd')[:], ('cd',
386          None, 'd'))
387        self.assertEqual(regex.match('^(?:(a)|c)((?(1)|d))$', 'cd')[:], ('cd',
388          None, 'd'))
389        self.assertEqual(regex.match('^(?:(a)|c)((?(1)|d))$', 'a')[:], ('a',
390          'a', ''))
391
392        # Tests for bug #1177831: exercise groups other than the first group.
393        p = regex.compile('(?P<g1>a)(?P<g2>b)?((?(g2)c|d))')
394        self.assertEqual(p.match('abc')[:], ('abc', 'a', 'b', 'c'))
395        self.assertEqual(p.match('ad')[:], ('ad', 'a', None, 'd'))
396        self.assertEqual(p.match('abd'), None)
397        self.assertEqual(p.match('ac'), None)
398
399    def test_re_groupref(self):
400        self.assertEqual(regex.match(r'^(\|)?([^()]+)\1$', '|a|')[:], ('|a|',
401          '|', 'a'))
402        self.assertEqual(regex.match(r'^(\|)?([^()]+)\1?$', 'a')[:], ('a',
403          None, 'a'))
404        self.assertEqual(regex.match(r'^(\|)?([^()]+)\1$', 'a|'), None)
405        self.assertEqual(regex.match(r'^(\|)?([^()]+)\1$', '|a'), None)
406        self.assertEqual(regex.match(r'^(?:(a)|c)(\1)$', 'aa')[:], ('aa', 'a',
407          'a'))
408        self.assertEqual(regex.match(r'^(?:(a)|c)(\1)?$', 'c')[:], ('c', None,
409          None))
410
411        self.assertEqual(regex.findall(r"(?i)(.{1,40}?),(.{1,40}?)(?:;)+(.{1,80}).{1,40}?\3(\ |;)+(.{1,80}?)\1",
412          "TEST, BEST; LEST ; Lest 123 Test, Best"), [('TEST', ' BEST',
413          ' LEST', ' ', '123 ')])
414
415    def test_groupdict(self):
416        self.assertEqual(regex.match('(?P<first>first) (?P<second>second)',
417          'first second').groupdict(), {'first': 'first', 'second': 'second'})
418
419    def test_expand(self):
420        self.assertEqual(regex.match("(?P<first>first) (?P<second>second)",
421          "first second").expand(r"\2 \1 \g<second> \g<first>"),
422          'second first second first')
423
424    def test_repeat_minmax(self):
425        self.assertEqual(regex.match(r"^(\w){1}$", "abc"), None)
426        self.assertEqual(regex.match(r"^(\w){1}?$", "abc"), None)
427        self.assertEqual(regex.match(r"^(\w){1,2}$", "abc"), None)
428        self.assertEqual(regex.match(r"^(\w){1,2}?$", "abc"), None)
429
430        self.assertEqual(regex.match(r"^(\w){3}$", "abc")[1], 'c')
431        self.assertEqual(regex.match(r"^(\w){1,3}$", "abc")[1], 'c')
432        self.assertEqual(regex.match(r"^(\w){1,4}$", "abc")[1], 'c')
433        self.assertEqual(regex.match(r"^(\w){3,4}?$", "abc")[1], 'c')
434        self.assertEqual(regex.match(r"^(\w){3}?$", "abc")[1], 'c')
435        self.assertEqual(regex.match(r"^(\w){1,3}?$", "abc")[1], 'c')
436        self.assertEqual(regex.match(r"^(\w){1,4}?$", "abc")[1], 'c')
437        self.assertEqual(regex.match(r"^(\w){3,4}?$", "abc")[1], 'c')
438
439        self.assertEqual(regex.match("^x{1}$", "xxx"), None)
440        self.assertEqual(regex.match("^x{1}?$", "xxx"), None)
441        self.assertEqual(regex.match("^x{1,2}$", "xxx"), None)
442        self.assertEqual(regex.match("^x{1,2}?$", "xxx"), None)
443
444        self.assertEqual(regex.match("^x{1}", "xxx")[0], 'x')
445        self.assertEqual(regex.match("^x{1}?", "xxx")[0], 'x')
446        self.assertEqual(regex.match("^x{0,1}", "xxx")[0], 'x')
447        self.assertEqual(regex.match("^x{0,1}?", "xxx")[0], '')
448
449        self.assertEqual(bool(regex.match("^x{3}$", "xxx")), True)
450        self.assertEqual(bool(regex.match("^x{1,3}$", "xxx")), True)
451        self.assertEqual(bool(regex.match("^x{1,4}$", "xxx")), True)
452        self.assertEqual(bool(regex.match("^x{3,4}?$", "xxx")), True)
453        self.assertEqual(bool(regex.match("^x{3}?$", "xxx")), True)
454        self.assertEqual(bool(regex.match("^x{1,3}?$", "xxx")), True)
455        self.assertEqual(bool(regex.match("^x{1,4}?$", "xxx")), True)
456        self.assertEqual(bool(regex.match("^x{3,4}?$", "xxx")), True)
457
458        self.assertEqual(regex.match("^x{}$", "xxx"), None)
459        self.assertEqual(bool(regex.match("^x{}$", "x{}")), True)
460
461    def test_getattr(self):
462        self.assertEqual(regex.compile("(?i)(a)(b)").pattern, '(?i)(a)(b)')
463        self.assertEqual(regex.compile("(?i)(a)(b)").flags, regex.I | regex.U |
464          regex.DEFAULT_VERSION)
465        self.assertEqual(regex.compile(b"(?i)(a)(b)").flags, regex.A | regex.I
466          | regex.DEFAULT_VERSION)
467        self.assertEqual(regex.compile("(?i)(a)(b)").groups, 2)
468        self.assertEqual(regex.compile("(?i)(a)(b)").groupindex, {})
469
470        self.assertEqual(regex.compile("(?i)(?P<first>a)(?P<other>b)").groupindex,
471          {'first': 1, 'other': 2})
472
473        self.assertEqual(regex.match("(a)", "a").pos, 0)
474        self.assertEqual(regex.match("(a)", "a").endpos, 1)
475
476        self.assertEqual(regex.search("b(c)", "abcdef").pos, 0)
477        self.assertEqual(regex.search("b(c)", "abcdef").endpos, 6)
478        self.assertEqual(regex.search("b(c)", "abcdef").span(), (1, 3))
479        self.assertEqual(regex.search("b(c)", "abcdef").span(1), (2, 3))
480
481        self.assertEqual(regex.match("(a)", "a").string, 'a')
482        self.assertEqual(regex.match("(a)", "a").regs, ((0, 1), (0, 1)))
483        self.assertEqual(repr(type(regex.match("(a)", "a").re)),
484          self.PATTERN_CLASS)
485
486        # Issue 14260.
487        p = regex.compile(r'abc(?P<n>def)')
488        p.groupindex["n"] = 0
489        self.assertEqual(p.groupindex["n"], 1)
490
491    def test_special_escapes(self):
492        self.assertEqual(regex.search(r"\b(b.)\b", "abcd abc bcd bx")[1], 'bx')
493        self.assertEqual(regex.search(r"\B(b.)\B", "abc bcd bc abxd")[1], 'bx')
494        self.assertEqual(regex.search(br"\b(b.)\b", b"abcd abc bcd bx",
495          regex.LOCALE)[1], b'bx')
496        self.assertEqual(regex.search(br"\B(b.)\B", b"abc bcd bc abxd",
497          regex.LOCALE)[1], b'bx')
498        self.assertEqual(regex.search(r"\b(b.)\b", "abcd abc bcd bx",
499          regex.UNICODE)[1], 'bx')
500        self.assertEqual(regex.search(r"\B(b.)\B", "abc bcd bc abxd",
501          regex.UNICODE)[1], 'bx')
502
503        self.assertEqual(regex.search(r"^abc$", "\nabc\n", regex.M)[0], 'abc')
504        self.assertEqual(regex.search(r"^\Aabc\Z$", "abc", regex.M)[0], 'abc')
505        self.assertEqual(regex.search(r"^\Aabc\Z$", "\nabc\n", regex.M), None)
506
507        self.assertEqual(regex.search(br"\b(b.)\b", b"abcd abc bcd bx")[1],
508          b'bx')
509        self.assertEqual(regex.search(br"\B(b.)\B", b"abc bcd bc abxd")[1],
510          b'bx')
511        self.assertEqual(regex.search(br"^abc$", b"\nabc\n", regex.M)[0],
512          b'abc')
513        self.assertEqual(regex.search(br"^\Aabc\Z$", b"abc", regex.M)[0],
514          b'abc')
515        self.assertEqual(regex.search(br"^\Aabc\Z$", b"\nabc\n", regex.M),
516          None)
517
518        self.assertEqual(regex.search(r"\d\D\w\W\s\S", "1aa! a")[0], '1aa! a')
519        self.assertEqual(regex.search(br"\d\D\w\W\s\S", b"1aa! a",
520          regex.LOCALE)[0], b'1aa! a')
521        self.assertEqual(regex.search(r"\d\D\w\W\s\S", "1aa! a",
522          regex.UNICODE)[0], '1aa! a')
523
524    def test_bigcharset(self):
525        self.assertEqual(regex.match(r"([\u2222\u2223])", "\u2222")[1],
526          '\u2222')
527        self.assertEqual(regex.match(r"([\u2222\u2223])", "\u2222",
528          regex.UNICODE)[1], '\u2222')
529        self.assertEqual("".join(regex.findall(".",
530          "e\xe8\xe9\xea\xeb\u0113\u011b\u0117", flags=regex.UNICODE)),
531          'e\xe8\xe9\xea\xeb\u0113\u011b\u0117')
532        self.assertEqual("".join(regex.findall(r"[e\xe8\xe9\xea\xeb\u0113\u011b\u0117]",
533          "e\xe8\xe9\xea\xeb\u0113\u011b\u0117", flags=regex.UNICODE)),
534          'e\xe8\xe9\xea\xeb\u0113\u011b\u0117')
535        self.assertEqual("".join(regex.findall(r"e|\xe8|\xe9|\xea|\xeb|\u0113|\u011b|\u0117",
536          "e\xe8\xe9\xea\xeb\u0113\u011b\u0117", flags=regex.UNICODE)),
537          'e\xe8\xe9\xea\xeb\u0113\u011b\u0117')
538
539    def test_anyall(self):
540        self.assertEqual(regex.match("a.b", "a\nb", regex.DOTALL)[0], "a\nb")
541        self.assertEqual(regex.match("a.*b", "a\n\nb", regex.DOTALL)[0],
542          "a\n\nb")
543
544    def test_non_consuming(self):
545        self.assertEqual(regex.match(r"(a(?=\s[^a]))", "a b")[1], 'a')
546        self.assertEqual(regex.match(r"(a(?=\s[^a]*))", "a b")[1], 'a')
547        self.assertEqual(regex.match(r"(a(?=\s[abc]))", "a b")[1], 'a')
548        self.assertEqual(regex.match(r"(a(?=\s[abc]*))", "a bc")[1], 'a')
549        self.assertEqual(regex.match(r"(a)(?=\s\1)", "a a")[1], 'a')
550        self.assertEqual(regex.match(r"(a)(?=\s\1*)", "a aa")[1], 'a')
551        self.assertEqual(regex.match(r"(a)(?=\s(abc|a))", "a a")[1], 'a')
552
553        self.assertEqual(regex.match(r"(a(?!\s[^a]))", "a a")[1], 'a')
554        self.assertEqual(regex.match(r"(a(?!\s[abc]))", "a d")[1], 'a')
555        self.assertEqual(regex.match(r"(a)(?!\s\1)", "a b")[1], 'a')
556        self.assertEqual(regex.match(r"(a)(?!\s(abc|a))", "a b")[1], 'a')
557
558    def test_ignore_case(self):
559        self.assertEqual(regex.match("abc", "ABC", regex.I)[0], 'ABC')
560        self.assertEqual(regex.match(b"abc", b"ABC", regex.I)[0], b'ABC')
561
562        self.assertEqual(regex.match(r"(a\s[^a]*)", "a bb", regex.I)[1],
563          'a bb')
564        self.assertEqual(regex.match(r"(a\s[abc])", "a b", regex.I)[1], 'a b')
565        self.assertEqual(regex.match(r"(a\s[abc]*)", "a bb", regex.I)[1],
566          'a bb')
567        self.assertEqual(regex.match(r"((a)\s\2)", "a a", regex.I)[1], 'a a')
568        self.assertEqual(regex.match(r"((a)\s\2*)", "a aa", regex.I)[1],
569          'a aa')
570        self.assertEqual(regex.match(r"((a)\s(abc|a))", "a a", regex.I)[1],
571          'a a')
572        self.assertEqual(regex.match(r"((a)\s(abc|a)*)", "a aa", regex.I)[1],
573          'a aa')
574
575        # Issue 3511.
576        self.assertEqual(regex.match(r"[Z-a]", "_").span(), (0, 1))
577        self.assertEqual(regex.match(r"(?i)[Z-a]", "_").span(), (0, 1))
578
579        self.assertEqual(bool(regex.match(r"(?i)nao", "nAo")), True)
580        self.assertEqual(bool(regex.match(r"(?i)n\xE3o", "n\xC3o")), True)
581        self.assertEqual(bool(regex.match(r"(?i)n\xE3o", "N\xC3O")), True)
582        self.assertEqual(bool(regex.match(r"(?i)s", "\u017F")), True)
583
584    def test_case_folding(self):
585        self.assertEqual(regex.search(r"(?fi)ss", "SS").span(), (0, 2))
586        self.assertEqual(regex.search(r"(?fi)SS", "ss").span(), (0, 2))
587        self.assertEqual(regex.search(r"(?fi)SS",
588          "\N{LATIN SMALL LETTER SHARP S}").span(), (0, 1))
589        self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LETTER SHARP S}",
590          "SS").span(), (0, 2))
591
592        self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LIGATURE ST}",
593          "ST").span(), (0, 2))
594        self.assertEqual(regex.search(r"(?fi)ST",
595          "\N{LATIN SMALL LIGATURE ST}").span(), (0, 1))
596        self.assertEqual(regex.search(r"(?fi)ST",
597          "\N{LATIN SMALL LIGATURE LONG S T}").span(), (0, 1))
598
599        self.assertEqual(regex.search(r"(?fi)SST",
600          "\N{LATIN SMALL LETTER SHARP S}t").span(), (0, 2))
601        self.assertEqual(regex.search(r"(?fi)SST",
602          "s\N{LATIN SMALL LIGATURE LONG S T}").span(), (0, 2))
603        self.assertEqual(regex.search(r"(?fi)SST",
604          "s\N{LATIN SMALL LIGATURE ST}").span(), (0, 2))
605        self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LIGATURE ST}",
606          "SST").span(), (1, 3))
607        self.assertEqual(regex.search(r"(?fi)SST",
608          "s\N{LATIN SMALL LIGATURE ST}").span(), (0, 2))
609
610        self.assertEqual(regex.search(r"(?fi)FFI",
611          "\N{LATIN SMALL LIGATURE FFI}").span(), (0, 1))
612        self.assertEqual(regex.search(r"(?fi)FFI",
613          "\N{LATIN SMALL LIGATURE FF}i").span(), (0, 2))
614        self.assertEqual(regex.search(r"(?fi)FFI",
615          "f\N{LATIN SMALL LIGATURE FI}").span(), (0, 2))
616        self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LIGATURE FFI}",
617          "FFI").span(), (0, 3))
618        self.assertEqual(regex.search(r"(?fi)\N{LATIN SMALL LIGATURE FF}i",
619          "FFI").span(), (0, 3))
620        self.assertEqual(regex.search(r"(?fi)f\N{LATIN SMALL LIGATURE FI}",
621          "FFI").span(), (0, 3))
622
623        sigma = "\u03A3\u03C3\u03C2"
624        for ch1 in sigma:
625            for ch2 in sigma:
626                if not regex.match(r"(?fi)" + ch1, ch2):
627                    self.fail()
628
629        self.assertEqual(bool(regex.search(r"(?iV1)ff", "\uFB00\uFB01")),
630          True)
631        self.assertEqual(bool(regex.search(r"(?iV1)ff", "\uFB01\uFB00")),
632          True)
633        self.assertEqual(bool(regex.search(r"(?iV1)fi", "\uFB00\uFB01")),
634          True)
635        self.assertEqual(bool(regex.search(r"(?iV1)fi", "\uFB01\uFB00")),
636          True)
637        self.assertEqual(bool(regex.search(r"(?iV1)fffi", "\uFB00\uFB01")),
638          True)
639        self.assertEqual(bool(regex.search(r"(?iV1)f\uFB03",
640          "\uFB00\uFB01")), True)
641        self.assertEqual(bool(regex.search(r"(?iV1)ff", "\uFB00\uFB01")),
642          True)
643        self.assertEqual(bool(regex.search(r"(?iV1)fi", "\uFB00\uFB01")),
644          True)
645        self.assertEqual(bool(regex.search(r"(?iV1)fffi", "\uFB00\uFB01")),
646          True)
647        self.assertEqual(bool(regex.search(r"(?iV1)f\uFB03",
648          "\uFB00\uFB01")), True)
649        self.assertEqual(bool(regex.search(r"(?iV1)f\uFB01", "\uFB00i")),
650          True)
651        self.assertEqual(bool(regex.search(r"(?iV1)f\uFB01", "\uFB00i")),
652          True)
653
654        self.assertEqual(regex.findall(r"(?iV0)\m(?:word){e<=3}\M(?<!\m(?:word){e<=1}\M)",
655          "word word2 word word3 word word234 word23 word"), ["word234",
656          "word23"])
657        self.assertEqual(regex.findall(r"(?iV1)\m(?:word){e<=3}\M(?<!\m(?:word){e<=1}\M)",
658          "word word2 word word3 word word234 word23 word"), ["word234",
659          "word23"])
660
661        self.assertEqual(regex.search(r"(?fi)a\N{LATIN SMALL LIGATURE FFI}ne",
662          "  affine  ").span(), (2, 8))
663        self.assertEqual(regex.search(r"(?fi)a(?:\N{LATIN SMALL LIGATURE FFI}|x)ne",
664           "  affine  ").span(), (2, 8))
665        self.assertEqual(regex.search(r"(?fi)a(?:\N{LATIN SMALL LIGATURE FFI}|xy)ne",
666           "  affine  ").span(), (2, 8))
667        self.assertEqual(regex.search(r"(?fi)a\L<options>ne", "affine",
668          options=["\N{LATIN SMALL LIGATURE FFI}"]).span(), (0, 6))
669        self.assertEqual(regex.search(r"(?fi)a\L<options>ne",
670          "a\N{LATIN SMALL LIGATURE FFI}ne", options=["ffi"]).span(), (0, 4))
671
672    def test_category(self):
673        self.assertEqual(regex.match(r"(\s)", " ")[1], ' ')
674
675    def test_not_literal(self):
676        self.assertEqual(regex.search(r"\s([^a])", " b")[1], 'b')
677        self.assertEqual(regex.search(r"\s([^a]*)", " bb")[1], 'bb')
678
679    def test_search_coverage(self):
680        self.assertEqual(regex.search(r"\s(b)", " b")[1], 'b')
681        self.assertEqual(regex.search(r"a\s", "a ")[0], 'a ')
682
683    def test_re_escape(self):
684        p = ""
685        self.assertEqual(regex.escape(p), p)
686        for i in range(0, 256):
687            p += chr(i)
688            self.assertEqual(bool(regex.match(regex.escape(chr(i)), chr(i))),
689              True)
690            self.assertEqual(regex.match(regex.escape(chr(i)), chr(i)).span(),
691              (0, 1))
692
693        pat = regex.compile(regex.escape(p))
694        self.assertEqual(pat.match(p).span(), (0, 256))
695
696    def test_re_escape_byte(self):
697        p = b""
698        self.assertEqual(regex.escape(p), p)
699        for i in range(0, 256):
700            b = bytes([i])
701            p += b
702            self.assertEqual(bool(regex.match(regex.escape(b), b)), True)
703            self.assertEqual(regex.match(regex.escape(b), b).span(), (0, 1))
704
705        pat = regex.compile(regex.escape(p))
706        self.assertEqual(pat.match(p).span(), (0, 256))
707
708    def test_constants(self):
709        if regex.I != regex.IGNORECASE:
710            self.fail()
711        if regex.L != regex.LOCALE:
712            self.fail()
713        if regex.M != regex.MULTILINE:
714            self.fail()
715        if regex.S != regex.DOTALL:
716            self.fail()
717        if regex.X != regex.VERBOSE:
718            self.fail()
719
720    def test_flags(self):
721        for flag in [regex.I, regex.M, regex.X, regex.S, regex.L]:
722            self.assertEqual(repr(type(regex.compile('^pattern$', flag))),
723              self.PATTERN_CLASS)
724
725    def test_sre_character_literals(self):
726        for i in [0, 8, 16, 32, 64, 127, 128, 255]:
727            self.assertEqual(bool(regex.match(r"\%03o" % i, chr(i))), True)
728            self.assertEqual(bool(regex.match(r"\%03o0" % i, chr(i) + "0")),
729              True)
730            self.assertEqual(bool(regex.match(r"\%03o8" % i, chr(i) + "8")),
731              True)
732            self.assertEqual(bool(regex.match(r"\x%02x" % i, chr(i))), True)
733            self.assertEqual(bool(regex.match(r"\x%02x0" % i, chr(i) + "0")),
734              True)
735            self.assertEqual(bool(regex.match(r"\x%02xz" % i, chr(i) + "z")),
736              True)
737
738        self.assertRaisesRegex(regex.error, self.INVALID_GROUP_REF, lambda:
739          regex.match(r"\911", ""))
740
741    def test_sre_character_class_literals(self):
742        for i in [0, 8, 16, 32, 64, 127, 128, 255]:
743            self.assertEqual(bool(regex.match(r"[\%03o]" % i, chr(i))), True)
744            self.assertEqual(bool(regex.match(r"[\%03o0]" % i, chr(i))), True)
745            self.assertEqual(bool(regex.match(r"[\%03o8]" % i, chr(i))), True)
746            self.assertEqual(bool(regex.match(r"[\x%02x]" % i, chr(i))), True)
747            self.assertEqual(bool(regex.match(r"[\x%02x0]" % i, chr(i))), True)
748            self.assertEqual(bool(regex.match(r"[\x%02xz]" % i, chr(i))), True)
749
750        self.assertRaisesRegex(regex.error, self.BAD_OCTAL_ESCAPE, lambda:
751          regex.match(r"[\911]", ""))
752
753    def test_bug_113254(self):
754        self.assertEqual(regex.match(r'(a)|(b)', 'b').start(1), -1)
755        self.assertEqual(regex.match(r'(a)|(b)', 'b').end(1), -1)
756        self.assertEqual(regex.match(r'(a)|(b)', 'b').span(1), (-1, -1))
757
758    def test_bug_527371(self):
759        # Bug described in patches 527371/672491.
760        self.assertEqual(regex.match(r'(a)?a','a').lastindex, None)
761        self.assertEqual(regex.match(r'(a)(b)?b','ab').lastindex, 1)
762        self.assertEqual(regex.match(r'(?P<a>a)(?P<b>b)?b','ab').lastgroup,
763          'a')
764        self.assertEqual(regex.match("(?P<a>a(b))", "ab").lastgroup, 'a')
765        self.assertEqual(regex.match("((a))", "a").lastindex, 1)
766
767    def test_bug_545855(self):
768        # Bug 545855 -- This pattern failed to cause a compile error as it
769        # should, instead provoking a TypeError.
770        self.assertRaisesRegex(regex.error, self.BAD_SET, lambda:
771          regex.compile('foo[a-'))
772
773    def test_bug_418626(self):
774        # Bugs 418626 at al. -- Testing Greg Chapman's addition of op code
775        # SRE_OP_MIN_REPEAT_ONE for eliminating recursion on simple uses of
776        # pattern '*?' on a long string.
777        self.assertEqual(regex.match('.*?c', 10000 * 'ab' + 'cd').end(0),
778          20001)
779        self.assertEqual(regex.match('.*?cd', 5000 * 'ab' + 'c' + 5000 * 'ab' +
780          'cde').end(0), 20003)
781        self.assertEqual(regex.match('.*?cd', 20000 * 'abc' + 'de').end(0),
782          60001)
783        # Non-simple '*?' still used to hit the recursion limit, before the
784        # non-recursive scheme was implemented.
785        self.assertEqual(regex.search('(a|b)*?c', 10000 * 'ab' + 'cd').end(0),
786          20001)
787
788    def test_bug_612074(self):
789        pat = "[" + regex.escape("\u2039") + "]"
790        self.assertEqual(regex.compile(pat) and 1, 1)
791
792    def test_stack_overflow(self):
793        # Nasty cases that used to overflow the straightforward recursive
794        # implementation of repeated groups.
795        self.assertEqual(regex.match('(x)*', 50000 * 'x')[1], 'x')
796        self.assertEqual(regex.match('(x)*y', 50000 * 'x' + 'y')[1], 'x')
797        self.assertEqual(regex.match('(x)*?y', 50000 * 'x' + 'y')[1], 'x')
798
799    def test_scanner(self):
800        def s_ident(scanner, token): return token
801        def s_operator(scanner, token): return "op%s" % token
802        def s_float(scanner, token): return float(token)
803        def s_int(scanner, token): return int(token)
804
805        scanner = regex.Scanner([(r"[a-zA-Z_]\w*", s_ident), (r"\d+\.\d*",
806          s_float), (r"\d+", s_int), (r"=|\+|-|\*|/", s_operator), (r"\s+",
807            None), ])
808
809        self.assertEqual(repr(type(scanner.scanner.scanner("").pattern)),
810          self.PATTERN_CLASS)
811
812        self.assertEqual(scanner.scan("sum = 3*foo + 312.50 + bar"), (['sum',
813          'op=', 3, 'op*', 'foo', 'op+', 312.5, 'op+', 'bar'], ''))
814
815    def test_bug_448951(self):
816        # Bug 448951 (similar to 429357, but with single char match).
817        # (Also test greedy matches.)
818        for op in '', '?', '*':
819            self.assertEqual(regex.match(r'((.%s):)?z' % op, 'z')[:], ('z',
820              None, None))
821            self.assertEqual(regex.match(r'((.%s):)?z' % op, 'a:z')[:], ('a:z',
822              'a:', 'a'))
823
824    def test_bug_725106(self):
825        # Capturing groups in alternatives in repeats.
826        self.assertEqual(regex.match('^((a)|b)*', 'abc')[:], ('ab', 'b', 'a'))
827        self.assertEqual(regex.match('^(([ab])|c)*', 'abc')[:], ('abc', 'c',
828          'b'))
829        self.assertEqual(regex.match('^((d)|[ab])*', 'abc')[:], ('ab', 'b',
830          None))
831        self.assertEqual(regex.match('^((a)c|[ab])*', 'abc')[:], ('ab', 'b',
832          None))
833        self.assertEqual(regex.match('^((a)|b)*?c', 'abc')[:], ('abc', 'b',
834          'a'))
835        self.assertEqual(regex.match('^(([ab])|c)*?d', 'abcd')[:], ('abcd',
836          'c', 'b'))
837        self.assertEqual(regex.match('^((d)|[ab])*?c', 'abc')[:], ('abc', 'b',
838          None))
839        self.assertEqual(regex.match('^((a)c|[ab])*?c', 'abc')[:], ('abc', 'b',
840          None))
841
842    def test_bug_725149(self):
843        # Mark_stack_base restoring before restoring marks.
844        self.assertEqual(regex.match('(a)(?:(?=(b)*)c)*', 'abb')[:], ('a', 'a',
845          None))
846        self.assertEqual(regex.match('(a)((?!(b)*))*', 'abb')[:], ('a', 'a',
847          None, None))
848
849    def test_bug_764548(self):
850        # Bug 764548, regex.compile() barfs on str/unicode subclasses.
851        class my_unicode(str): pass
852        pat = regex.compile(my_unicode("abc"))
853        self.assertEqual(pat.match("xyz"), None)
854
855    def test_finditer(self):
856        it = regex.finditer(r":+", "a:b::c:::d")
857        self.assertEqual([item[0] for item in it], [':', '::', ':::'])
858
859    def test_bug_926075(self):
860        if regex.compile('bug_926075') is regex.compile(b'bug_926075'):
861            self.fail()
862
863    def test_bug_931848(self):
864        pattern = "[\u002E\u3002\uFF0E\uFF61]"
865        self.assertEqual(regex.compile(pattern).split("a.b.c"), ['a', 'b',
866          'c'])
867
868    def test_bug_581080(self):
869        it = regex.finditer(r"\s", "a b")
870        self.assertEqual(next(it).span(), (1, 2))
871        self.assertRaises(StopIteration, lambda: next(it))
872
873        scanner = regex.compile(r"\s").scanner("a b")
874        self.assertEqual(scanner.search().span(), (1, 2))
875        self.assertEqual(scanner.search(), None)
876
877    def test_bug_817234(self):
878        it = regex.finditer(r".*", "asdf")
879        self.assertEqual(next(it).span(), (0, 4))
880        self.assertEqual(next(it).span(), (4, 4))
881        self.assertRaises(StopIteration, lambda: next(it))
882
883    def test_empty_array(self):
884        # SF buf 1647541.
885        import array
886        for typecode in 'bBhHiIlLfd':
887            a = array.array(typecode)
888            self.assertEqual(regex.compile(b"bla").match(a), None)
889            self.assertEqual(regex.compile(b"").match(a)[1 : ], ())
890
891    def test_inline_flags(self):
892        # Bug #1700.
893        upper_char = chr(0x1ea0) # Latin Capital Letter A with Dot Below
894        lower_char = chr(0x1ea1) # Latin Small Letter A with Dot Below
895
896        p = regex.compile(upper_char, regex.I | regex.U)
897        self.assertEqual(bool(p.match(lower_char)), True)
898
899        p = regex.compile(lower_char, regex.I | regex.U)
900        self.assertEqual(bool(p.match(upper_char)), True)
901
902        p = regex.compile('(?i)' + upper_char, regex.U)
903        self.assertEqual(bool(p.match(lower_char)), True)
904
905        p = regex.compile('(?i)' + lower_char, regex.U)
906        self.assertEqual(bool(p.match(upper_char)), True)
907
908        p = regex.compile('(?iu)' + upper_char)
909        self.assertEqual(bool(p.match(lower_char)), True)
910
911        p = regex.compile('(?iu)' + lower_char)
912        self.assertEqual(bool(p.match(upper_char)), True)
913
914        # Changed to positional flags in regex 2023.12.23.
915        self.assertEqual(bool(regex.match(r"(?i)a", "A")), True)
916        self.assertEqual(regex.match(r"a(?i)", "A"), None)
917
918    def test_dollar_matches_twice(self):
919        # $ matches the end of string, and just before the terminating \n.
920        pattern = regex.compile('$')
921        self.assertEqual(pattern.sub('#', 'a\nb\n'), 'a\nb#\n#')
922        self.assertEqual(pattern.sub('#', 'a\nb\nc'), 'a\nb\nc#')
923        self.assertEqual(pattern.sub('#', '\n'), '#\n#')
924
925        pattern = regex.compile('$', regex.MULTILINE)
926        self.assertEqual(pattern.sub('#', 'a\nb\n' ), 'a#\nb#\n#')
927        self.assertEqual(pattern.sub('#', 'a\nb\nc'), 'a#\nb#\nc#')
928        self.assertEqual(pattern.sub('#', '\n'), '#\n#')
929
930    def test_bytes_str_mixing(self):
931        # Mixing str and bytes is disallowed.
932        pat = regex.compile('.')
933        bpat = regex.compile(b'.')
934        self.assertRaisesRegex(TypeError, self.STR_PAT_ON_BYTES, lambda:
935          pat.match(b'b'))
936        self.assertRaisesRegex(TypeError, self.BYTES_PAT_ON_STR, lambda:
937          bpat.match('b'))
938        self.assertRaisesRegex(TypeError, self.STR_PAT_BYTES_TEMPL, lambda:
939          pat.sub(b'b', 'c'))
940        self.assertRaisesRegex(TypeError, self.STR_PAT_ON_BYTES, lambda:
941          pat.sub('b', b'c'))
942        self.assertRaisesRegex(TypeError, self.STR_PAT_ON_BYTES, lambda:
943          pat.sub(b'b', b'c'))
944        self.assertRaisesRegex(TypeError, self.BYTES_PAT_ON_STR, lambda:
945          bpat.sub(b'b', 'c'))
946        self.assertRaisesRegex(TypeError, self.BYTES_PAT_STR_TEMPL, lambda:
947          bpat.sub('b', b'c'))
948        self.assertRaisesRegex(TypeError, self.BYTES_PAT_ON_STR, lambda:
949          bpat.sub('b', 'c'))
950
951        self.assertRaisesRegex(ValueError, self.BYTES_PAT_UNI_FLAG, lambda:
952          regex.compile(br'\w', regex.UNICODE))
953        self.assertRaisesRegex(ValueError, self.BYTES_PAT_UNI_FLAG, lambda:
954          regex.compile(br'(?u)\w'))
955        self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda:
956          regex.compile(r'\w', regex.UNICODE | regex.ASCII))
957        self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda:
958          regex.compile(r'(?u)\w', regex.ASCII))
959        self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda:
960          regex.compile(r'(?a)\w', regex.UNICODE))
961        self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda:
962          regex.compile(r'(?au)\w'))
963
964    def test_ascii_and_unicode_flag(self):
965        # String patterns.
966        for flags in (0, regex.UNICODE):
967            pat = regex.compile('\xc0', flags | regex.IGNORECASE)
968            self.assertEqual(bool(pat.match('\xe0')), True)
969            pat = regex.compile(r'\w', flags)
970            self.assertEqual(bool(pat.match('\xe0')), True)
971
972        pat = regex.compile('\xc0', regex.ASCII | regex.IGNORECASE)
973        self.assertEqual(pat.match('\xe0'), None)
974        pat = regex.compile('(?a)\xc0', regex.IGNORECASE)
975        self.assertEqual(pat.match('\xe0'), None)
976        pat = regex.compile(r'\w', regex.ASCII)
977        self.assertEqual(pat.match('\xe0'), None)
978        pat = regex.compile(r'(?a)\w')
979        self.assertEqual(pat.match('\xe0'), None)
980
981        # Bytes patterns.
982        for flags in (0, regex.ASCII):
983            pat = regex.compile(b'\xc0', flags | regex.IGNORECASE)
984            self.assertEqual(pat.match(b'\xe0'), None)
985            pat = regex.compile(br'\w')
986            self.assertEqual(pat.match(b'\xe0'), None)
987
988        self.assertRaisesRegex(ValueError, self.MIXED_FLAGS, lambda:
989          regex.compile(r'(?au)\w'))
990
991    def test_subscripting_match(self):
992        m = regex.match(r'(?<a>\w)', 'xy')
993        if not m:
994            self.fail("Failed: expected match but returned None")
995        elif not m or m[0] != m.group(0) or m[1] != m.group(1):
996            self.fail("Failed")
997        if not m:
998            self.fail("Failed: expected match but returned None")
999        elif m[:] != ('x', 'x'):
1000            self.fail("Failed: expected \"('x', 'x')\" but got {} instead".format(ascii(m[:])))
1001
1002    def test_new_named_groups(self):
1003        m0 = regex.match(r'(?P<a>\w)', 'x')
1004        m1 = regex.match(r'(?<a>\w)', 'x')
1005        if not (m0 and m1 and m0[:] == m1[:]):
1006            self.fail("Failed")
1007
1008    def test_properties(self):
1009        self.assertEqual(regex.match(b'(?ai)\xC0', b'\xE0'), None)
1010        self.assertEqual(regex.match(br'(?ai)\xC0', b'\xE0'), None)
1011        self.assertEqual(regex.match(br'(?a)\w', b'\xE0'), None)
1012        self.assertEqual(bool(regex.match(r'\w', '\xE0')), True)
1013
1014        # Dropped the following test. It's not possible to determine what the
1015        # correct result should be in the general case.
1016#        self.assertEqual(bool(regex.match(br'(?L)\w', b'\xE0')),
1017#          b'\xE0'.isalnum())
1018
1019        self.assertEqual(bool(regex.match(br'(?L)\d', b'0')), True)
1020        self.assertEqual(bool(regex.match(br'(?L)\s', b' ')), True)
1021        self.assertEqual(bool(regex.match(br'(?L)\w', b'a')), True)
1022        self.assertEqual(regex.match(br'(?L)\d', b'?'), None)
1023        self.assertEqual(regex.match(br'(?L)\s', b'?'), None)
1024        self.assertEqual(regex.match(br'(?L)\w', b'?'), None)
1025
1026        self.assertEqual(regex.match(br'(?L)\D', b'0'), None)
1027        self.assertEqual(regex.match(br'(?L)\S', b' '), None)
1028        self.assertEqual(regex.match(br'(?L)\W', b'a'), None)
1029        self.assertEqual(bool(regex.match(br'(?L)\D', b'?')), True)
1030        self.assertEqual(bool(regex.match(br'(?L)\S', b'?')), True)
1031        self.assertEqual(bool(regex.match(br'(?L)\W', b'?')), True)
1032
1033        self.assertEqual(bool(regex.match(r'\p{Cyrillic}',
1034          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1035        self.assertEqual(bool(regex.match(r'(?i)\p{Cyrillic}',
1036          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1037        self.assertEqual(bool(regex.match(r'\p{IsCyrillic}',
1038          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1039        self.assertEqual(bool(regex.match(r'\p{Script=Cyrillic}',
1040          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1041        self.assertEqual(bool(regex.match(r'\p{InCyrillic}',
1042          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1043        self.assertEqual(bool(regex.match(r'\p{Block=Cyrillic}',
1044          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1045        self.assertEqual(bool(regex.match(r'[[:Cyrillic:]]',
1046          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1047        self.assertEqual(bool(regex.match(r'[[:IsCyrillic:]]',
1048          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1049        self.assertEqual(bool(regex.match(r'[[:Script=Cyrillic:]]',
1050          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1051        self.assertEqual(bool(regex.match(r'[[:InCyrillic:]]',
1052          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1053        self.assertEqual(bool(regex.match(r'[[:Block=Cyrillic:]]',
1054          '\N{CYRILLIC CAPITAL LETTER A}')), True)
1055
1056        self.assertEqual(bool(regex.match(r'\P{Cyrillic}',
1057          '\N{LATIN CAPITAL LETTER A}')), True)
1058        self.assertEqual(bool(regex.match(r'\P{IsCyrillic}',
1059          '\N{LATIN CAPITAL LETTER A}')), True)
1060        self.assertEqual(bool(regex.match(r'\P{Script=Cyrillic}',
1061          '\N{LATIN CAPITAL LETTER A}')), True)
1062        self.assertEqual(bool(regex.match(r'\P{InCyrillic}',
1063          '\N{LATIN CAPITAL LETTER A}')), True)
1064        self.assertEqual(bool(regex.match(r'\P{Block=Cyrillic}',
1065          '\N{LATIN CAPITAL LETTER A}')), True)
1066        self.assertEqual(bool(regex.match(r'\p{^Cyrillic}',
1067          '\N{LATIN CAPITAL LETTER A}')), True)
1068        self.assertEqual(bool(regex.match(r'\p{^IsCyrillic}',
1069          '\N{LATIN CAPITAL LETTER A}')), True)
1070        self.assertEqual(bool(regex.match(r'\p{^Script=Cyrillic}',
1071          '\N{LATIN CAPITAL LETTER A}')), True)
1072        self.assertEqual(bool(regex.match(r'\p{^InCyrillic}',
1073          '\N{LATIN CAPITAL LETTER A}')), True)
1074        self.assertEqual(bool(regex.match(r'\p{^Block=Cyrillic}',
1075          '\N{LATIN CAPITAL LETTER A}')), True)
1076        self.assertEqual(bool(regex.match(r'[[:^Cyrillic:]]',
1077          '\N{LATIN CAPITAL LETTER A}')), True)
1078        self.assertEqual(bool(regex.match(r'[[:^IsCyrillic:]]',
1079          '\N{LATIN CAPITAL LETTER A}')), True)
1080        self.assertEqual(bool(regex.match(r'[[:^Script=Cyrillic:]]',
1081          '\N{LATIN CAPITAL LETTER A}')), True)
1082        self.assertEqual(bool(regex.match(r'[[:^InCyrillic:]]',
1083          '\N{LATIN CAPITAL LETTER A}')), True)
1084        self.assertEqual(bool(regex.match(r'[[:^Block=Cyrillic:]]',
1085          '\N{LATIN CAPITAL LETTER A}')), True)
1086
1087        self.assertEqual(bool(regex.match(r'\d', '0')), True)
1088        self.assertEqual(bool(regex.match(r'\s', ' ')), True)
1089        self.assertEqual(bool(regex.match(r'\w', 'A')), True)
1090        self.assertEqual(regex.match(r"\d", "?"), None)
1091        self.assertEqual(regex.match(r"\s", "?"), None)
1092        self.assertEqual(regex.match(r"\w", "?"), None)
1093        self.assertEqual(regex.match(r"\D", "0"), None)
1094        self.assertEqual(regex.match(r"\S", " "), None)
1095        self.assertEqual(regex.match(r"\W", "A"), None)
1096        self.assertEqual(bool(regex.match(r'\D', '?')), True)
1097        self.assertEqual(bool(regex.match(r'\S', '?')), True)
1098        self.assertEqual(bool(regex.match(r'\W', '?')), True)
1099
1100        self.assertEqual(bool(regex.match(r'\p{L}', 'A')), True)
1101        self.assertEqual(bool(regex.match(r'\p{L}', 'a')), True)
1102        self.assertEqual(bool(regex.match(r'\p{Lu}', 'A')), True)
1103        self.assertEqual(bool(regex.match(r'\p{Ll}', 'a')), True)
1104
1105        self.assertEqual(bool(regex.match(r'(?i)a', 'a')), True)
1106        self.assertEqual(bool(regex.match(r'(?i)a', 'A')), True)
1107
1108        self.assertEqual(bool(regex.match(r'\w', '0')), True)
1109        self.assertEqual(bool(regex.match(r'\w', 'a')), True)
1110        self.assertEqual(bool(regex.match(r'\w', '_')), True)
1111
1112        self.assertEqual(regex.match(r"\X", "\xE0").span(), (0, 1))
1113        self.assertEqual(regex.match(r"\X", "a\u0300").span(), (0, 2))
1114        self.assertEqual(regex.findall(r"\X",
1115          "a\xE0a\u0300e\xE9e\u0301"), ['a', '\xe0', 'a\u0300', 'e',
1116          '\xe9', 'e\u0301'])
1117        self.assertEqual(regex.findall(r"\X{3}",
1118          "a\xE0a\u0300e\xE9e\u0301"), ['a\xe0a\u0300', 'e\xe9e\u0301'])
1119        self.assertEqual(regex.findall(r"\X", "\r\r\n\u0301A\u0301"),
1120          ['\r', '\r\n', '\u0301', 'A\u0301'])
1121
1122        self.assertEqual(bool(regex.match(r'\p{Ll}', 'a')), True)
1123
1124        chars_u = "-09AZaz_\u0393\u03b3"
1125        chars_b = b"-09AZaz_"
1126        word_set = set("Ll Lm Lo Lt Lu Mc Me Mn Nd Nl No Pc".split())
1127
1128        tests = [
1129            (r"\w", chars_u, "09AZaz_\u0393\u03b3"),
1130            (r"[[:word:]]", chars_u, "09AZaz_\u0393\u03b3"),
1131            (r"\W", chars_u, "-"),
1132            (r"[[:^word:]]", chars_u, "-"),
1133            (r"\d", chars_u, "09"),
1134            (r"[[:digit:]]", chars_u, "09"),
1135            (r"\D", chars_u, "-AZaz_\u0393\u03b3"),
1136            (r"[[:^digit:]]", chars_u, "-AZaz_\u0393\u03b3"),
1137            (r"[[:alpha:]]", chars_u, "AZaz\u0393\u03b3"),
1138            (r"[[:^alpha:]]", chars_u, "-09_"),
1139            (r"[[:alnum:]]", chars_u, "09AZaz\u0393\u03b3"),
1140            (r"[[:^alnum:]]", chars_u, "-_"),
1141            (r"[[:xdigit:]]", chars_u, "09Aa"),
1142            (r"[[:^xdigit:]]", chars_u, "-Zz_\u0393\u03b3"),
1143            (r"\p{InBasicLatin}", "a\xE1", "a"),
1144            (r"\P{InBasicLatin}", "a\xE1", "\xE1"),
1145            (r"(?i)\p{InBasicLatin}", "a\xE1", "a"),
1146            (r"(?i)\P{InBasicLatin}", "a\xE1", "\xE1"),
1147
1148            (br"(?L)\w", chars_b, b"09AZaz_"),
1149            (br"(?L)[[:word:]]", chars_b, b"09AZaz_"),
1150            (br"(?L)\W", chars_b, b"-"),
1151            (br"(?L)[[:^word:]]", chars_b, b"-"),
1152            (br"(?L)\d", chars_b, b"09"),
1153            (br"(?L)[[:digit:]]", chars_b, b"09"),
1154            (br"(?L)\D", chars_b, b"-AZaz_"),
1155            (br"(?L)[[:^digit:]]", chars_b, b"-AZaz_"),
1156            (br"(?L)[[:alpha:]]", chars_b, b"AZaz"),
1157            (br"(?L)[[:^alpha:]]", chars_b, b"-09_"),
1158            (br"(?L)[[:alnum:]]", chars_b, b"09AZaz"),
1159            (br"(?L)[[:^alnum:]]", chars_b, b"-_"),
1160            (br"(?L)[[:xdigit:]]", chars_b, b"09Aa"),
1161            (br"(?L)[[:^xdigit:]]", chars_b, b"-Zz_"),
1162
1163            (br"(?a)\w", chars_b, b"09AZaz_"),
1164            (br"(?a)[[:word:]]", chars_b, b"09AZaz_"),
1165            (br"(?a)\W", chars_b, b"-"),
1166            (br"(?a)[[:^word:]]", chars_b, b"-"),
1167            (br"(?a)\d", chars_b, b"09"),
1168            (br"(?a)[[:digit:]]", chars_b, b"09"),
1169            (br"(?a)\D", chars_b, b"-AZaz_"),
1170            (br"(?a)[[:^digit:]]", chars_b, b"-AZaz_"),
1171            (br"(?a)[[:alpha:]]", chars_b, b"AZaz"),
1172            (br"(?a)[[:^alpha:]]", chars_b, b"-09_"),
1173            (br"(?a)[[:alnum:]]", chars_b, b"09AZaz"),
1174            (br"(?a)[[:^alnum:]]", chars_b, b"-_"),
1175            (br"(?a)[[:xdigit:]]", chars_b, b"09Aa"),
1176            (br"(?a)[[:^xdigit:]]", chars_b, b"-Zz_"),
1177        ]
1178        for pattern, chars, expected in tests:
1179            try:
1180                if chars[ : 0].join(regex.findall(pattern, chars)) != expected:
1181                    self.fail("Failed: {}".format(pattern))
1182            except Exception as e:
1183                self.fail("Failed: {} raised {}".format(pattern, ascii(e)))
1184
1185        self.assertEqual(bool(regex.match(r"\p{NumericValue=0}", "0")),
1186          True)
1187        self.assertEqual(bool(regex.match(r"\p{NumericValue=1/2}",
1188          "\N{VULGAR FRACTION ONE HALF}")), True)
1189        self.assertEqual(bool(regex.match(r"\p{NumericValue=0.5}",
1190          "\N{VULGAR FRACTION ONE HALF}")), True)
1191
1192    def test_word_class(self):
1193        self.assertEqual(regex.findall(r"\w+",
1194          " \u0939\u093f\u0928\u094d\u0926\u0940,"),
1195          ['\u0939\u093f\u0928\u094d\u0926\u0940'])
1196        self.assertEqual(regex.findall(r"\W+",
1197          " \u0939\u093f\u0928\u094d\u0926\u0940,"), [' ', ','])
1198        self.assertEqual(regex.split(r"(?V1)\b",
1199          " \u0939\u093f\u0928\u094d\u0926\u0940,"), [' ',
1200          '\u0939\u093f\u0928\u094d\u0926\u0940', ','])

Showing the first 1,200 of 4541 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai