Completed
Push — master ( b86d85...a3675f )
by De
01:27
created

RegexTests.test_unexpected_kw_arg4()   A

Complexity

Conditions 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 16
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_func_name(self):
97
        """Test FUNC_NAME."""
98
        regex = r"^" + re.FUNC_NAME + r"$"
99
        real_funcs = [lambda x:x, range, dir, dict.get, classmethod]  # TODO
100
        real_func_names = [f.__name__ for f in real_funcs]
101
        funcs = ['get', 'range', '<lambda>', 'print'] + list(real_func_names)
102
        for func in funcs:
103
            self.assertRegexpMatches(func, regex)
104
105
    def test_module_name(self):
106
        """Test MODULE_NAME."""
107
        regex = r"^" + re.MODULE_NAME + r"$"
108
        real_modules = set(sys.modules.keys())
109
        modules = ['sys', 'unittest.runner'] + list(real_modules)
110
        for mod in modules:
111
            self.assertRegexpMatches(mod, regex)
112
113
    def test_unbound_assignment(self):
114
        """Test VARREFBEFOREASSIGN_RE."""
115
        msgs = [
116
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
117
            "local variable 'some_var' referenced before assignment",
118
            "free variable 'some_var' referenced before assignment " \
119
            "in enclosing scope",
120
        ]
121
        groups = ('some_var',)
122
        named_groups = {'name': 'some_var'}
123
        results = (groups, named_groups)
124
        for msg in msgs:
125
            self.re_matches(msg, re.VARREFBEFOREASSIGN_RE, results)
126
127
    def test_name_not_defined(self):
128
        """Test NAMENOTDEFINED_RE."""
129
        msgs = [
130
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy3
131
            "name 'some_name' is not defined",
132
            # Python 2.6/2.7/3.2/3.3/PyPy/PyPy3
133
            "global name 'some_name' is not defined",
134
        ]
135
        groups = ('some_name',)
136
        named_groups = {'name': 'some_name'}
137
        results = (groups, named_groups)
138
        for msg in msgs:
139
            self.re_matches(msg, re.NAMENOTDEFINED_RE, results)
140
141
    def test_attribute_error(self):
142
        """Test ATTRIBUTEERROR_RE."""
143
        group_msg = {
144
            ('some.class', 'attri'): [
145
                # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
146
                "'some.class' object has no attribute 'attri'",
147
            ],
148
            ('SomeClass', 'attri'): [
149
                # Python 2.6/2.7/PyPy
150
                "SomeClass instance has no attribute 'attri'",
151
                # Python 2.6/2.7
152
                "class SomeClass has no attribute 'attri'",
153
                # Python 3.2/3.3/3.4/3.5
154
                "type object 'SomeClass' has no attribute 'attri'",
155
            ],
156
        }
157
        for groups, msgs in group_msg.items():
158
            _, attr = groups
159
            named_groups = {'attr': attr}
160
            results = (groups, named_groups)
161
            for msg in msgs:
162
                self.re_matches(msg, re.ATTRIBUTEERROR_RE, results)
163
164
    def test_module_attribute_error(self):
165
        """Test MODULEHASNOATTRIBUTE_RE."""
166
        # Python 3.5
167
        msg = "module 'some_module' has no attribute 'attri'"
168
        groups = ('some_module', 'attri')
169
        _, attr = groups
170
        named_groups = {'attr': attr}
171
        results = (groups, named_groups)
172
        self.re_matches(msg, re.MODULEHASNOATTRIBUTE_RE, results)
173
174
    def test_cannot_import(self):
175
        """Test CANNOTIMPORT_RE."""
176
        msgs = [
177
            # Python 2.6/2.7/3.2/3.3
178
            "cannot import name pie",
179
            # Python 3.4/3.5/PyPy/PyPy3
180
            "cannot import name 'pie'",
181
            # Python 3.7
182
            "cannot import name 'pie' from 'math' (/some/path)",
183
            "cannot import name 'pie' from 'math' (unknown location)"
184
        ]
185
        name = 'pie'
186
        groups = (name, )
187
        named_groups = {'name': name}
188
        results = (groups, named_groups)
189
        for msg in msgs:
190
            self.re_matches(msg, re.CANNOTIMPORT_RE, results)
191
192
    def test_no_module_named(self):
193
        """Test NOMODULE_RE."""
194
        msgs = [
195
            # Python 2.6/2.7/3.2/PyPy/PyPy3
196
            "No module named fake_module",
197
            # Python 3.3/3.4/3.5
198
            "No module named 'fake_module'",
199
        ]
200
        groups = ('fake_module',)
201
        results = (groups, dict())
202
        for msg in msgs:
203
            self.re_matches(msg, re.NOMODULE_RE, results)
204
205
    def test_index_out_of_range(self):
206
        """Test INDEXOUTOFRANGE_RE."""
207
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
208
        msg = "list index out of range"
209
        self.re_matches(msg, re.INDEXOUTOFRANGE_RE, NO_GROUP)
210
211
    def test_unsubscriptable(self):
212
        """Test UNSUBSCRIPTABLE_RE."""
213
        msgs = [
214
            # Python 2.6
215
            "'function' object is unsubscriptable",
216
            # Python 3.2/3.3/3.4/3.5/PyPy/PyPy3
217
            "'function' object is not subscriptable",
218
        ]
219
        groups = ('function',)
220
        results = (groups, dict())
221
        for msg in msgs:
222
            self.re_matches(msg, re.UNSUBSCRIPTABLE_RE, results)
223
224
    def test_unexpected_kw_arg(self):
225
        """Test UNEXPECTED_KEYWORDARG_RE."""
226
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
227
        msgs = [
228
            ("some_func() got an unexpected keyword argument 'a'",
229
                ('some_func', 'a')),
230
            ("<lambda>() got an unexpected keyword argument 'a'",
231
                ('<lambda>', 'a')),
232
        ]
233
        for msg, groups in msgs:
234
            func, kw_arg = groups
235
            named_groups = {'arg': kw_arg, 'func': func}
236
            results = (groups, named_groups)
237
            self.re_matches(msg, re.UNEXPECTED_KEYWORDARG_RE, results)
238
239
    def test_unexpected_kw_arg2(self):
240
        """Test UNEXPECTED_KEYWORDARG2_RE."""
241
        # Python 2.6/2.7/3.2/3.3/3.4/3.5
242
        msg = "'this_doesnt_exist' is an invalid " \
243
            "keyword argument for this function"
244
        groups = ('this_doesnt_exist', )
245
        kw_arg, = groups
246
        named_groups = {'arg': kw_arg}
247
        results = (groups, named_groups)
248
        self.re_matches(msg, re.UNEXPECTED_KEYWORDARG2_RE, results)
249
250
    def test_unexpected_kw_arg3(self):
251
        """Test UNEXPECTED_KEYWORDARG3_RE."""
252
        # PyPy/PyPy3
253
        msg = "invalid keyword arguments to print()"
254
        func = 'print'
255
        groups = (func, )
256
        named_groups = {'func': func}
257
        results = (groups, named_groups)
258
        self.re_matches(msg, re.UNEXPECTED_KEYWORDARG3_RE, results)
259
260
    def test_unexpected_kw_arg4(self):
261
        """Test UNEXPECTED_KEYWORDARG4_RE."""
262
        # Python 3.7
263
        msgs = [
264
            ("'this_doesnt_exist' is an invalid keyword argument for int()",
265
                ('this_doesnt_exist', 'int')),
266
            ("'end_' is an invalid keyword argument for print()",
267
                ('end_', 'print')),
268
            ("'cmp' is an invalid keyword argument for sort()",
269
                ('cmp', 'sort')),
270
        ]
271
        for msg, groups in msgs:
272
            kw_arg, func = groups
273
            named_groups = {'arg': kw_arg, 'func': func}
274
            results = (groups, named_groups)
275
            self.re_matches(msg, re.UNEXPECTED_KEYWORDARG4_RE, results)
276
277
    def test_func_takes_no_kwarg(self):
278
        """Test FUNC_TAKES_NO_KEYWORDARG_RE."""
279
        msgs = [
280
            # CPython : most versions
281
            "get() takes no keyword arguments",
282
            # CPython nightly (as of 21 January 2017) - Python 3.7
283
            "get does not take keyword arguments",
284
            # CPython nightly (as of 7 March 2017) - Python 3.7
285
            "get() does not take keyword arguments",
286
        ]
287
        func = 'get'
288
        groups = (func, )
289
        named_groups = {'func': func}
290
        results = (groups, named_groups)
291
        for msg in msgs:
292
            self.re_matches(msg, re.FUNC_TAKES_NO_KEYWORDARG_RE, results)
293
294
    def test_zero_length_field(self):
295
        """Test ZERO_LEN_FIELD_RE."""
296
        # Python 2.6
297
        msg = "zero length field name in format"
298
        self.re_matches(msg, re.ZERO_LEN_FIELD_RE, NO_GROUP)
299
300
    def test_math_domain_error(self):
301
        """Test MATH_DOMAIN_ERROR_RE."""
302
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
303
        msg = "math domain error"
304
        self.re_matches(msg, re.MATH_DOMAIN_ERROR_RE, NO_GROUP)
305
306
    def test_too_many_values(self):
307
        """Test TOO_MANY_VALUES_UNPACK_RE."""
308
        msgs = [
309
            # Python 2.6/2.7
310
            "too many values to unpack",
311
            # Python 3.2/3.3/3.4/3.5/PyPy3
312
            "too many values to unpack (expected 3)",
313
        ]
314
        for msg in msgs:
315
            self.re_matches(msg, re.TOO_MANY_VALUES_UNPACK_RE, NO_GROUP)
316
317
    def test_unhashable_type(self):
318
        """Test UNHASHABLE_RE."""
319
        msgs = [
320
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
321
            "unhashable type: 'list'",
322
            # PyPy/PyPy3
323
            "'list' objects are unhashable",
324
        ]
325
        groups = ('list',)
326
        results = (groups, dict())
327
        for msg in msgs:
328
            self.re_matches(msg, re.UNHASHABLE_RE, results)
329
330
    def test_cannot_be_interpreted_as_integer(self):
331
        """Test CANNOT_BE_INTERPRETED_INT_RE."""
332
        msgs = {
333
            "'str' object cannot be interpreted as an integer": 'str',
334
            "'list' object cannot be interpreted as an integer": 'list',
335
        }
336
        for msg, typ in msgs.items():
337
            results = ((typ,), dict())
338
            self.re_matches(msg, re.CANNOT_BE_INTERPRETED_INT_RE, results)
339
340
    def test_int_expected_got(self):
341
        """Test INTEGER_EXPECTED_GOT_RE."""
342
        msgs = {
343
            "expected integer, got str object": 'str',
344
            "range() integer end argument expected, got list.": 'list',
345
            "range() integer start argument expected, got list.": 'list',
346
        }
347
        for msg, typ in msgs.items():
348
            results = ((typ,), dict())
349
            self.re_matches(msg, re.INTEGER_EXPECTED_GOT_RE, results)
350
351
    def test_indices_must_be_int(self):
352
        """Test INDICES_MUST_BE_INT_RE."""
353
        msgs = {
354
            # Python 2.6, 2.7, 3.2, 3.3, 3.4
355
            "list indices must be integers, not str": "str",
356
            "list indices must be integers or slices, not str": "str",
357
            # Python 3.5
358
            "tuple indices must be integers or slices, not str": "str",
359
            # PyPy
360
            "list index must be an integer, not str": "str",
361
        }
362
        for msg, typ in msgs.items():
363
            results = ((typ,), dict())
364
            self.re_matches(msg, re.INDICES_MUST_BE_INT_RE, results)
365
366
    def test_outside_function(self):
367
        """Test OUTSIDE_FUNCTION_RE."""
368
        msgs = [
369
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
370
            "'return' outside function",
371
            # PyPy/PyPy3
372
            "return outside function",
373
        ]
374
        groups = ('return',)
375
        results = (groups, dict())
376
        for msg in msgs:
377
            self.re_matches(msg, re.OUTSIDE_FUNCTION_RE, results)
378
379
    def test_nb_positional_argument(self):
380
        """Test NB_ARG_RE."""
381
        msgs = [
382
            # Python 2.6/2.7/PyPy/PyPy3
383
            ("some_func() takes exactly 1 argument (2 given)",
384
                'some_func', '1', '2'),
385
            ("some_func() takes exactly 3 arguments (1 given)",
386
                'some_func', '3', '1'),
387
            ("some_func() takes no arguments (1 given)",
388
                'some_func', 'no', '1'),
389
            ("some_func() takes at least 2 non-keyword arguments (0 given)",
390
                'some_func', '2', '0'),
391
            # Python 3.2
392
            ("some_func() takes exactly 1 positional argument (2 given)",
393
                'some_func', '1', '2'),
394
            # Python 3.3/3.4/3.5
395
            ("some_func() takes 1 positional argument but 2 were given",
396
                'some_func', '1', '2'),
397
            ("some_func() takes 0 positional arguments but 1 was given",
398
                'some_func', '0', '1'),
399
            # PyPy adds suggestions sometimes:
400
            ("some_func() takes no arguments (1 given)"
401
             ". Did you forget 'self' in the function definition?",
402
                'some_func', 'no', '1'),
403
            # More!!!
404
            ("get expected at least 1 arguments, got 0",
405
                'get', '1', '0'),
406
            ("get expected at most 2 arguments, got 3",
407
                'get', '2', '3'),
408
        ]
409
        for msg, func, exp, nb in msgs:
410
            groups = (func, exp, nb)
411
            named_groups = {'func': func, 'expected': exp, 'actual': nb}
412
            results = (groups, named_groups)
413
            self.re_matches(msg, re.NB_ARG_RE, results)
414
415
    def test_missing_positional_arg(self):
416
        """Test MISSING_POS_ARG_RE."""
417
        msgs = [
418
            # Python 3.3/3.4/3.5
419
            "some_func() missing 2 required positional arguments: "
420
            "'much' and 'args'",
421
            "some_func() missing 1 required positional argument: "
422
            "'much'",
423
        ]
424
        func = 'some_func'
425
        groups = (func,)
426
        named_groups = {'func': func}
427
        results = (groups, named_groups)
428
        for msg in msgs:
429
            self.re_matches(msg, re.MISSING_POS_ARG_RE, results)
430
431
    def test_need_more_values_to_unpack(self):
432
        """Test NEED_MORE_VALUES_RE."""
433
        msgs = [
434
            # Python 2.6/2.7/3.2/3.3/3.4/3.5(?)/PyPy3
435
            "need more than 2 values to unpack",
436
            # Python 3.5
437
            "not enough values to unpack (expected 3, got 2)",
438
        ]
439
        for msg in msgs:
440
            self.re_matches(msg, re.NEED_MORE_VALUES_RE, NO_GROUP)
441
442
    def test_missing_parentheses(self):
443
        """Test MISSING_PARENT_RE."""
444
        # Python 3.4/3.5
445
        msg = "Missing parentheses in call to 'exec'"
446
        func = 'exec'
447
        groups = (func,)
448
        named_groups = {'func': func}
449
        results = (groups, named_groups)
450
        self.re_matches(msg, re.MISSING_PARENT_RE, results)
451
452
    def test_invalid_literal(self):
453
        """Test INVALID_LITERAL_RE."""
454
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
455
        msg = "invalid literal for int() with base 10: 'toto'"
456
        groups = ('int', 'toto')
457
        results = (groups, dict())
458
        self.re_matches(msg, re.INVALID_LITERAL_RE, results)
459
460
    def test_invalid_syntax(self):
461
        """Test INVALID_SYNTAX_RE."""
462
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy3
463
        msg = "invalid syntax"
464
        self.re_matches(msg, re.INVALID_SYNTAX_RE, NO_GROUP)
465
466
    def test_invalid_comp(self):
467
        """Test INVALID_COMP_RE."""
468
        # PyPy3
469
        msg = "invalid comparison"
470
        self.re_matches(msg, re.INVALID_COMP_RE, NO_GROUP)
471
472
    def test_expected_length(self):
473
        """Test EXPECTED_LENGTH_RE."""
474
        # PyPy
475
        msg = "expected length 3, got 2"
476
        groups = ('3', '2')
477
        results = (groups, dict())
478
        self.re_matches(msg, re.EXPECTED_LENGTH_RE, results)
479
480
    def test_future_first(self):
481
        """Test FUTURE_FIRST_RE."""
482
        msgs = [
483
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
484
            "from __future__ imports must occur at the beginning of the file",
485
            # PyPy/PyPy3
486
            "__future__ statements must appear at beginning of file",
487
        ]
488
        for msg in msgs:
489
            self.re_matches(msg, re.FUTURE_FIRST_RE, NO_GROUP)
490
491
    def test_future_feature_not_def(self):
492
        """Test FUTURE_FEATURE_NOT_DEF_RE."""
493
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
494
        msg = "future feature divisio is not defined"
495
        groups = ('divisio',)
496
        results = (groups, dict())
497
        self.re_matches(msg, re.FUTURE_FEATURE_NOT_DEF_RE, results)
498
499
    def test_result_has_too_many_items(self):
500
        """Test RESULT_TOO_MANY_ITEMS_RE."""
501
        # Python 2.6
502
        msg = "range() result has too many items"
503
        func = 'range'
504
        groups = (func, )
505
        named_groups = {'func': func}
506
        results = (groups, named_groups)
507
        self.re_matches(msg, re.RESULT_TOO_MANY_ITEMS_RE, results)
508
509
    def test_unqualified_exec(self):
510
        """Test UNQUALIFIED_EXEC_RE."""
511
        msgs = [
512
            # Python 2.6
513
            "unqualified exec is not allowed in function 'func_name' "
514
            "it is a nested function",
515
            # Python 2.7
516
            "unqualified exec is not allowed in function 'func_name' "
517
            "because it is a nested function",
518
            # Python 2.6
519
            "unqualified exec is not allowed in function 'func_name' "
520
            "it contains a nested function with free variables",
521
            # Python 2.7
522
            "unqualified exec is not allowed in function 'func_name' "
523
            "because it contains a nested function with free variables",
524
        ]
525
        for msg in msgs:
526
            self.re_matches(msg, re.UNQUALIFIED_EXEC_RE, NO_GROUP)
527
528
    def test_import_star(self):
529
        """Test IMPORTSTAR_RE."""
530
        msgs = [
531
            # Python 2.6
532
            "import * is not allowed in function 'func_name' because it "
533
            "is contains a nested function with free variables",
534
            # Python 2.7
535
            "import * is not allowed in function 'func_name' because it "
536
            "contains a nested function with free variables",
537
            # Python 2.6
538
            "import * is not allowed in function 'func_name' because it "
539
            "is is a nested function",
540
            # Python 2.7
541
            "import * is not allowed in function 'func_name' because it "
542
            "is a nested function",
543
            # Python 3
544
            "import * only allowed at module level"
545
        ]
546
        for msg in msgs:
547
            self.re_matches(msg, re.IMPORTSTAR_RE, NO_GROUP)
548
549
    def test_does_not_support(self):
550
        """Test OBJ_DOES_NOT_SUPPORT_RE."""
551
        msgs = [
552
            ("'range' object does not support item assignment",
553
                ("range", "item assignment")),
554
            ("'str' object doesn't support item deletion",
555
                ("str", "item deletion")),
556
            ("'set' object does not support indexing",
557
                ("set", "indexing")),
558
        ]
559
        for msg, groups in msgs:
560
            results = (groups, dict())
561
            self.re_matches(msg, re.OBJ_DOES_NOT_SUPPORT_RE, results)
562
563
    def test_cant_convert(self):
564
        """Test CANT_CONVERT_RE."""
565
        msg = "Can't convert 'int' object to str implicitly"
566
        groups = ('int', 'str')
567
        results = (groups, dict())
568
        self.re_matches(msg, re.CANT_CONVERT_RE, results)
569
570
    def test_must_be_type1_not_type2(self):
571
        """Test MUST_BE_TYPE1_NOT_TYPE2_RE."""
572
        msg = "must be str, not int"
573
        groups = ('str', 'int')
574
        results = (groups, dict())
575
        self.re_matches(msg, re.MUST_BE_TYPE1_NOT_TYPE2_RE, results)
576
577
    def test_cannot_concat(self):
578
        """Test CANNOT_CONCAT_RE."""
579
        msg = "cannot concatenate 'str' and 'int' objects"
580
        groups = ('str', 'int')
581
        results = (groups, dict())
582
        self.re_matches(msg, re.CANNOT_CONCAT_RE, results)
583
584
    def test_only_concat(self):
585
        """Test ONLY_CONCAT_RE."""
586
        msg = 'can only concatenate list (not "set") to list'
587
        self.re_matches(msg, re.ONLY_CONCAT_RE, NO_GROUP)
588
589
    def test_unsupported_operand(self):
590
        """Test UNSUPPORTED_OP_RE."""
591
        msg = "unsupported operand type(s) for +: 'int' and 'str'"
592
        groups = ('+', 'int', 'str')
593
        results = (groups, dict())
594
        self.re_matches(msg, re.UNSUPPORTED_OP_RE, results)
595
596
    def test_bad_operand_unary(self):
597
        """Test BAD_OPERAND_UNARY_RE."""
598
        msgs = [
599
            ("bad operand type for unary ~: 'set'", ('~', 'set')),
600
            ("bad operand type for abs(): 'set'", ('abs()', 'set')),
601
            ("unsupported operand type for unary neg: 'Foobar'",
602
                ('neg', 'Foobar')),
603
        ]
604
        for msg, groups in msgs:
605
            results = (groups, dict())
606
            self.re_matches(msg, re.BAD_OPERAND_UNARY_RE, results)
607
608
    def test_not_callable(self):
609
        """Test NOT_CALLABLE_RE."""
610
        msg = "'list' object is not callable"
611
        groups = ('list',)
612
        results = (groups, dict())
613
        self.re_matches(msg, re.NOT_CALLABLE_RE, results)
614
615
    def test_descriptor_requires(self):
616
        """Test DESCRIPT_REQUIRES_TYPE_RE."""
617
        msg = "descriptor 'add' requires a 'set' object but received a 'int'"
618
        groups = ('add', 'set', 'int')
619
        results = (groups, dict())
620
        self.re_matches(msg, re.DESCRIPT_REQUIRES_TYPE_RE, results)
621
622
    def test_argument_not_iterable(self):
623
        """Test ARG_NOT_ITERABLE_RE."""
624
        msgs = [
625
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
626
            "argument of type 'type' is not iterable",
627
            # PyPy/PyPy3
628
            "'type' object is not iterable"
629
        ]
630
        groups = ('type',)
631
        results = (groups, dict())
632
        for msg in msgs:
633
            self.re_matches(msg, re.ARG_NOT_ITERABLE_RE, results)
634
635
    def test_must_be_called_with_instance(self):
636
        """Test MUST_BE_CALLED_WITH_INST_RE."""
637
        msg = "unbound method add() must be called with set " \
638
              "instance as first argument (got int instance instead)"
639
        groups = ('add', 'set', 'int')
640
        results = (groups, dict())
641
        self.re_matches(msg, re.MUST_BE_CALLED_WITH_INST_RE, results)
642
643
    def test_object_has_no(self):
644
        """Test OBJECT_HAS_NO_FUNC_RE."""
645
        msgs = {
646
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
647
            'len': "object of type 'generator' has no len()",
648
            # PyPy/PyPy3
649
            'length': "'generator' has no length",
650
        }
651
        for name, msg in msgs.items():
652
            groups = ('generator', name)
653
            results = (groups, dict())
654
            self.re_matches(msg, re.OBJECT_HAS_NO_FUNC_RE, results)
655
656
    def test_instance_has_no_meth(self):
657
        """Test INSTANCE_HAS_NO_METH_RE."""
658
        # Python 2.6/2.7
659
        msg = "CustomClass instance has no __call__ method"
660
        class_, method = 'CustomClass', '__call__'
661
        groups = (class_, method)
662
        results = (groups, dict())
663
        self.re_matches(msg, re.INSTANCE_HAS_NO_METH_RE, results)
664
665
    def test_nobinding_nonlocal(self):
666
        """Test NO_BINDING_NONLOCAL_RE."""
667
        msg = "no binding for nonlocal 'foo' found"
668
        groups = ('foo',)
669
        results = (groups, dict())
670
        self.re_matches(msg, re.NO_BINDING_NONLOCAL_RE, results)
671
672
    def test_nonlocal_at_module_level(self):
673
        """Test NONLOCAL_AT_MODULE_RE."""
674
        msg = "nonlocal declaration not allowed at module level"
675
        self.re_matches(msg, re.NONLOCAL_AT_MODULE_RE, NO_GROUP)
676
677
    def test_unexpected_eof(self):
678
        """Test UNEXPECTED_EOF_RE."""
679
        msg = "unexpected EOF while parsing"
680
        self.re_matches(msg, re.UNEXPECTED_EOF_RE, NO_GROUP)
681
682
    def test_nosuchfile(self):
683
        """Test NO_SUCH_FILE_RE."""
684
        msg = "No such file or directory"
685
        self.re_matches(msg, re.NO_SUCH_FILE_RE, NO_GROUP)
686
687
    def test_timedata_does_not_match_format(self):
688
        """Test TIME_DATA_DOES_NOT_MATCH_FORMAT_RE."""
689
        msg = "time data '%d %b %y' does not match format '30 Nov 00'"
690
        # 'time data "%d \'%b %y" does not match format \'30 Nov 00\''
691
        groups = ("'%d %b %y'", "'30 Nov 00'")
692
        named_groups = {'format': "'30 Nov 00'", 'timedata': "'%d %b %y'"}
693
        results = (groups, named_groups)
694
        self.re_matches(msg, re.TIME_DATA_DOES_NOT_MATCH_FORMAT_RE, results)
695
696
    def test_invalid_token(self):
697
        """Test INVALID_TOKEN_RE."""
698
        msg = 'invalid token'
699
        self.re_matches(msg, re.INVALID_TOKEN_RE, NO_GROUP)
700
701
    def test_exc_must_derive_from(self):
702
        """Test EXC_MUST_DERIVE_FROM_RE."""
703
        msgs = [
704
            # Python 2.7
705
            "exceptions must be old-style classes or derived from "
706
            "BaseException, not NoneType",
707
            # Python 3.3 / 3.4
708
            "exceptions must derive from BaseException",
709
        ]
710
        for msg in msgs:
711
            self.re_matches(msg, re.EXC_MUST_DERIVE_FROM_RE, NO_GROUP)
712
713
    def test_unorderable_types(self):
714
        """Test UNORDERABLE_TYPES_RE."""
715
        msgs = [
716
            # Python 3.2 to 3.5
717
            "unorderable types: str() > int()",
718
            "unorderable types: FoobarClass() <= int()",
719
            # PyPy
720
            "unorderable types: FoobarClass > FoobarClass",
721
        ]
722
        for msg in msgs:
723
            self.re_matches(msg, re.UNORDERABLE_TYPES_RE, NO_GROUP)
724
725
    def test_op_not_supported_between_instances(self):
726
        """Test OP_NOT_SUPP_BETWEEN_INSTANCES_RE."""
727
        msgs = [
728
            # Python 3.6
729
            "'<' not supported between instances of 'int' and 'NoneType'",
730
            "'>' not supported between instances of 'Foo' and 'Foo'",
731
        ]
732
        for msg in msgs:
733
            self.re_matches(msg, re.OP_NOT_SUPP_BETWEEN_INSTANCES_RE, NO_GROUP)
734
735
    def test_max_recursion_depth(self):
736
        """Test MAX_RECURSION_DEPTH_RE."""
737
        msg = 'maximum recursion depth exceeded'
738
        self.re_matches(msg, re.MAX_RECURSION_DEPTH_RE, NO_GROUP)
739
740
    def test_size_changed_during_iter(self):
741
        """Test SIZE_CHANGED_DURING_ITER_RE."""
742
        msgs = {
743
            "Set": "Set changed size during iteration",
744
            "dictionnary": "dictionnary changed size during iteration",
745
        }
746
        for name, msg in msgs.items():
747
            groups = (name, )
748
            results = (groups, dict())
749
            self.re_matches(msg, re.SIZE_CHANGED_DURING_ITER_RE, results)
750
751
if __name__ == '__main__':
752
    print(sys.version_info)
753
    unittest2.main()
754