Completed
Push — master ( eb5e12...1ec1f9 )
by De
01:03
created

RegexTests.test_instance_has_no_meth()   A

Complexity

Conditions 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 1
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_only_concat(self):
523
        """Test ONLY_CONCAT_RE."""
524
        msg = 'can only concatenate list (not "set") to list'
525
        self.re_matches(msg, re.ONLY_CONCAT_RE, NO_GROUP)
526
527
    def test_unsupported_operand(self):
528
        """Test UNSUPPORTED_OP_RE."""
529
        msg = "unsupported operand type(s) for +: 'int' and 'str'"
530
        groups = ('+', 'int', 'str')
531
        results = (groups, dict())
532
        self.re_matches(msg, re.UNSUPPORTED_OP_RE, results)
533
534
    def test_bad_operand_unary(self):
535
        """Test BAD_OPERAND_UNARY_RE."""
536
        msgs = [
537
            ("bad operand type for unary ~: 'set'", ('~', 'set')),
538
            ("bad operand type for abs(): 'set'", ('abs()', 'set')),
539
            ("unsupported operand type for unary neg: 'Foobar'",
540
                ('neg', 'Foobar')),
541
        ]
542
        for msg, groups in msgs:
543
            results = (groups, dict())
544
            self.re_matches(msg, re.BAD_OPERAND_UNARY_RE, results)
545
546
    def test_not_callable(self):
547
        """Test NOT_CALLABLE_RE."""
548
        msg = "'list' object is not callable"
549
        groups = ('list',)
550
        results = (groups, dict())
551
        self.re_matches(msg, re.NOT_CALLABLE_RE, results)
552
553
    def test_descriptor_requires(self):
554
        """Test DESCRIPT_REQUIRES_TYPE_RE."""
555
        msg = "descriptor 'add' requires a 'set' object but received a 'int'"
556
        groups = ('add', 'set', 'int')
557
        results = (groups, dict())
558
        self.re_matches(msg, re.DESCRIPT_REQUIRES_TYPE_RE, results)
559
560
    def test_argument_not_iterable(self):
561
        """Test ARG_NOT_ITERABLE_RE."""
562
        msgs = [
563
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
564
            "argument of type 'type' is not iterable",
565
            # PyPy/PyPy3
566
            "'type' object is not iterable"
567
        ]
568
        groups = ('type',)
569
        results = (groups, dict())
570
        for msg in msgs:
571
            self.re_matches(msg, re.ARG_NOT_ITERABLE_RE, results)
572
573
    def test_must_be_called_with_instance(self):
574
        """Test MUST_BE_CALLED_WITH_INST_RE."""
575
        msg = "unbound method add() must be called with set " \
576
              "instance as first argument (got int instance instead)"
577
        groups = ('add', 'set', 'int')
578
        results = (groups, dict())
579
        self.re_matches(msg, re.MUST_BE_CALLED_WITH_INST_RE, results)
580
581
    def test_object_has_no(self):
582
        """Test OBJECT_HAS_NO_FUNC_RE."""
583
        msgs = {
584
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
585
            'len': "object of type 'generator' has no len()",
586
            # PyPy/PyPy3
587
            'length': "'generator' has no length",
588
        }
589
        for name, msg in msgs.items():
590
            groups = ('generator', name)
591
            results = (groups, dict())
592
            self.re_matches(msg, re.OBJECT_HAS_NO_FUNC_RE, results)
593
594
    def test_instance_has_no_meth(self):
595
        """Test INSTANCE_HAS_NO_METH_RE."""
596
        # Python 2.6/2.7
597
        msg = "CustomClass instance has no __call__ method"
598
        class_, method = 'CustomClass', '__call__'
599
        groups = (class_, method)
600
        results = (groups, dict())
601
        self.re_matches(msg, re.INSTANCE_HAS_NO_METH_RE, results)
602
603
    def test_nobinding_nonlocal(self):
604
        """Test NO_BINDING_NONLOCAL_RE."""
605
        msg = "no binding for nonlocal 'foo' found"
606
        groups = ('foo',)
607
        results = (groups, dict())
608
        self.re_matches(msg, re.NO_BINDING_NONLOCAL_RE, results)
609
610
    def test_nonlocal_at_module_level(self):
611
        """Test NONLOCAL_AT_MODULE_RE."""
612
        msg = "nonlocal declaration not allowed at module level"
613
        self.re_matches(msg, re.NONLOCAL_AT_MODULE_RE, NO_GROUP)
614
615
    def test_unexpected_eof(self):
616
        """Test UNEXPECTED_EOF_RE."""
617
        msg = "unexpected EOF while parsing"
618
        self.re_matches(msg, re.UNEXPECTED_EOF_RE, NO_GROUP)
619
620
    def test_nosuchfile(self):
621
        """Test NO_SUCH_FILE_RE."""
622
        msg = "No such file or directory"
623
        self.re_matches(msg, re.NO_SUCH_FILE_RE, NO_GROUP)
624
625
    def test_timedata_does_not_match_format(self):
626
        """Test TIME_DATA_DOES_NOT_MATCH_FORMAT_RE."""
627
        msg = "time data '%d %b %y' does not match format '30 Nov 00'"
628
        # 'time data "%d \'%b %y" does not match format \'30 Nov 00\''
629
        groups = ("'%d %b %y'", "'30 Nov 00'")
630
        named_groups = {'format': "'30 Nov 00'", 'timedata': "'%d %b %y'"}
631
        results = (groups, named_groups)
632
        self.re_matches(msg, re.TIME_DATA_DOES_NOT_MATCH_FORMAT_RE, results)
633
634
    def test_invalid_token(self):
635
        """Test INVALID_TOKEN_RE."""
636
        msg = 'invalid token'
637
        self.re_matches(msg, re.INVALID_TOKEN_RE, NO_GROUP)
638
639
    def test_exc_must_derive_from(self):
640
        """Test EXC_MUST_DERIVE_FROM_RE."""
641
        msgs = [
642
            # Python 2.7
643
            "exceptions must be old-style classes or derived from "
644
            "BaseException, not NoneType",
645
            # Python 3.3 / 3.4
646
            "exceptions must derive from BaseException",
647
        ]
648
        for msg in msgs:
649
            self.re_matches(msg, re.EXC_MUST_DERIVE_FROM_RE, NO_GROUP)
650
651
    def test_unorderable_types(self):
652
        """Test UNORDERABLE_TYPES_RE."""
653
        msgs = [
654
            # Python 3.2 to 3.5
655
            "unorderable types: str() > int()",
656
            "unorderable types: FoobarClass() <= int()",
657
            # PyPy
658
            "unorderable types: FoobarClass > FoobarClass",
659
        ]
660
        for msg in msgs:
661
            self.re_matches(msg, re.UNORDERABLE_TYPES_RE, NO_GROUP)
662
663
    def test_op_not_supported_between_instances(self):
664
        """Test OP_NOT_SUPP_BETWEEN_INSTANCES_RE."""
665
        msgs = [
666
            # Python 3.6
667
            "'<' not supported between instances of 'int' and 'NoneType'",
668
            "'>' not supported between instances of 'Foo' and 'Foo'",
669
        ]
670
        for msg in msgs:
671
            self.re_matches(msg, re.OP_NOT_SUPP_BETWEEN_INSTANCES_RE, NO_GROUP)
672
673
    def test_max_recursion_depth(self):
674
        """Test MAX_RECURSION_DEPTH_RE."""
675
        msg = 'maximum recursion depth exceeded'
676
        self.re_matches(msg, re.MAX_RECURSION_DEPTH_RE, NO_GROUP)
677
678
    def test_size_changed_during_iter(self):
679
        """Test SIZE_CHANGED_DURING_ITER_RE."""
680
        msgs = {
681
            "Set": "Set changed size during iteration",
682
            "dictionnary": "dictionnary changed size during iteration",
683
        }
684
        for name, msg in msgs.items():
685
            groups = (name, )
686
            results = (groups, dict())
687
            self.re_matches(msg, re.SIZE_CHANGED_DURING_ITER_RE, results)
688
689
if __name__ == '__main__':
690
    print(sys.version_info)
691
    unittest2.main()
692