Completed
Push — master ( ba5da2...8ab8de )
by De
01:20
created

RegexTests.test_max_recursion_depth()   A

Complexity

Conditions 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
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
7
NO_GROUP = ((), dict())
8
# Flag used to check that a text only match the expected regexp and not
9
# the other to ensure we do not have ambiguous/double regexp matching.
10
CHECK_OTHERS_DONT_MATCH = True
11
12
13
class RegexTests(unittest2.TestCase):
14
    """Tests to check that error messages match the regexps."""
15
16
    def re_matches(self, text, regexp, results):
17
        """Check that text matches regexp and gives the right match groups.
18
19
        result is a tuple containing the expected return values for groups()
20
        and groupdict().
21
        """
22
        groups, named_groups = results
23
        self.assertRegexpMatches(text, regexp)   # does pretty printing
24
        match = re.match(regexp, text)
25
        self.assertTrue(match)
26
        self.assertEqual(groups, match.groups())
27
        self.assertEqual(named_groups, match.groupdict())
28
        for other_name, other_re in re.ALL_REGEXPS.items():
29
            if other_re != regexp and CHECK_OTHERS_DONT_MATCH:
30
                details = "text '%s' matches %s (on top of %s)" % \
31
                        (text, other_name, regexp)
32
                self.assertNotRegexpMatches(text, other_re, details)
33
                no_match = re.match(other_re, text)
34
                self.assertEqual(no_match, None, details)
35
36
    def test_unbound_assignment(self):
37
        """Test VARREFBEFOREASSIGN_RE."""
38
        msgs = [
39
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
40
            "local variable 'some_var' referenced before assignment",
41
            "free variable 'some_var' referenced before assignment " \
42
            "in enclosing scope",
43
        ]
44
        groups = ('some_var',)
45
        named_groups = {'name': 'some_var'}
46
        results = (groups, named_groups)
47
        for msg in msgs:
48
            self.re_matches(msg, re.VARREFBEFOREASSIGN_RE, results)
49
50
    def test_name_not_defined(self):
51
        """Test NAMENOTDEFINED_RE."""
52
        msgs = [
53
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy3
54
            "name 'some_name' is not defined",
55
            # Python 2.6/2.7/3.2/3.3/PyPy/PyPy3
56
            "global name 'some_name' is not defined",
57
        ]
58
        groups = ('some_name',)
59
        named_groups = {'name': 'some_name'}
60
        for msg in msgs:
61
            self.re_matches(msg, re.NAMENOTDEFINED_RE, (groups, named_groups))
62
63
    def test_attribute_error(self):
64
        """Test ATTRIBUTEERROR_RE."""
65
        group_msg = {
66
            ('some.class', 'attri'): [
67
                # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
68
                "'some.class' object has no attribute 'attri'",
69
            ],
70
            ('SomeClass', 'attri'): [
71
                # Python 2.6/2.7/PyPy
72
                "SomeClass instance has no attribute 'attri'",
73
                # Python 2.6/2.7
74
                "class SomeClass has no attribute 'attri'",
75
                # Python 3.2/3.3/3.4/3.5
76
                "type object 'SomeClass' has no attribute 'attri'",
77
            ],
78
        }
79
        for group, msgs in group_msg.items():
80
            for msg in msgs:
81
                self.re_matches(msg, re.ATTRIBUTEERROR_RE, (group, dict()))
82
83
    def test_module_attribute_error(self):
84
        """Test MODULEHASNOATTRIBUTE_RE."""
85
        # Python 3.5
86
        msg = "module 'some_module' has no attribute 'attri'"
87
        group = ('some_module', 'attri')
88
        self.re_matches(msg, re.MODULEHASNOATTRIBUTE_RE, (group, dict()))
89
90
    def test_cannot_import(self):
91
        """Test CANNOTIMPORT_RE."""
92
        msgs = [
93
            # Python 2.6/2.7/3.2/3.3
94
            "cannot import name pie",
95
            # Python 3.4/3.5/PyPy/PyPy3
96
            "cannot import name 'pie'",
97
        ]
98
        groups = ('pie',)
99
        for msg in msgs:
100
            self.re_matches(msg, re.CANNOTIMPORT_RE, (groups, dict()))
101
102
    def test_no_module_named(self):
103
        """Test NOMODULE_RE."""
104
        msgs = [
105
            # Python 2.6/2.7/3.2/PyPy/PyPy3
106
            "No module named fake_module",
107
            # Python 3.3/3.4/3.5
108
            "No module named 'fake_module'",
109
        ]
110
        groups = ('fake_module',)
111
        for msg in msgs:
112
            self.re_matches(msg, re.NOMODULE_RE, (groups, dict()))
113
114
    def test_index_out_of_range(self):
115
        """Test INDEXOUTOFRANGE_RE."""
116
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
117
        msg = "list index out of range"
118
        self.re_matches(msg, re.INDEXOUTOFRANGE_RE, NO_GROUP)
119
120
    def test_unsubscriptable(self):
121
        """Test UNSUBSCRIPTABLE_RE."""
122
        msgs = [
123
            # Python 2.6
124
            "'function' object is unsubscriptable",
125
            # Python 3.2/3.3/3.4/3.5/PyPy/PyPy3
126
            "'function' object is not subscriptable",
127
        ]
128
        groups = ('function',)
129
        for msg in msgs:
130
            self.re_matches(msg, re.UNSUBSCRIPTABLE_RE, (groups, dict()))
131
132
    def test_unexpected_kw_arg(self):
133
        """Test UNEXPECTED_KEYWORDARG_RE."""
134
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
135
        msgs = [
136
            ("some_func() got an unexpected keyword argument 'a'",
137
                ('some_func', 'a')),
138
            ("<lambda>() got an unexpected keyword argument 'a'",
139
                ('<lambda>', 'a')),
140
        ]
141
        for msg, groups in msgs:
142
            self.re_matches(msg, re.UNEXPECTED_KEYWORDARG_RE, (groups, dict()))
143
144
    def test_unexpected_kw_arg2(self):
145
        """Test UNEXPECTED_KEYWORDARG2_RE."""
146
        # Python 2.6/2.7/3.2/3.3/3.4/3.5
147
        msg = "'this_doesnt_exist' is an invalid " \
148
            "keyword argument for this function"
149
        groups = ('this_doesnt_exist', )
150
        self.re_matches(msg, re.UNEXPECTED_KEYWORDARG2_RE, (groups, dict()))
151
152
    def test_unexpected_kw_arg3(self):
153
        """Test UNEXPECTED_KEYWORDARG3_RE."""
154
        # PyPy/PyPy3
155
        msg = "invalid keyword arguments to print()"
156
        groups = ('print', )
157
        self.re_matches(msg, re.UNEXPECTED_KEYWORDARG3_RE, (groups, dict()))
158
159
    def test_zero_length_field(self):
160
        """Test ZERO_LEN_FIELD_RE."""
161
        # Python 2.6
162
        msg = "zero length field name in format"
163
        self.re_matches(msg, re.ZERO_LEN_FIELD_RE, NO_GROUP)
164
165
    def test_math_domain_error(self):
166
        """Test MATH_DOMAIN_ERROR_RE."""
167
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
168
        msg = "math domain error"
169
        self.re_matches(msg, re.MATH_DOMAIN_ERROR_RE, NO_GROUP)
170
171
    def test_too_many_values(self):
172
        """Test TOO_MANY_VALUES_UNPACK_RE."""
173
        msgs = [
174
            # Python 2.6/2.7
175
            "too many values to unpack",
176
            # Python 3.2/3.3/3.4/3.5/PyPy3
177
            "too many values to unpack (expected 3)",
178
        ]
179
        for msg in msgs:
180
            self.re_matches(msg, re.TOO_MANY_VALUES_UNPACK_RE, NO_GROUP)
181
182
    def test_unhashable_type(self):
183
        """Test UNHASHABLE_RE."""
184
        msgs = [
185
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
186
            "unhashable type: 'list'",
187
            # PyPy/PyPy3
188
            "'list' objects are unhashable",
189
        ]
190
        groups = ('list',)
191
        for msg in msgs:
192
            self.re_matches(msg, re.UNHASHABLE_RE, (groups, dict()))
193
194
    def test_outside_function(self):
195
        """Test OUTSIDE_FUNCTION_RE."""
196
        msgs = [
197
            # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
198
            "'return' outside function",
199
            # PyPy/PyPy3
200
            "return outside function",
201
        ]
202
        groups = ('return',)
203
        for msg in msgs:
204
            self.re_matches(msg, re.OUTSIDE_FUNCTION_RE, (groups, dict()))
205
206
    def test_nb_positional_argument(self):
207
        """Test NB_ARG_RE."""
208
        msgs = [
209
            # Python 2.6/2.7/PyPy/PyPy3
210
            ("some_func() takes exactly 1 argument (2 given)",
211
                '1', '2'),
212
            ("some_func() takes exactly 3 arguments (1 given)",
213
                '3', '1'),
214
            ("some_func() takes no arguments (1 given)",
215
                'no', '1'),
216
            ("some_func() takes at least 2 non-keyword arguments (0 given)",
217
                '2', '0'),
218
            # Python 3.2
219
            ("some_func() takes exactly 1 positional argument (2 given)",
220
                '1', '2'),
221
            # Python 3.3/3.4/3.5
222
            ("some_func() takes 1 positional argument but 2 were given",
223
                '1', '2'),
224
            ("some_func() takes 0 positional arguments but 1 was given",
225
                '0', '1'),
226
        ]
227
        for msg, exp, nb in msgs:
228
            groups = ('some_func', exp, nb)
229
            self.re_matches(msg, re.NB_ARG_RE, (groups, dict()))
230
231
    def test_missing_positional_arg(self):
232
        """Test MISSING_POS_ARG_RE."""
233
        msgs = [
234
            # Python 3.3/3.4/3.5
235
            "some_func() missing 2 required positional arguments: "
236
            "'much' and 'args'",
237
            "some_func() missing 1 required positional argument: "
238
            "'much'",
239
        ]
240
        groups = ('some_func',)
241
        for msg in msgs:
242
            self.re_matches(msg, re.MISSING_POS_ARG_RE, (groups, dict()))
243
244
    def test_need_more_values_to_unpack(self):
245
        """Test NEED_MORE_VALUES_RE."""
246
        msgs = [
247
            # Python 2.6/2.7/3.2/3.3/3.4/3.5(?)/PyPy3
248
            "need more than 2 values to unpack",
249
            # Python 3.5
250
            "not enough values to unpack (expected 3, got 2)",
251
        ]
252
        for msg in msgs:
253
            self.re_matches(msg, re.NEED_MORE_VALUES_RE, NO_GROUP)
254
255
    def test_missing_parentheses(self):
256
        """Test MISSING_PARENT_RE."""
257
        # Python 3.4/3.5
258
        msg = "Missing parentheses in call to 'exec'"
259
        groups = ('exec',)
260
        self.re_matches(msg, re.MISSING_PARENT_RE, (groups, dict()))
261
262
    def test_invalid_literal(self):
263
        """Test INVALID_LITERAL_RE."""
264
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
265
        msg = "invalid literal for int() with base 10: 'toto'"
266
        groups = ('int', 'toto')
267
        self.re_matches(msg, re.INVALID_LITERAL_RE, (groups, dict()))
268
269
    def test_invalid_syntax(self):
270
        """Test INVALID_SYNTAX_RE."""
271
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy3
272
        msg = "invalid syntax"
273
        self.re_matches(msg, re.INVALID_SYNTAX_RE, NO_GROUP)
274
275
    def test_invalid_comp(self):
276
        """Test INVALID_COMP_RE."""
277
        # PyPy3
278
        msg = "invalid comparison"
279
        self.re_matches(msg, re.INVALID_COMP_RE, NO_GROUP)
280
281
    def test_expected_length(self):
282
        """Test EXPECTED_LENGTH_RE."""
283
        # PyPy
284
        msg = "expected length 3, got 2"
285
        groups = ('3', '2')
286
        self.re_matches(msg, re.EXPECTED_LENGTH_RE, (groups, dict()))
287
288
    def test_future_first(self):
289
        """Test FUTURE_FIRST_RE."""
290
        msgs = [
291
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
292
            "from __future__ imports must occur at the beginning of the file",
293
            # PyPy/PyPy3
294
            "__future__ statements must appear at beginning of file",
295
        ]
296
        for msg in msgs:
297
            self.re_matches(msg, re.FUTURE_FIRST_RE, NO_GROUP)
298
299
    def test_future_feature_not_def(self):
300
        """Test FUTURE_FEATURE_NOT_DEF_RE."""
301
        # Python 2.6/2.7/3.2/3.3/3.4/3.5/PyPy/PyPy3
302
        msg = "future feature divisio is not defined"
303
        groups = ('divisio',)
304
        self.re_matches(msg, re.FUTURE_FEATURE_NOT_DEF_RE, (groups, dict()))
305
306
    def test_result_has_too_many_items(self):
307
        """Test RESULT_TOO_MANY_ITEMS_RE."""
308
        # Python 2.6
309
        msg = "range() result has too many items"
310
        groups = ('range',)
311
        self.re_matches(msg, re.RESULT_TOO_MANY_ITEMS_RE, (groups, dict()))
312
313
    def test_unqualified_exec(self):
314
        """Test UNQUALIFIED_EXEC_RE."""
315
        msgs = [
316
            # Python 2.6
317
            "unqualified exec is not allowed in function 'func_name' "
318
            "it is a nested function",
319
            # Python 2.7
320
            "unqualified exec is not allowed in function 'func_name' "
321
            "because it is a nested function",
322
            # Python 2.6
323
            "unqualified exec is not allowed in function 'func_name' "
324
            "it contains a nested function with free variables",
325
            # Python 2.7
326
            "unqualified exec is not allowed in function 'func_name' "
327
            "because it contains a nested function with free variables",
328
        ]
329
        for msg in msgs:
330
            self.re_matches(msg, re.UNQUALIFIED_EXEC_RE, NO_GROUP)
331
332
    def test_import_star(self):
333
        """Test IMPORTSTAR_RE."""
334
        msgs = [
335
            # Python 2.6
336
            "import * is not allowed in function 'func_name' because it "
337
            "is contains a nested function with free variables",
338
            # Python 2.7
339
            "import * is not allowed in function 'func_name' because it "
340
            "contains a nested function with free variables",
341
            # Python 2.6
342
            "import * is not allowed in function 'func_name' because it "
343
            "is is a nested function",
344
            # Python 2.7
345
            "import * is not allowed in function 'func_name' because it "
346
            "is a nested function",
347
            # Python 3
348
            "import * only allowed at module level"
349
        ]
350
        for msg in msgs:
351
            self.re_matches(msg, re.IMPORTSTAR_RE, NO_GROUP)
352
353
    def test_does_not_support(self):
354
        """Test OBJ_DOES_NOT_SUPPORT_RE."""
355
        msgs = [
356
            ("'range' object does not support item assignment",
357
                ("range", "item assignment")),
358
            ("'str' object doesn't support item deletion",
359
                ("str", "item deletion")),
360
            ("'set' object does not support indexing",
361
                ("set", "indexing")),
362
        ]
363
        for msg, groups in msgs:
364
            self.re_matches(msg, re.OBJ_DOES_NOT_SUPPORT_RE, (groups, dict()))
365
366
    def test_cant_convert(self):
367
        """Test CANT_CONVERT_RE."""
368
        msg = "Can't convert 'int' object to str implicitly"
369
        groups = ('int', 'str')
370
        self.re_matches(msg, re.CANT_CONVERT_RE, (groups, dict()))
371
372
    def test_must_be_type1_not_type2(self):
373
        """Test MUST_BE_TYPE1_NOT_TYPE2_RE."""
374
        msg = "must be str, not int"
375
        groups = ('str', 'int')
376
        self.re_matches(msg, re.MUST_BE_TYPE1_NOT_TYPE2_RE, (groups, dict()))
377
378
    def test_cannot_concat(self):
379
        """Test CANNOT_CONCAT_RE."""
380
        msg = "cannot concatenate 'str' and 'int' objects"
381
        groups = ('str', 'int')
382
        self.re_matches(msg, re.CANNOT_CONCAT_RE, (groups, dict()))
383
384
    def test_unsupported_operand(self):
385
        """Test UNSUPPORTED_OP_RE."""
386
        msg = "unsupported operand type(s) for +: 'int' and 'str'"
387
        groups = ('+', 'int', 'str')
388
        self.re_matches(msg, re.UNSUPPORTED_OP_RE, (groups, dict()))
389
390
    def test_bad_operand_unary(self):
391
        """Test BAD_OPERAND_UNARY_RE."""
392
        msgs = [
393
            ("bad operand type for unary ~: 'set'", ('~', 'set')),
394
            ("bad operand type for abs(): 'set'", ('abs()', 'set')),
395
            ("unsupported operand type for unary neg: 'Foobar'",
396
                ('neg', 'Foobar')),
397
        ]
398
        for msg, group in msgs:
399
            self.re_matches(msg, re.BAD_OPERAND_UNARY_RE, (group, dict()))
400
401
    def test_not_callable(self):
402
        """Test NOT_CALLABLE_RE."""
403
        msg = "'list' object is not callable"
404
        groups = ('list',)
405
        self.re_matches(msg, re.NOT_CALLABLE_RE, (groups, dict()))
406
407
    def test_descriptor_requires(self):
408
        """Test DESCRIPT_REQUIRES_TYPE_RE."""
409
        msg = "descriptor 'add' requires a 'set' object but received a 'int'"
410
        groups = ('add', 'set', 'int')
411
        self.re_matches(
412
            msg, re.DESCRIPT_REQUIRES_TYPE_RE, (groups, dict()))
413
414
    def test_argument_not_iterable(self):
415
        """Test ARG_NOT_ITERABLE_RE."""
416
        msgs = [
417
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
418
            "argument of type 'type' is not iterable",
419
            # PyPy/PyPy3
420
            "'type' object is not iterable"
421
        ]
422
        groups = ('type',)
423
        for msg in msgs:
424
            self.re_matches(msg, re.ARG_NOT_ITERABLE_RE, (groups, dict()))
425
426
    def test_must_be_called_with_instance(self):
427
        """Test MUST_BE_CALLED_WITH_INST_RE."""
428
        msg = "unbound method add() must be called with set " \
429
              "instance as first argument (got int instance instead)"
430
        groups = ('add', 'set', 'int')
431
        self.re_matches(
432
            msg, re.MUST_BE_CALLED_WITH_INST_RE, (groups, dict()))
433
434
    def test_object_has_no(self):
435
        """Test OBJECT_HAS_NO_FUNC_RE."""
436
        msgs = {
437
            # Python 2.6/2.7/3.2/3.3/3.4/3.5
438
            'len': "object of type 'generator' has no len()",
439
            # PyPy/PyPy3
440
            'length': "'generator' has no length",
441
        }
442
        for name, msg in msgs.items():
443
            groups = ('generator', name)
444
            self.re_matches(msg, re.OBJECT_HAS_NO_FUNC_RE, (groups, dict()))
445
446
    def test_nobinding_nonlocal(self):
447
        """Test NO_BINDING_NONLOCAL_RE."""
448
        msg = "no binding for nonlocal 'foo' found"
449
        groups = ('foo',)
450
        self.re_matches(msg, re.NO_BINDING_NONLOCAL_RE, (groups, dict()))
451
452
    def test_nosuchfile(self):
453
        """Test NO_SUCH_FILE_RE."""
454
        msg = "No such file or directory"
455
        self.re_matches(msg, re.NO_SUCH_FILE_RE, NO_GROUP)
456
457
    def test_timedata_does_not_match_format(self):
458
        """Test TIME_DATA_DOES_NOT_MATCH_FORMAT_RE."""
459
        msg = "time data '%d %b %y' does not match format '30 Nov 00'"
460
        # 'time data "%d \'%b %y" does not match format \'30 Nov 00\''
461
        groups = ("'%d %b %y'", "'30 Nov 00'")
462
        named_groups = {'format': "'30 Nov 00'", 'timedata': "'%d %b %y'"}
463
        self.re_matches(msg,
464
                        re.TIME_DATA_DOES_NOT_MATCH_FORMAT_RE,
465
                        (groups, named_groups))
466
467
    def test_invalid_token(self):
468
        """Test INVALID_TOKEN_RE."""
469
        msg = 'invalid token'
470
        self.re_matches(msg, re.INVALID_TOKEN_RE, NO_GROUP)
471
472
    def test_max_recursion_depth(self):
473
        """Test MAX_RECURSION_DEPTH_RE."""
474
        msg = 'maximum recursion depth exceeded'
475
        self.re_matches(msg, re.MAX_RECURSION_DEPTH_RE, NO_GROUP)
476
477
if __name__ == '__main__':
478
    print(sys.version_info)
479
    unittest2.main()
480