Completed
Push — master ( 74734e...6e9a61 )
by De
01:16
created

RegexTests   F

Complexity

Total Complexity 62

Size/Duplication

Total Lines 430
Duplicated Lines 0 %

Importance

Changes 21
Bugs 1 Features 3
Metric Value
wmc 62
c 21
b 1
f 3
dl 0
loc 430
rs 3.8461

44 Methods

Rating   Name   Duplication   Size   Complexity  
A test_unexpected_kw_arg2() 0 7 1
A test_unbound_assignment() 0 13 2
A test_cannot_import() 0 11 2
A test_name_not_defined() 0 12 2
A test_attribute_error() 0 19 3
A test_too_many_values() 0 10 2
A test_zero_length_field() 0 5 1
A test_unsubscriptable() 0 13 2
A test_unexpected_kw_arg() 0 6 1
A test_index_out_of_range() 0 5 1
A test_math_domain_error() 0 5 1
A test_outside_function() 0 11 2
A test_no_module_named() 0 11 2
A test_unexpected_kw_arg3() 0 6 1
A test_module_attribute_error() 0 6 1
A re_matches() 0 12 1
A test_unhashable_type() 0 11 2
A test_missing_parentheses() 0 6 1
A test_object_has_no() 0 11 2
A test_not_callable() 0 5 1
A test_invalid_token() 0 4 1
A test_future_first() 0 10 2
A test_missing_positional_arg() 0 12 2
A test_nobinding_nonlocal() 0 5 1
A test_unqualified_exec() 0 18 2
A test_expected_length() 0 6 1
A test_does_not_support() 0 5 1
B test_nb_positional_argument() 0 24 2
A test_need_more_values_to_unpack() 0 10 2
A test_unsupported_operand() 0 5 1
A test_argument_not_iterable() 0 11 2
A test_cant_convert() 0 5 1
A test_future_feature_not_def() 0 6 1
A test_timedata_does_not_match_format() 0 9 1
A test_nosuchfile() 0 4 1
A test_invalid_comp() 0 5 1
A test_must_be_called_with_instance() 0 7 1
A test_invalid_literal() 0 6 1
A test_invalid_syntax() 0 5 1
A test_cannot_concat() 0 5 1
A test_must_be_type1_not_type2() 0 5 1
A test_result_has_too_many_items() 0 6 1
A test_import_star() 0 20 2
A test_descriptor_requires() 0 6 1

How to fix   Complexity   

Complex Class

Complex classes like RegexTests often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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