Skip to content

Commit 96ee439

Browse files
[mccabe] Add more functional tests to allow for easier refactor
1 parent 5b39db3 commit 96ee439

File tree

2 files changed

+158
-47
lines changed

2 files changed

+158
-47
lines changed

tests/functional/ext/mccabe/mccabe.py

Lines changed: 129 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
11
# pylint: disable=invalid-name,unnecessary-pass,no-else-return,useless-else-on-loop
22
# pylint: disable=undefined-variable,consider-using-sys-exit,unused-variable,too-many-return-statements
3-
# pylint: disable=redefined-outer-name,using-constant-test,unused-argument
3+
# pylint: disable=redefined-outer-name,using-constant-test,unused-argument,unnecessary-lambda-assignment
44
# pylint: disable=broad-except, not-context-manager, no-method-argument, unspecified-encoding, broad-exception-raised
55

66
"""Checks use of "too-complex" check"""
77

88

9-
def f1(): # [too-complex]
9+
def just_a_pass(): # [too-complex]
1010
"""McCabe rating: 1"""
1111
pass
1212

1313

14-
def f2(n): # [too-complex]
14+
def just_a_yield(): # [too-complex]
15+
"""McCabe rating: 1"""
16+
yield from range(10)
17+
18+
19+
def just_a_return(): # [too-complex]
20+
"""McCabe rating: 1"""
21+
return 42
22+
23+
24+
def just_a_raise(): # [too-complex]
25+
"""McCabe rating: 1"""
26+
raise ValueError("An error occurred")
27+
28+
29+
def one_edge_multiple_operations(n): # [too-complex]
1530
"""McCabe rating: 1"""
1631
k = n + 4
1732
s = k + n
1833
return s
1934

2035

21-
def f3(n): # [too-complex]
36+
def if_elif_else(n): # [too-complex]
2237
"""McCabe rating: 3"""
2338
if n > 3:
2439
return "bigger than three"
@@ -28,44 +43,83 @@ def f3(n): # [too-complex]
2843
return "smaller than or equal to three"
2944

3045

31-
def f4(): # [too-complex]
46+
def if_with_conditionals(a, b, c): # [too-complex]
47+
"""McCabe rating: 2"""
48+
if ( # pylint: disable=too-many-boolean-expressions
49+
a
50+
and b
51+
or c
52+
or (a and not b)
53+
or (b and not c)
54+
or (c and not a)
55+
or (a and b and c)
56+
):
57+
return True
58+
return False
59+
60+
61+
def for_loop(): # [too-complex]
3262
"""McCabe rating: 2"""
3363
for i in range(10):
3464
print(i)
3565

3666

37-
def f5(mylist): # [too-complex]
67+
def for_loop_with_else(mylist): # [too-complex]
3868
"""McCabe rating: 2"""
3969
for i in mylist:
4070
print(i)
4171
else:
4272
print(None)
4373

4474

45-
def f6(n): # [too-complex]
75+
def recursive_if_else(n): # [too-complex]
4676
"""McCabe rating: 2"""
4777
if n > 4:
48-
return f(n - 1)
78+
return recursive_if_else(n - 1)
4979
else:
5080
return n
5181

5282

53-
def f7(): # [too-complex]
83+
def for_loop_with_break(): # [too-complex]
84+
"""McCabe rating: 3"""
85+
for i in range(10):
86+
if i == 5:
87+
break
88+
89+
90+
def for_loop_with_continue(): # [too-complex]
91+
"""McCabe rating: 3"""
92+
for i in range(10):
93+
if i % 2 == 0:
94+
continue
95+
print(i)
96+
97+
98+
def for_loop_with_continue_and_break(): # [too-complex]
99+
"""McCabe rating: 4"""
100+
for i in range(10):
101+
if i % 2 == 0:
102+
continue
103+
if i % 5 == 0:
104+
break
105+
106+
107+
def inner_functions(): # [too-complex]
54108
"""McCabe rating: 3"""
55109

56-
def b():
110+
def inner_function(): # Known false negative ?
57111
"""McCabe rating: 2"""
58112

59-
def c():
113+
def innermost_function(): # Known false negative ?
60114
"""McCabe rating: 1"""
61115
pass
62116

63-
c()
117+
innermost_function()
64118

65-
b()
119+
inner_function()
66120

67121

68-
def f8(): # [too-complex]
122+
def try_with_multiple_except_and_else(): # [too-complex]
69123
"""McCabe rating: 4"""
70124
try:
71125
print(1)
@@ -77,7 +131,44 @@ def f8(): # [too-complex]
77131
print(4)
78132

79133

80-
def f9(): # [too-complex]
134+
def with_(fp): # [too-complex]
135+
"""McCabe rating: 1"""
136+
with open(fp) as f:
137+
content = f.read()
138+
return content
139+
140+
141+
def lambda_with_if(lst): # [too-complex]
142+
"""McCabe rating should be 4, but is 1 (known false negative ?)
143+
144+
See counterpart 'comprehension_with_if' below."""
145+
f = lambda x: [x for x in lst if x % 2 == 0] or range(10)
146+
return f(lst)
147+
148+
149+
def comprehension_with_if(lst): # [too-complex]
150+
"""McCabe rating: should be 4 but is 1 (known false negative ?)
151+
https://github.com/PyCQA/mccabe/issues/69
152+
"""
153+
return [x for x in lst if x % 2 == 0] or range(10)
154+
155+
156+
def comprehension_with_if_equivalent(lst): # [too-complex]
157+
"""McCabe rating: 4
158+
159+
See counterpart 'comprehension_with_if' above.
160+
"""
161+
xs = []
162+
for x in lst:
163+
if x % 2 == 0:
164+
xs.append(x)
165+
if xs:
166+
return xs
167+
else:
168+
return range(10)
169+
170+
171+
def nested_ifs_elifs_elses(): # [too-complex]
81172
"""McCabe rating: 9"""
82173
myint = 2
83174
if myint > 5:
@@ -103,7 +194,7 @@ def f9(): # [too-complex]
103194
myint = 4
104195

105196

106-
def f10(): # [too-complex]
197+
def big_elif_chain_with_nested_ifs(): # [too-complex]
107198
"""McCabe rating: 11"""
108199
myint = 2
109200
if myint == 5:
@@ -130,16 +221,16 @@ def f10(): # [too-complex]
130221
return myint
131222

132223

133-
class MyClass1:
224+
class ExampleComplexityClass:
134225
"""Class of example to test mccabe"""
135226

136-
_name = "MyClass" # To force a tail.node=None
227+
_name = "ExampleComplexityKlass" # To force a tail.node=None
137228

138-
def method1(): # [too-complex]
229+
def just_a_pass(self): # [too-complex]
139230
"""McCabe rating: 1"""
140231
pass
141232

142-
def method2(self, param1): # [too-complex, too-many-branches]
233+
def highly_complex(self, param1): # [too-complex, too-many-branches]
143234
"""McCabe rating: 15"""
144235
if not param1:
145236
pass
@@ -148,9 +239,7 @@ def method2(self, param1): # [too-complex, too-many-branches]
148239
pass
149240
else:
150241
pass
151-
152242
pass
153-
154243
if param1:
155244
pass
156245
if param1:
@@ -166,7 +255,6 @@ def method2(self, param1): # [too-complex, too-many-branches]
166255
if param1:
167256
for value in range(5):
168257
pass
169-
170258
pass
171259
for count in range(6):
172260
with open("myfile") as fp:
@@ -195,7 +283,8 @@ def method2(self, param1): # [too-complex, too-many-branches]
195283
return param1
196284

197285

198-
for count in range(10): # [too-complex]
286+
for count in range(10): # [too-complex]
287+
# McCabe rating: 4
199288
if count == 1:
200289
exit(0)
201290
elif count == 2:
@@ -204,7 +293,7 @@ def method2(self, param1): # [too-complex, too-many-branches]
204293
exit(2)
205294

206295

207-
def method3(self): # [too-complex]
296+
def try_finally_with_nested_ifs(): # [too-complex]
208297
"""McCabe rating: 3"""
209298
try:
210299
if True:
@@ -215,23 +304,23 @@ def method3(self): # [too-complex]
215304
pass
216305
return True
217306

218-
def match_case_complexity(avg): # [too-complex]
307+
308+
def match_case(avg): # [too-complex]
219309
"""McCabe rating: 4
220310
See https://github.com/astral-sh/ruff/issues/11421
221311
"""
222312
# pylint: disable=bare-name-capture-pattern
223313
match avg:
224-
case avg if avg < .3:
314+
case avg if avg < 0.3:
225315
avg_grade = "F"
226-
case avg if avg < .7:
316+
case avg if avg < 0.7:
227317
avg_grade = "E+"
228318
case _:
229319
raise ValueError(f"Unexpected average: {avg}")
230320
return avg_grade
231321

232322

233-
234-
def nested_match(data): # [too-complex]
323+
def nested_match_case(data): # [too-complex]
235324
"""McCabe rating: 8
236325
237326
Nested match statements."""
@@ -251,3 +340,13 @@ def nested_match(data): # [too-complex]
251340
return "Product with no price"
252341
case _:
253342
return "Unknown data type"
343+
344+
345+
def yield_in_for_loop(a=None, b=None, c=None): # [too-complex]
346+
"""McCabe rating: 4"""
347+
yield from a or ()
348+
for elt in b:
349+
if elt is not None:
350+
yield elt
351+
if c is not None:
352+
yield c
Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
1-
too-complex:9:0:9:6:f1:'f1' is too complex. The McCabe rating is 1:HIGH
2-
too-complex:14:0:14:6:f2:'f2' is too complex. The McCabe rating is 1:HIGH
3-
too-complex:21:0:21:6:f3:'f3' is too complex. The McCabe rating is 3:HIGH
4-
too-complex:31:0:31:6:f4:'f4' is too complex. The McCabe rating is 2:HIGH
5-
too-complex:37:0:37:6:f5:'f5' is too complex. The McCabe rating is 2:HIGH
6-
too-complex:45:0:45:6:f6:'f6' is too complex. The McCabe rating is 2:HIGH
7-
too-complex:53:0:53:6:f7:'f7' is too complex. The McCabe rating is 3:HIGH
8-
too-complex:68:0:68:6:f8:'f8' is too complex. The McCabe rating is 4:HIGH
9-
too-complex:80:0:80:6:f9:'f9' is too complex. The McCabe rating is 9:HIGH
10-
too-complex:106:0:106:7:f10:'f10' is too complex. The McCabe rating is 11:HIGH
11-
too-complex:138:4:138:15:MyClass1.method1:'method1' is too complex. The McCabe rating is 1:HIGH
12-
too-complex:142:4:142:15:MyClass1.method2:'method2' is too complex. The McCabe rating is 15:HIGH
13-
too-many-branches:142:4:142:15:MyClass1.method2:Too many branches (19/12):UNDEFINED
14-
too-complex:198:0:204:15::This 'for' is too complex. The McCabe rating is 4:HIGH
15-
too-complex:207:0:207:11:method3:'method3' is too complex. The McCabe rating is 3:HIGH
16-
too-complex:218:0:218:25:match_case_complexity:'match_case_complexity' is too complex. The McCabe rating is 4:HIGH
17-
too-complex:234:0:234:16:nested_match:'nested_match' is too complex. The McCabe rating is 8:HIGH
1+
too-complex:9:0:9:15:just_a_pass:'just_a_pass' is too complex. The McCabe rating is 1:HIGH
2+
too-complex:14:0:14:16:just_a_yield:'just_a_yield' is too complex. The McCabe rating is 1:HIGH
3+
too-complex:19:0:19:17:just_a_return:'just_a_return' is too complex. The McCabe rating is 1:HIGH
4+
too-complex:24:0:24:16:just_a_raise:'just_a_raise' is too complex. The McCabe rating is 1:HIGH
5+
too-complex:29:0:29:32:one_edge_multiple_operations:'one_edge_multiple_operations' is too complex. The McCabe rating is 1:HIGH
6+
too-complex:36:0:36:16:if_elif_else:'if_elif_else' is too complex. The McCabe rating is 3:HIGH
7+
too-complex:46:0:46:24:if_with_conditionals:'if_with_conditionals' is too complex. The McCabe rating is 2:HIGH
8+
too-complex:61:0:61:12:for_loop:'for_loop' is too complex. The McCabe rating is 2:HIGH
9+
too-complex:67:0:67:22:for_loop_with_else:'for_loop_with_else' is too complex. The McCabe rating is 2:HIGH
10+
too-complex:75:0:75:21:recursive_if_else:'recursive_if_else' is too complex. The McCabe rating is 2:HIGH
11+
too-complex:83:0:83:23:for_loop_with_break:'for_loop_with_break' is too complex. The McCabe rating is 3:HIGH
12+
too-complex:90:0:90:26:for_loop_with_continue:'for_loop_with_continue' is too complex. The McCabe rating is 3:HIGH
13+
too-complex:98:0:98:36:for_loop_with_continue_and_break:'for_loop_with_continue_and_break' is too complex. The McCabe rating is 4:HIGH
14+
too-complex:107:0:107:19:inner_functions:'inner_functions' is too complex. The McCabe rating is 3:HIGH
15+
too-complex:122:0:122:37:try_with_multiple_except_and_else:'try_with_multiple_except_and_else' is too complex. The McCabe rating is 4:HIGH
16+
too-complex:134:0:134:9:with_:'with_' is too complex. The McCabe rating is 1:HIGH
17+
too-complex:141:0:141:18:lambda_with_if:'lambda_with_if' is too complex. The McCabe rating is 1:HIGH
18+
too-complex:149:0:149:25:comprehension_with_if:'comprehension_with_if' is too complex. The McCabe rating is 1:HIGH
19+
too-complex:156:0:156:36:comprehension_with_if_equivalent:'comprehension_with_if_equivalent' is too complex. The McCabe rating is 4:HIGH
20+
too-complex:171:0:171:26:nested_ifs_elifs_elses:'nested_ifs_elifs_elses' is too complex. The McCabe rating is 9:HIGH
21+
too-complex:197:0:197:34:big_elif_chain_with_nested_ifs:'big_elif_chain_with_nested_ifs' is too complex. The McCabe rating is 11:HIGH
22+
too-complex:229:4:229:19:ExampleComplexityClass.just_a_pass:'just_a_pass' is too complex. The McCabe rating is 1:HIGH
23+
too-complex:233:4:233:22:ExampleComplexityClass.highly_complex:'highly_complex' is too complex. The McCabe rating is 15:HIGH
24+
too-many-branches:233:4:233:22:ExampleComplexityClass.highly_complex:Too many branches (19/12):UNDEFINED
25+
too-complex:286:0:293:15::This 'for' is too complex. The McCabe rating is 4:HIGH
26+
too-complex:296:0:296:31:try_finally_with_nested_ifs:'try_finally_with_nested_ifs' is too complex. The McCabe rating is 3:HIGH
27+
too-complex:308:0:308:14:match_case:'match_case' is too complex. The McCabe rating is 4:HIGH
28+
too-complex:323:0:323:21:nested_match_case:'nested_match_case' is too complex. The McCabe rating is 8:HIGH
29+
too-complex:345:0:345:21:yield_in_for_loop:'yield_in_for_loop' is too complex. The McCabe rating is 4:HIGH

0 commit comments

Comments
 (0)