codekingpro/portable-devtools
114k
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', ','])
