Completed
Push — master ( 141494...3d5cd9 )
by De
01:03
created

RegexTests.test_var_name()   A

Complexity

Conditions 3

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6666
cc 3
1
# -*- coding: utf-8
2
"""Unit tests for regexps from didyoumean_re.py."""
3
import unittest2
4
import didyoumean_re as re
5
import sys
6
from didyoumean_internal import get_subclasses
7
8
NO_GROUP = ((), dict())
9
# Various technical flags to check more that meet the eyes in tests
10
# Flag used to check that a text only match the expected regexp and not
11
# the other to ensure we do not have ambiguous/double regexp matching.
12
CHECK_OTHERS_DONT_MATCH = True
13
# Flag to check that the regexp provided does correspond to a regexp
14
# listed in re.ALL_REGEXPS
15
CHECK_RE_LISTED = True
16
# Flag to check that the name used for the regexp in re.ALL_REGEXPS
17
# does match the naming convention
18
CHECK_RE_NAME = True
19
# Flag to check that the regex does match a few conventions such as:
20
# stars with ^, ends with $.
21
CHECK_RE_VALUE = True
22
23
24
class RegexTests(unittest2.TestCase):
25
    """Tests to check that error messages match the regexps."""
26
27
    def re_matches(self, text, regexp, results):
28
        """Check that text matches regexp and gives the right match groups.
29
30
        result is a tuple containing the expected return values for groups()
31
        and groupdict().
32
        """
33
        groups, named_groups = results
34
        self.assertRegexpMatches(text, regexp)   # does pretty printing
35
        match = re.match(regexp, text)
36
        self.assertTrue(match)
37
        self.assertEqual(groups, match.groups())
38
        self.assertEqual(named_groups, match.groupdict())
39
        self.check_more_about_re(text, regexp)
40
41
    def check_more_about_re(self, text, regexp):
42
        """Check various properties about the regexp.
43
44
        Properties checked are configurable via global constants. These
45
        properties are not stricly speaking required but they help to
46
        detect potential issues much more quickly.
47
        """
48
        if CHECK_RE_VALUE:
49
            self.assertTrue(regexp.startswith('^'))
50
            self.assertTrue(regexp.endswith('$'))
51
        found = False
52
        for other_name, other_re in re.ALL_REGEXPS.items():
53
            if other_re == regexp:
54
                found = True
55
                if CHECK_RE_NAME:
56
                    self.assertTrue(other_name.endswith('_RE'))
57
            elif CHECK_OTHERS_DONT_MATCH:
58
                details = "text '%s' matches %s (on top of %s)" % \
59
                        (text, other_name, regexp)
60
                self.assertNotRegexpMatches(text, other_re, details)
61
                no_match = re.match(other_re, text)
62
                self.assertEqual(no_match, None, details)
63
        if CHECK_RE_LISTED:
64
            self.assertTrue(found)
65
66
    def test_var_name(self):
67
        """Test VAR_NAME."""
68
        regex = r"^" + re.VAR_NAME + r"$"
69
        real_names = set(locals().keys()) | set(globals().keys())
70
        names = ['a', 'a1', '_a1', 'aa_bb'] + list(real_names)
71
        for name in names:
72
            self.assertRegexpMatches(name, regex)
73
        for name in ['1a']:
74
            self.assertNotRegexpMatches(name, regex)
75
76
    def test_attr_name(self):
77
        """Test ATTR_NAME."""
78
        regex = r"^" + re.ATTR_NAME + r"$"
79
        real_attrs = set(att
80
                         for o in get_subclasses(object)
81
                         for att in dir(o))
82
        attrs = ['do_stuff', '__magic__'] + list(real_attrs)
83
        for attr in attrs:
84
            self.assertRegexpMatches(attr, regex)
85
        for attr in ['1a']:
86
            self.assertNotRegexpMatches(attr, regex)
87
88
    def test_type_name(self):
89
        """Test TYPE_NAME."""
90
        regex = r"^" + re.TYPE_NAME + r"$"
91
        real_types = set(c.__name__ for c in get_subclasses(object))
92
        types = ['str', 'int', 'method-wrapper'] + list(real_types)
93
        for type_ in types:
94
            self.assertRegexpMatches(type_, regex)
95
96
    def test_module_name(self):
97
        """Test MODULE_NAME."""
98
        regex = r"^" + re.MODULE_NAME + r"$"
99
        real_modules = set(sys.modules.keys())
100
        modules = ['sys', 'unittest.runner'] + list(real_modules)
101
        for mod in modules:
102
            self.assertRegexpMatches(mod, regex)
103
104
    def test_unbound_assignment(self):
105
        """Test VARREFBEFOREASSIGN_RE."""
106
        msgs = [
107
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
108
            "local variable 'some_var' referenced before assignment",
109
            "free variable 'some_var' referenced before assignment " \
110
            "in enclosing scope",
111
        ]
112
        groups = ('some_var',)
113
        named_groups = {'name': 'some_var'}
114
        results = (groups, named_groups)
115
        for msg in msgs:
116
            self.re_matches(msg, re.VARREFBEFOREASSIGN_RE, results)
117
118
    def test_name_not_defined(self):
119
        """Test NAMENOTDEFINED_RE."""
120
        msgs = [
121
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy3
122
            "name 'some_name' is not defined",
123
            # Python 2.6/2.7/3.2/3.3/PyPy/PyPy3
124
            "global name 'some_name' is not defined",
125
        ]
126
        groups = ('some_name',)
127
        named_groups = {'name': 'some_name'}
128
        results = (groups, named_groups)
129
        for msg in msgs:
130
            self.re_matches(msg, re.NAMENOTDEFINED_RE, results)
131
132
    def test_attribute_error(self):
133
        """Test ATTRIBUTEERROR_RE."""
134
        group_msg = {
135
            ('some.class', 'attri'): [
136
                # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
137
                "'some.class' object has no attribute 'attri'",
138
            ],
139
            ('SomeClass', 'attri'): [
140
                # Python 2.6/2.7/PyPy
141
                "SomeClass instance has no attribute 'attri'",
142
                # Python 2.6/2.7
143
                "class SomeClass has no attribute 'attri'",
144
                # Python 3.2/3.3/3.4/3.5
145
                "type object 'SomeClass' has no attribute 'attri'",
146
            ],
147
        }
148
        for groups, msgs in group_msg.items():
149
            _, attr = groups
150
            named_groups = {'attr': attr}
151
            results = (groups, named_groups)
152
            for msg in msgs:
153
                self.re_matches(msg, re.ATTRIBUTEERROR_RE, results)
154
155
    def test_module_attribute_error(self):
156
        """Test MODULEHASNOATTRIBUTE_RE."""
157
        # Python 3.5
158
        msg = "module 'some_module' has no attribute 'attri'"
159
        groups = ('some_module', 'attri')
160
        _, attr = groups
161
        named_groups = {'attr': attr}
162
        results = (groups, named_groups)
163
        self.re_matches(msg, re.MODULEHASNOATTRIBUTE_RE, results)
164
165
    def test_cannot_import(self):
166
        """Test CANNOTIMPORT_RE."""
167
        msgs = [
168
            # Python 2.6/2.7/3.2/3.3
169
            "cannot import name pie",
170
            # Python 3.4/3.5/PyPy/PyPy3
171
            "cannot import name 'pie'",
172
        ]
173
        groups = ('pie',)
174
        results = (groups, dict())
175
        for msg in msgs:
176
            self.re_matches(msg, re.CANNOTIMPORT_RE, results)
177
178
    def test_no_module_named(self):
179
        """Test NOMODULE_RE."""
180
        msgs = [
181
            # Python 2.6/2.7/3.2/PyPy/PyPy3
182
            "No module named fake_module",
183
            # Python 3.3/3.4/3.5
184
            "No module named 'fake_module'",
185
        ]
186
        groups = ('fake_module',)
187
        results = (groups, dict())
188
        for msg in msgs:
189
            self.re_matches(msg, re.NOMODULE_RE, results)
190
191
    def test_index_out_of_range(self):
192
        """Test INDEXOUTOFRANGE_RE."""
193
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
194
        msg = "list index out of range"
195
        self.re_matches(msg, re.INDEXOUTOFRANGE_RE, NO_GROUP)
196
197
    def test_unsubscriptable(self):
198
        """Test UNSUBSCRIPTABLE_RE."""
199
        msgs = [
200
            # Python 2.6
201
            "'function' object is unsubscriptable",
202
            # Python 3.2/3.3/3.4/3.5/PyPy/PyPy3
203
            "'function' object is not subscriptable",
204
        ]
205
        groups = ('function',)
206
        results = (groups, dict())
207
        for msg in msgs:
208
            self.re_matches(msg, re.UNSUBSCRIPTABLE_RE, results)
209
210
    def test_unexpected_kw_arg(self):
211
        """Test UNEXPECTED_KEYWORDARG_RE."""
212
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
213
        msgs = [
214
            ("some_func() got an unexpected keyword argument 'a'",
215
                ('some_func', 'a')),
216
            ("<lambda>() got an unexpected keyword argument 'a'",
217
                ('<lambda>', 'a')),
218
        ]
219
        for msg, groups in msgs:
220
            _, kw_arg = groups
221
            named_groups = {'arg': kw_arg}
222
            results = (groups, named_groups)
223
            self.re_matches(msg, re.UNEXPECTED_KEYWORDARG_RE, results)
224
225
    def test_unexpected_kw_arg2(self):
226
        """Test UNEXPECTED_KEYWORDARG2_RE."""
227
        # Python 2.6/2.7/3.2/3.3/3.4/3.5
228
        msg = "'this_doesnt_exist' is an invalid " \
229
            "keyword argument for this function"
230
        groups = ('this_doesnt_exist', )
231
        kw_arg, = groups
232
        named_groups = {'arg': kw_arg}
233
        results = (groups, named_groups)
234
        self.re_matches(msg, re.UNEXPECTED_KEYWORDARG2_RE, results)
235
236
    def test_unexpected_kw_arg3(self):
237
        """Test UNEXPECTED_KEYWORDARG3_RE."""
238
        # PyPy/PyPy3
239
        msg = "invalid keyword arguments to print()"
240
        groups = ('print', )
241
        results = (groups, dict())
242
        self.re_matches(msg, re.UNEXPECTED_KEYWORDARG3_RE, results)
243
244
    def test_zero_length_field(self):
245
        """Test ZERO_LEN_FIELD_RE."""
246
        # Python 2.6
247
        msg = "zero length field name in format"
248
        self.re_matches(msg, re.ZERO_LEN_FIELD_RE, NO_GROUP)
249
250
    def test_math_domain_error(self):
251
        """Test MATH_DOMAIN_ERROR_RE."""
252
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
253
        msg = "math domain error"
254
        self.re_matches(msg, re.MATH_DOMAIN_ERROR_RE, NO_GROUP)
255
256
    def test_too_many_values(self):
257
        """Test TOO_MANY_VALUES_UNPACK_RE."""
258
        msgs = [
259
            # Python 2.6/2.7
260
            "too many values to unpack",
261
            # Python 3.2/3.3/3.4/3.5/PyPy3
262
            "too many values to unpack (expected 3)",
263
        ]
264
        for msg in msgs:
265
            self.re_matches(msg, re.TOO_MANY_VALUES_UNPACK_RE, NO_GROUP)
266
267
    def test_unhashable_type(self):
268
        """Test UNHASHABLE_RE."""
269
        msgs = [
270
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
271
            "unhashable type: 'list'",
272
            # PyPy/PyPy3
273
            "'list' objects are unhashable",
274
        ]
275
        groups = ('list',)
276
        results = (groups, dict())
277
        for msg in msgs:
278
            self.re_matches(msg, re.UNHASHABLE_RE, results)
279
280
    def test_cannot_be_interpreted_as_integer(self):
281
        """Test CANNOT_BE_INTERPRETED_INT_RE."""
282
        msgs = {
283
            "'str' object cannot be interpreted as an integer": 'str',
284
            "'list' object cannot be interpreted as an integer": 'list',
285
        }
286
        for msg, typ in msgs.items():
287
            results = ((typ,), dict())
288
            self.re_matches(msg, re.CANNOT_BE_INTERPRETED_INT_RE, results)
289
290
    def test_int_expected_got(self):
291
        """Test INTEGER_EXPECTED_GOT_RE."""
292
        msgs = {
293
            "expected integer, got str object": 'str',
294
            "range() integer end argument expected, got list.": 'list',
295
            "range() integer start argument expected, got list.": 'list',
296
        }
297
        for msg, typ in msgs.items():
298
            results = ((typ,), dict())
299
            self.re_matches(msg, re.INTEGER_EXPECTED_GOT_RE, results)
300
301
    def test_indices_must_be_int(self):
302
        """Test INDICES_MUST_BE_INT_RE."""
303
        msgs = {
304
            # Python 2.6, 2.7, 3.2, 3.3, 3.4
305
            "list indices must be integers, not str": "str",
306
            "list indices must be integers or slices, not str": "str",
307
            # Python 3.5
308
            "tuple indices must be integers or slices, not str": "str",
309
            # PyPy
310
            "list index must be an integer, not str": "str",
311
        }
312
        for msg, typ in msgs.items():
313
            results = ((typ,), dict())
314
            self.re_matches(msg, re.INDICES_MUST_BE_INT_RE, results)
315
316
    def test_outside_function(self):
317
        """Test OUTSIDE_FUNCTION_RE."""
318
        msgs = [
319
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
320
            "'return' outside function",
321
            # PyPy/PyPy3
322
            "return outside function",
323
        ]
324
        groups = ('return',)
325
        results = (groups, dict())
326
        for msg in msgs:
327
            self.re_matches(msg, re.OUTSIDE_FUNCTION_RE, results)
328
329
    def test_nb_positional_argument(self):
330
        """Test NB_ARG_RE."""
331
        msgs = [
332
            # Python 2.6/2.7/PyPy/PyPy3
333
            ("some_func() takes exactly 1 argument (2 given)",
334
                '1', '2'),
335
            ("some_func() takes exactly 3 arguments (1 given)",
336
                '3', '1'),
337
            ("some_func() takes no arguments (1 given)",
338
                'no', '1'),
339
            ("some_func() takes at least 2 non-keyword arguments (0 given)",
340
                '2', '0'),
341
            # Python 3.2
342
            ("some_func() takes exactly 1 positional argument (2 given)",
343
                '1', '2'),
344
            # Python 3.3/3.4/3.5
345
            ("some_func() takes 1 positional argument but 2 were given",
346
                '1', '2'),
347
            ("some_func() takes 0 positional arguments but 1 was given",
348
                '0', '1'),
349
            # PyPy adds suggestions sometimes:
350
            ("some_func() takes no arguments (1 given)"
351
             ". Did you forget 'self' in the function definition?",
352
                'no', '1'),
353
        ]
354
        for msg, exp, nb in msgs:
355
            groups = ('some_func', exp, nb)
356
            results = (groups, dict())
357
            self.re_matches(msg, re.NB_ARG_RE, results)
358
359
    def test_missing_positional_arg(self):
360
        """Test MISSING_POS_ARG_RE."""
361
        msgs = [
362
            # Python 3.3/3.4/3.5
363
            "some_func() missing 2 required positional arguments: "
364
            "'much' and 'args'",
365
            "some_func() missing 1 required positional argument: "
366
            "'much'",
367
        ]
368
        groups = ('some_func',)
369
        results = (groups, dict())
370
        for msg in msgs:
371
            self.re_matches(msg, re.MISSING_POS_ARG_RE, results)
372
373
    def test_need_more_values_to_unpack(self):
374
        """Test NEED_MORE_VALUES_RE."""
375
        msgs = [
376
            # Python 2.6/2.7/3.2/3.3/3.4/3.5(?)/PyPy3
377
            "need more than 2 values to unpack",
378
            # Python 3.5
379
            "not enough values to unpack (expected 3, got 2)",
380
        ]
381
        for msg in msgs:
382
            self.re_matches(msg, re.NEED_MORE_VALUES_RE, NO_GROUP)
383
384
    def test_missing_parentheses(self):
385
        """Test MISSING_PARENT_RE."""
386
        # Python 3.4/3.5
387
        msg = "Missing parentheses in call to 'exec'"
388
        groups = ('exec',)
389
        results = (groups, dict())
390
        self.re_matches(msg, re.MISSING_PARENT_RE, results)
391
392
    def test_invalid_literal(self):
393
        """Test INVALID_LITERAL_RE."""
394
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
395
        msg = "invalid literal for int() with base 10: 'toto'"
396
        groups = ('int', 'toto')
397
        results = (groups, dict())
398
        self.re_matches(msg, re.INVALID_LITERAL_RE, results)
399
400
    def test_invalid_syntax(self):
401
        """Test INVALID_SYNTAX_RE."""
402
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy3
403
        msg = "invalid syntax"
404
        self.re_matches(msg, re.INVALID_SYNTAX_RE, NO_GROUP)
405
406
    def test_invalid_comp(self):
407
        """Test INVALID_COMP_RE."""
408
        # PyPy3
409
        msg = "invalid comparison"
410
        self.re_matches(msg, re.INVALID_COMP_RE, NO_GROUP)
411
412
    def test_expected_length(self):
413
        """Test EXPECTED_LENGTH_RE."""
414
        # PyPy
415
        msg = "expected length 3, got 2"
416
        groups = ('3', '2')
417
        results = (groups, dict())
418
        self.re_matches(msg, re.EXPECTED_LENGTH_RE, results)
419
420
    def test_future_first(self):
421
        """Test FUTURE_FIRST_RE."""
422
        msgs = [
423
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
424
            "from __future__ imports must occur at the beginning of the file",
425
            # PyPy/PyPy3
426
            "__future__ statements must appear at beginning of file",
427
        ]
428
        for msg in msgs:
429
            self.re_matches(msg, re.FUTURE_FIRST_RE, NO_GROUP)
430
431
    def test_future_feature_not_def(self):
432
        """Test FUTURE_FEATURE_NOT_DEF_RE."""
433
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
434
        msg = "future feature divisio is not defined"
435
        groups = ('divisio',)
436
        results = (groups, dict())
437
        self.re_matches(msg, re.FUTURE_FEATURE_NOT_DEF_RE, results)
438
439
    def test_result_has_too_many_items(self):
440
        """Test RESULT_TOO_MANY_ITEMS_RE."""
441
        # Python 2.6
442
        msg = "range() result has too many items"
443
        groups = ('range',)
444
        results = (groups, dict())
445
        self.re_matches(msg, re.RESULT_TOO_MANY_ITEMS_RE, results)
446
447
    def test_unqualified_exec(self):
448
        """Test UNQUALIFIED_EXEC_RE."""
449
        msgs = [
450
            # Python 2.6
451
            "unqualified exec is not allowed in function 'func_name' "
452
            "it is a nested function",
453
            # Python 2.7
454
            "unqualified exec is not allowed in function 'func_name' "
455
            "because it is a nested function",
456
            # Python 2.6
457
            "unqualified exec is not allowed in function 'func_name' "
458
            "it contains a nested function with free variables",
459
            # Python 2.7
460
            "unqualified exec is not allowed in function 'func_name' "
461
            "because it contains a nested function with free variables",
462
        ]
463
        for msg in msgs:
464
            self.re_matches(msg, re.UNQUALIFIED_EXEC_RE, NO_GROUP)
465
466
    def test_import_star(self):
467
        """Test IMPORTSTAR_RE."""
468
        msgs = [
469
            # Python 2.6
470
            "import * is not allowed in function 'func_name' because it "
471
            "is contains a nested function with free variables",
472
            # Python 2.7
473
            "import * is not allowed in function 'func_name' because it "
474
            "contains a nested function with free variables",
475
            # Python 2.6
476
            "import * is not allowed in function 'func_name' because it "
477
            "is is a nested function",
478
            # Python 2.7
479
            "import * is not allowed in function 'func_name' because it "
480
            "is a nested function",
481
            # Python 3
482
            "import * only allowed at module level"
483
        ]
484
        for msg in msgs:
485
            self.re_matches(msg, re.IMPORTSTAR_RE, NO_GROUP)
486
487
    def test_does_not_support(self):
488
        """Test OBJ_DOES_NOT_SUPPORT_RE."""
489
        msgs = [
490
            ("'range' object does not support item assignment",
491
                ("range", "item assignment")),
492
            ("'str' object doesn't support item deletion",
493
                ("str", "item deletion")),
494
            ("'set' object does not support indexing",
495
                ("set", "indexing")),
496
        ]
497
        for msg, groups in msgs:
498
            results = (groups, dict())
499
            self.re_matches(msg, re.OBJ_DOES_NOT_SUPPORT_RE, results)
500
501
    def test_cant_convert(self):
502
        """Test CANT_CONVERT_RE."""
503
        msg = "Can't convert 'int' object to str implicitly"
504
        groups = ('int', 'str')
505
        results = (groups, dict())
506
        self.re_matches(msg, re.CANT_CONVERT_RE, results)
507
508
    def test_must_be_type1_not_type2(self):
509
        """Test MUST_BE_TYPE1_NOT_TYPE2_RE."""
510
        msg = "must be str, not int"
511
        groups = ('str', 'int')
512
        results = (groups, dict())
513
        self.re_matches(msg, re.MUST_BE_TYPE1_NOT_TYPE2_RE, results)
514
515
    def test_cannot_concat(self):
516
        """Test CANNOT_CONCAT_RE."""
517
        msg = "cannot concatenate 'str' and 'int' objects"
518
        groups = ('str', 'int')
519
        results = (groups, dict())
520
        self.re_matches(msg, re.CANNOT_CONCAT_RE, results)
521
522
    def test_unsupported_operand(self):
523
        """Test UNSUPPORTED_OP_RE."""
524
        msg = "unsupported operand type(s) for +: 'int' and 'str'"
525
        groups = ('+', 'int', 'str')
526
        results = (groups, dict())
527
        self.re_matches(msg, re.UNSUPPORTED_OP_RE, results)
528
529
    def test_bad_operand_unary(self):
530
        """Test BAD_OPERAND_UNARY_RE."""
531
        msgs = [
532
            ("bad operand type for unary ~: 'set'", ('~', 'set')),
533
            ("bad operand type for abs(): 'set'", ('abs()', 'set')),
534
            ("unsupported operand type for unary neg: 'Foobar'",
535
                ('neg', 'Foobar')),
536
        ]
537
        for msg, groups in msgs:
538
            results = (groups, dict())
539
            self.re_matches(msg, re.BAD_OPERAND_UNARY_RE, results)
540
541
    def test_not_callable(self):
542
        """Test NOT_CALLABLE_RE."""
543
        msg = "'list' object is not callable"
544
        groups = ('list',)
545
        results = (groups, dict())
546
        self.re_matches(msg, re.NOT_CALLABLE_RE, results)
547
548
    def test_descriptor_requires(self):
549
        """Test DESCRIPT_REQUIRES_TYPE_RE."""
550
        msg = "descriptor 'add' requires a 'set' object but received a 'int'"
551
        groups = ('add', 'set', 'int')
552
        results = (groups, dict())
553
        self.re_matches(msg, re.DESCRIPT_REQUIRES_TYPE_RE, results)
554
555
    def test_argument_not_iterable(self):
556
        """Test ARG_NOT_ITERABLE_RE."""
557
        msgs = [
558
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
559
            "argument of type 'type' is not iterable",
560
            # PyPy/PyPy3
561
            "'type' object is not iterable"
562
        ]
563
        groups = ('type',)
564
        results = (groups, dict())
565
        for msg in msgs:
566
            self.re_matches(msg, re.ARG_NOT_ITERABLE_RE, results)
567
568
    def test_must_be_called_with_instance(self):
569
        """Test MUST_BE_CALLED_WITH_INST_RE."""
570
        msg = "unbound method add() must be called with set " \
571
              "instance as first argument (got int instance instead)"
572
        groups = ('add', 'set', 'int')
573
        results = (groups, dict())
574
        self.re_matches(msg, re.MUST_BE_CALLED_WITH_INST_RE, results)
575
576
    def test_object_has_no(self):
577
        """Test OBJECT_HAS_NO_FUNC_RE."""
578
        msgs = {
579
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
580
            'len': "object of type 'generator' has no len()",
581
            # PyPy/PyPy3
582
            'length': "'generator' has no length",
583
        }
584
        for name, msg in msgs.items():
585
            groups = ('generator', name)
586
            results = (groups, dict())
587
            self.re_matches(msg, re.OBJECT_HAS_NO_FUNC_RE, results)
588
589
    def test_nobinding_nonlocal(self):
590
        """Test NO_BINDING_NONLOCAL_RE."""
591
        msg = "no binding for nonlocal 'foo' found"
592
        groups = ('foo',)
593
        results = (groups, dict())
594
        self.re_matches(msg, re.NO_BINDING_NONLOCAL_RE, results)
595
596
    def test_nonlocal_at_module_level(self):
597
        """Test NONLOCAL_AT_MODULE_RE."""
598
        msg = "nonlocal declaration not allowed at module level"
599
        self.re_matches(msg, re.NONLOCAL_AT_MODULE_RE, NO_GROUP)
600
601
    def test_unexpected_eof(self):
602
        """Test UNEXPECTED_EOF_RE."""
603
        msg = "unexpected EOF while parsing"
604
        self.re_matches(msg, re.UNEXPECTED_EOF_RE, NO_GROUP)
605
606
    def test_nosuchfile(self):
607
        """Test NO_SUCH_FILE_RE."""
608
        msg = "No such file or directory"
609
        self.re_matches(msg, re.NO_SUCH_FILE_RE, NO_GROUP)
610
611
    def test_timedata_does_not_match_format(self):
612
        """Test TIME_DATA_DOES_NOT_MATCH_FORMAT_RE."""
613
        msg = "time data '%d %b %y' does not match format '30 Nov 00'"
614
        # 'time data "%d \'%b %y" does not match format \'30 Nov 00\''
615
        groups = ("'%d %b %y'", "'30 Nov 00'")
616
        named_groups = {'format': "'30 Nov 00'", 'timedata': "'%d %b %y'"}
617
        results = (groups, named_groups)
618
        self.re_matches(msg, re.TIME_DATA_DOES_NOT_MATCH_FORMAT_RE, results)
619
620
    def test_invalid_token(self):
621
        """Test INVALID_TOKEN_RE."""
622
        msg = 'invalid token'
623
        self.re_matches(msg, re.INVALID_TOKEN_RE, NO_GROUP)
624
625
    def test_exc_must_derive_from(self):
626
        """Test EXC_MUST_DERIVE_FROM_RE."""
627
        msgs = [
628
            # Python 2.7
629
            "exceptions must be old-style classes or derived from "
630
            "BaseException, not NoneType",
631
            # Python 3.3 / 3.4
632
            "exceptions must derive from BaseException",
633
        ]
634
        for msg in msgs:
635
            self.re_matches(msg, re.EXC_MUST_DERIVE_FROM_RE, NO_GROUP)
636
637
    def test_unorderable_types(self):
638
        """Test UNORDERABLE_TYPES_RE."""
639
        msgs = [
640
            # Python 3.2 to 3.5
641
            "unorderable types: str() > int()",
642
            "unorderable types: FoobarClass() <= int()",
643
            # PyPy
644
            "unorderable types: FoobarClass > FoobarClass",
645
        ]
646
        for msg in msgs:
647
            self.re_matches(msg, re.UNORDERABLE_TYPES_RE, NO_GROUP)
648
649
    def test_op_not_supported_between_instances(self):
650
        """Test OP_NOT_SUPP_BETWEEN_INSTANCES_RE."""
651
        msgs = [
652
            # Python 3.6
653
            "'<' not supported between instances of 'int' and 'NoneType'",
654
            "'>' not supported between instances of 'Foo' and 'Foo'",
655
        ]
656
        for msg in msgs:
657
            self.re_matches(msg, re.OP_NOT_SUPP_BETWEEN_INSTANCES_RE, NO_GROUP)
658
659
    def test_max_recursion_depth(self):
660
        """Test MAX_RECURSION_DEPTH_RE."""
661
        msg = 'maximum recursion depth exceeded'
662
        self.re_matches(msg, re.MAX_RECURSION_DEPTH_RE, NO_GROUP)
663
664
    def test_size_changed_during_iter(self):
665
        """Test SIZE_CHANGED_DURING_ITER_RE."""
666
        msgs = {
667
            "Set": "Set changed size during iteration",
668
            "dictionnary": "dictionnary changed size during iteration",
669
        }
670
        for name, msg in msgs.items():
671
            groups = (name, )
672
            results = (groups, dict())
673
            self.re_matches(msg, re.SIZE_CHANGED_DURING_ITER_RE, results)
674
675
if __name__ == '__main__':
676
    print(sys.version_info)
677
    unittest2.main()
678