Completed
Push — master ( 9a0071...f44f4c )
by De
01:14
created

RegexTests.test_unexpected_kw_arg()   A

Complexity

Conditions 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 2
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_func_takes_no_kwarg(self):
245
        """Test FUNC_TAKES_NO_KEYWORDARG_RE."""
246
        msgs = [
247
            # Cython : most versions
248
            "get() takes no keyword arguments",
249
            # Cython nightly (as of 21 January 2017) - Python 3.7
250
            "get does not take keyword arguments",
251
        ]
252
        groups = ('get', )
253
        results = (groups, dict())
254
        for msg in msgs:
255
            self.re_matches(msg, re.FUNC_TAKES_NO_KEYWORDARG_RE, results)
256
257
    def test_zero_length_field(self):
258
        """Test ZERO_LEN_FIELD_RE."""
259
        # Python 2.6
260
        msg = "zero length field name in format"
261
        self.re_matches(msg, re.ZERO_LEN_FIELD_RE, NO_GROUP)
262
263
    def test_math_domain_error(self):
264
        """Test MATH_DOMAIN_ERROR_RE."""
265
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
266
        msg = "math domain error"
267
        self.re_matches(msg, re.MATH_DOMAIN_ERROR_RE, NO_GROUP)
268
269
    def test_too_many_values(self):
270
        """Test TOO_MANY_VALUES_UNPACK_RE."""
271
        msgs = [
272
            # Python 2.6/2.7
273
            "too many values to unpack",
274
            # Python 3.2/3.3/3.4/3.5/PyPy3
275
            "too many values to unpack (expected 3)",
276
        ]
277
        for msg in msgs:
278
            self.re_matches(msg, re.TOO_MANY_VALUES_UNPACK_RE, NO_GROUP)
279
280
    def test_unhashable_type(self):
281
        """Test UNHASHABLE_RE."""
282
        msgs = [
283
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
284
            "unhashable type: 'list'",
285
            # PyPy/PyPy3
286
            "'list' objects are unhashable",
287
        ]
288
        groups = ('list',)
289
        results = (groups, dict())
290
        for msg in msgs:
291
            self.re_matches(msg, re.UNHASHABLE_RE, results)
292
293
    def test_cannot_be_interpreted_as_integer(self):
294
        """Test CANNOT_BE_INTERPRETED_INT_RE."""
295
        msgs = {
296
            "'str' object cannot be interpreted as an integer": 'str',
297
            "'list' object cannot be interpreted as an integer": 'list',
298
        }
299
        for msg, typ in msgs.items():
300
            results = ((typ,), dict())
301
            self.re_matches(msg, re.CANNOT_BE_INTERPRETED_INT_RE, results)
302
303
    def test_int_expected_got(self):
304
        """Test INTEGER_EXPECTED_GOT_RE."""
305
        msgs = {
306
            "expected integer, got str object": 'str',
307
            "range() integer end argument expected, got list.": 'list',
308
            "range() integer start argument expected, got list.": 'list',
309
        }
310
        for msg, typ in msgs.items():
311
            results = ((typ,), dict())
312
            self.re_matches(msg, re.INTEGER_EXPECTED_GOT_RE, results)
313
314
    def test_indices_must_be_int(self):
315
        """Test INDICES_MUST_BE_INT_RE."""
316
        msgs = {
317
            # Python 2.6, 2.7, 3.2, 3.3, 3.4
318
            "list indices must be integers, not str": "str",
319
            "list indices must be integers or slices, not str": "str",
320
            # Python 3.5
321
            "tuple indices must be integers or slices, not str": "str",
322
            # PyPy
323
            "list index must be an integer, not str": "str",
324
        }
325
        for msg, typ in msgs.items():
326
            results = ((typ,), dict())
327
            self.re_matches(msg, re.INDICES_MUST_BE_INT_RE, results)
328
329
    def test_outside_function(self):
330
        """Test OUTSIDE_FUNCTION_RE."""
331
        msgs = [
332
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
333
            "'return' outside function",
334
            # PyPy/PyPy3
335
            "return outside function",
336
        ]
337
        groups = ('return',)
338
        results = (groups, dict())
339
        for msg in msgs:
340
            self.re_matches(msg, re.OUTSIDE_FUNCTION_RE, results)
341
342
    def test_nb_positional_argument(self):
343
        """Test NB_ARG_RE."""
344
        msgs = [
345
            # Python 2.6/2.7/PyPy/PyPy3
346
            ("some_func() takes exactly 1 argument (2 given)",
347
                '1', '2'),
348
            ("some_func() takes exactly 3 arguments (1 given)",
349
                '3', '1'),
350
            ("some_func() takes no arguments (1 given)",
351
                'no', '1'),
352
            ("some_func() takes at least 2 non-keyword arguments (0 given)",
353
                '2', '0'),
354
            # Python 3.2
355
            ("some_func() takes exactly 1 positional argument (2 given)",
356
                '1', '2'),
357
            # Python 3.3/3.4/3.5
358
            ("some_func() takes 1 positional argument but 2 were given",
359
                '1', '2'),
360
            ("some_func() takes 0 positional arguments but 1 was given",
361
                '0', '1'),
362
            # PyPy adds suggestions sometimes:
363
            ("some_func() takes no arguments (1 given)"
364
             ". Did you forget 'self' in the function definition?",
365
                'no', '1'),
366
        ]
367
        for msg, exp, nb in msgs:
368
            groups = ('some_func', exp, nb)
369
            results = (groups, dict())
370
            self.re_matches(msg, re.NB_ARG_RE, results)
371
372
    def test_missing_positional_arg(self):
373
        """Test MISSING_POS_ARG_RE."""
374
        msgs = [
375
            # Python 3.3/3.4/3.5
376
            "some_func() missing 2 required positional arguments: "
377
            "'much' and 'args'",
378
            "some_func() missing 1 required positional argument: "
379
            "'much'",
380
        ]
381
        groups = ('some_func',)
382
        results = (groups, dict())
383
        for msg in msgs:
384
            self.re_matches(msg, re.MISSING_POS_ARG_RE, results)
385
386
    def test_need_more_values_to_unpack(self):
387
        """Test NEED_MORE_VALUES_RE."""
388
        msgs = [
389
            # Python 2.6/2.7/3.2/3.3/3.4/3.5(?)/PyPy3
390
            "need more than 2 values to unpack",
391
            # Python 3.5
392
            "not enough values to unpack (expected 3, got 2)",
393
        ]
394
        for msg in msgs:
395
            self.re_matches(msg, re.NEED_MORE_VALUES_RE, NO_GROUP)
396
397
    def test_missing_parentheses(self):
398
        """Test MISSING_PARENT_RE."""
399
        # Python 3.4/3.5
400
        msg = "Missing parentheses in call to 'exec'"
401
        groups = ('exec',)
402
        results = (groups, dict())
403
        self.re_matches(msg, re.MISSING_PARENT_RE, results)
404
405
    def test_invalid_literal(self):
406
        """Test INVALID_LITERAL_RE."""
407
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
408
        msg = "invalid literal for int() with base 10: 'toto'"
409
        groups = ('int', 'toto')
410
        results = (groups, dict())
411
        self.re_matches(msg, re.INVALID_LITERAL_RE, results)
412
413
    def test_invalid_syntax(self):
414
        """Test INVALID_SYNTAX_RE."""
415
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy3
416
        msg = "invalid syntax"
417
        self.re_matches(msg, re.INVALID_SYNTAX_RE, NO_GROUP)
418
419
    def test_invalid_comp(self):
420
        """Test INVALID_COMP_RE."""
421
        # PyPy3
422
        msg = "invalid comparison"
423
        self.re_matches(msg, re.INVALID_COMP_RE, NO_GROUP)
424
425
    def test_expected_length(self):
426
        """Test EXPECTED_LENGTH_RE."""
427
        # PyPy
428
        msg = "expected length 3, got 2"
429
        groups = ('3', '2')
430
        results = (groups, dict())
431
        self.re_matches(msg, re.EXPECTED_LENGTH_RE, results)
432
433
    def test_future_first(self):
434
        """Test FUTURE_FIRST_RE."""
435
        msgs = [
436
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
437
            "from __future__ imports must occur at the beginning of the file",
438
            # PyPy/PyPy3
439
            "__future__ statements must appear at beginning of file",
440
        ]
441
        for msg in msgs:
442
            self.re_matches(msg, re.FUTURE_FIRST_RE, NO_GROUP)
443
444
    def test_future_feature_not_def(self):
445
        """Test FUTURE_FEATURE_NOT_DEF_RE."""
446
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
447
        msg = "future feature divisio is not defined"
448
        groups = ('divisio',)
449
        results = (groups, dict())
450
        self.re_matches(msg, re.FUTURE_FEATURE_NOT_DEF_RE, results)
451
452
    def test_result_has_too_many_items(self):
453
        """Test RESULT_TOO_MANY_ITEMS_RE."""
454
        # Python 2.6
455
        msg = "range() result has too many items"
456
        groups = ('range',)
457
        results = (groups, dict())
458
        self.re_matches(msg, re.RESULT_TOO_MANY_ITEMS_RE, results)
459
460
    def test_unqualified_exec(self):
461
        """Test UNQUALIFIED_EXEC_RE."""
462
        msgs = [
463
            # Python 2.6
464
            "unqualified exec is not allowed in function 'func_name' "
465
            "it is a nested function",
466
            # Python 2.7
467
            "unqualified exec is not allowed in function 'func_name' "
468
            "because it is a nested function",
469
            # Python 2.6
470
            "unqualified exec is not allowed in function 'func_name' "
471
            "it contains a nested function with free variables",
472
            # Python 2.7
473
            "unqualified exec is not allowed in function 'func_name' "
474
            "because it contains a nested function with free variables",
475
        ]
476
        for msg in msgs:
477
            self.re_matches(msg, re.UNQUALIFIED_EXEC_RE, NO_GROUP)
478
479
    def test_import_star(self):
480
        """Test IMPORTSTAR_RE."""
481
        msgs = [
482
            # Python 2.6
483
            "import * is not allowed in function 'func_name' because it "
484
            "is contains a nested function with free variables",
485
            # Python 2.7
486
            "import * is not allowed in function 'func_name' because it "
487
            "contains a nested function with free variables",
488
            # Python 2.6
489
            "import * is not allowed in function 'func_name' because it "
490
            "is is a nested function",
491
            # Python 2.7
492
            "import * is not allowed in function 'func_name' because it "
493
            "is a nested function",
494
            # Python 3
495
            "import * only allowed at module level"
496
        ]
497
        for msg in msgs:
498
            self.re_matches(msg, re.IMPORTSTAR_RE, NO_GROUP)
499
500
    def test_does_not_support(self):
501
        """Test OBJ_DOES_NOT_SUPPORT_RE."""
502
        msgs = [
503
            ("'range' object does not support item assignment",
504
                ("range", "item assignment")),
505
            ("'str' object doesn't support item deletion",
506
                ("str", "item deletion")),
507
            ("'set' object does not support indexing",
508
                ("set", "indexing")),
509
        ]
510
        for msg, groups in msgs:
511
            results = (groups, dict())
512
            self.re_matches(msg, re.OBJ_DOES_NOT_SUPPORT_RE, results)
513
514
    def test_cant_convert(self):
515
        """Test CANT_CONVERT_RE."""
516
        msg = "Can't convert 'int' object to str implicitly"
517
        groups = ('int', 'str')
518
        results = (groups, dict())
519
        self.re_matches(msg, re.CANT_CONVERT_RE, results)
520
521
    def test_must_be_type1_not_type2(self):
522
        """Test MUST_BE_TYPE1_NOT_TYPE2_RE."""
523
        msg = "must be str, not int"
524
        groups = ('str', 'int')
525
        results = (groups, dict())
526
        self.re_matches(msg, re.MUST_BE_TYPE1_NOT_TYPE2_RE, results)
527
528
    def test_cannot_concat(self):
529
        """Test CANNOT_CONCAT_RE."""
530
        msg = "cannot concatenate 'str' and 'int' objects"
531
        groups = ('str', 'int')
532
        results = (groups, dict())
533
        self.re_matches(msg, re.CANNOT_CONCAT_RE, results)
534
535
    def test_only_concat(self):
536
        """Test ONLY_CONCAT_RE."""
537
        msg = 'can only concatenate list (not "set") to list'
538
        self.re_matches(msg, re.ONLY_CONCAT_RE, NO_GROUP)
539
540
    def test_unsupported_operand(self):
541
        """Test UNSUPPORTED_OP_RE."""
542
        msg = "unsupported operand type(s) for +: 'int' and 'str'"
543
        groups = ('+', 'int', 'str')
544
        results = (groups, dict())
545
        self.re_matches(msg, re.UNSUPPORTED_OP_RE, results)
546
547
    def test_bad_operand_unary(self):
548
        """Test BAD_OPERAND_UNARY_RE."""
549
        msgs = [
550
            ("bad operand type for unary ~: 'set'", ('~', 'set')),
551
            ("bad operand type for abs(): 'set'", ('abs()', 'set')),
552
            ("unsupported operand type for unary neg: 'Foobar'",
553
                ('neg', 'Foobar')),
554
        ]
555
        for msg, groups in msgs:
556
            results = (groups, dict())
557
            self.re_matches(msg, re.BAD_OPERAND_UNARY_RE, results)
558
559
    def test_not_callable(self):
560
        """Test NOT_CALLABLE_RE."""
561
        msg = "'list' object is not callable"
562
        groups = ('list',)
563
        results = (groups, dict())
564
        self.re_matches(msg, re.NOT_CALLABLE_RE, results)
565
566
    def test_descriptor_requires(self):
567
        """Test DESCRIPT_REQUIRES_TYPE_RE."""
568
        msg = "descriptor 'add' requires a 'set' object but received a 'int'"
569
        groups = ('add', 'set', 'int')
570
        results = (groups, dict())
571
        self.re_matches(msg, re.DESCRIPT_REQUIRES_TYPE_RE, results)
572
573
    def test_argument_not_iterable(self):
574
        """Test ARG_NOT_ITERABLE_RE."""
575
        msgs = [
576
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
577
            "argument of type 'type' is not iterable",
578
            # PyPy/PyPy3
579
            "'type' object is not iterable"
580
        ]
581
        groups = ('type',)
582
        results = (groups, dict())
583
        for msg in msgs:
584
            self.re_matches(msg, re.ARG_NOT_ITERABLE_RE, results)
585
586
    def test_must_be_called_with_instance(self):
587
        """Test MUST_BE_CALLED_WITH_INST_RE."""
588
        msg = "unbound method add() must be called with set " \
589
              "instance as first argument (got int instance instead)"
590
        groups = ('add', 'set', 'int')
591
        results = (groups, dict())
592
        self.re_matches(msg, re.MUST_BE_CALLED_WITH_INST_RE, results)
593
594
    def test_object_has_no(self):
595
        """Test OBJECT_HAS_NO_FUNC_RE."""
596
        msgs = {
597
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
598
            'len': "object of type 'generator' has no len()",
599
            # PyPy/PyPy3
600
            'length': "'generator' has no length",
601
        }
602
        for name, msg in msgs.items():
603
            groups = ('generator', name)
604
            results = (groups, dict())
605
            self.re_matches(msg, re.OBJECT_HAS_NO_FUNC_RE, results)
606
607
    def test_instance_has_no_meth(self):
608
        """Test INSTANCE_HAS_NO_METH_RE."""
609
        # Python 2.6/2.7
610
        msg = "CustomClass instance has no __call__ method"
611
        class_, method = 'CustomClass', '__call__'
612
        groups = (class_, method)
613
        results = (groups, dict())
614
        self.re_matches(msg, re.INSTANCE_HAS_NO_METH_RE, results)
615
616
    def test_nobinding_nonlocal(self):
617
        """Test NO_BINDING_NONLOCAL_RE."""
618
        msg = "no binding for nonlocal 'foo' found"
619
        groups = ('foo',)
620
        results = (groups, dict())
621
        self.re_matches(msg, re.NO_BINDING_NONLOCAL_RE, results)
622
623
    def test_nonlocal_at_module_level(self):
624
        """Test NONLOCAL_AT_MODULE_RE."""
625
        msg = "nonlocal declaration not allowed at module level"
626
        self.re_matches(msg, re.NONLOCAL_AT_MODULE_RE, NO_GROUP)
627
628
    def test_unexpected_eof(self):
629
        """Test UNEXPECTED_EOF_RE."""
630
        msg = "unexpected EOF while parsing"
631
        self.re_matches(msg, re.UNEXPECTED_EOF_RE, NO_GROUP)
632
633
    def test_nosuchfile(self):
634
        """Test NO_SUCH_FILE_RE."""
635
        msg = "No such file or directory"
636
        self.re_matches(msg, re.NO_SUCH_FILE_RE, NO_GROUP)
637
638
    def test_timedata_does_not_match_format(self):
639
        """Test TIME_DATA_DOES_NOT_MATCH_FORMAT_RE."""
640
        msg = "time data '%d %b %y' does not match format '30 Nov 00'"
641
        # 'time data "%d \'%b %y" does not match format \'30 Nov 00\''
642
        groups = ("'%d %b %y'", "'30 Nov 00'")
643
        named_groups = {'format': "'30 Nov 00'", 'timedata': "'%d %b %y'"}
644
        results = (groups, named_groups)
645
        self.re_matches(msg, re.TIME_DATA_DOES_NOT_MATCH_FORMAT_RE, results)
646
647
    def test_invalid_token(self):
648
        """Test INVALID_TOKEN_RE."""
649
        msg = 'invalid token'
650
        self.re_matches(msg, re.INVALID_TOKEN_RE, NO_GROUP)
651
652
    def test_exc_must_derive_from(self):
653
        """Test EXC_MUST_DERIVE_FROM_RE."""
654
        msgs = [
655
            # Python 2.7
656
            "exceptions must be old-style classes or derived from "
657
            "BaseException, not NoneType",
658
            # Python 3.3 / 3.4
659
            "exceptions must derive from BaseException",
660
        ]
661
        for msg in msgs:
662
            self.re_matches(msg, re.EXC_MUST_DERIVE_FROM_RE, NO_GROUP)
663
664
    def test_unorderable_types(self):
665
        """Test UNORDERABLE_TYPES_RE."""
666
        msgs = [
667
            # Python 3.2 to 3.5
668
            "unorderable types: str() > int()",
669
            "unorderable types: FoobarClass() <= int()",
670
            # PyPy
671
            "unorderable types: FoobarClass > FoobarClass",
672
        ]
673
        for msg in msgs:
674
            self.re_matches(msg, re.UNORDERABLE_TYPES_RE, NO_GROUP)
675
676
    def test_op_not_supported_between_instances(self):
677
        """Test OP_NOT_SUPP_BETWEEN_INSTANCES_RE."""
678
        msgs = [
679
            # Python 3.6
680
            "'<' not supported between instances of 'int' and 'NoneType'",
681
            "'>' not supported between instances of 'Foo' and 'Foo'",
682
        ]
683
        for msg in msgs:
684
            self.re_matches(msg, re.OP_NOT_SUPP_BETWEEN_INSTANCES_RE, NO_GROUP)
685
686
    def test_max_recursion_depth(self):
687
        """Test MAX_RECURSION_DEPTH_RE."""
688
        msg = 'maximum recursion depth exceeded'
689
        self.re_matches(msg, re.MAX_RECURSION_DEPTH_RE, NO_GROUP)
690
691
    def test_size_changed_during_iter(self):
692
        """Test SIZE_CHANGED_DURING_ITER_RE."""
693
        msgs = {
694
            "Set": "Set changed size during iteration",
695
            "dictionnary": "dictionnary changed size during iteration",
696
        }
697
        for name, msg in msgs.items():
698
            groups = (name, )
699
            results = (groups, dict())
700
            self.re_matches(msg, re.SIZE_CHANGED_DURING_ITER_RE, results)
701
702
if __name__ == '__main__':
703
    print(sys.version_info)
704
    unittest2.main()
705