Skip to content

Commit 7290e6f

Browse files
committed
fix: WPS222 false positive for nested conditions
1 parent 88d8755 commit 7290e6f

3 files changed

Lines changed: 40 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Semantic versioning in our case means:
2424
- Fixes false positive `WPS366` allowing the use
2525
of a single constant in `or`, #3610
2626
- Fixes the false positive `WPS330` when alternating unary operators, #3594
27+
- Fixes the false positive `WPS222` for nested conditions, #3630
2728

2829

2930
## 1.6.0

tests/test_visitors/test_ast/test_complexity/test_counts/test_condition_counts.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,33 +45,48 @@
4545
print(1)
4646
"""
4747

48+
# 3 conditions, nested conditions are not counted.
49+
if_with_nested_conditions = """
50+
if (a is None or (func1(a) and b) or (func2(a) and c)):
51+
...
52+
"""
53+
4854
# Real examples:
4955

5056
complex_assignment = """
51-
some = zero and first or (second and last) or default()
57+
some = zero and first or (second and last) or default() or c or d
5258
"""
5359

5460
complex_condition = """
55-
if x == x1 and y == y1 and z == z1 or v == v1 or last():
61+
if x == x1 and y == y1 and z == z1 or v == v1 or last() or to_be() \
62+
or not_to_be():
5663
...
5764
"""
5865

66+
complex_list_comprehension = """
67+
def example(x, y):
68+
return [i for i in range(x) if i % 2 == 0 or i == y or i > 10 or \
69+
y < 4 or i != 0]
70+
"""
71+
5972
complex_while = """
60-
while (x > x1 or y < y1) or (small(z) and v) or last():
73+
while (x > x1 or y < y1) or (small(z) and v) or first() or second() or last():
6174
...
6275
"""
6376

6477
complex_match = """
6578
match some:
66-
case 1 if (x > x1 or y < y1) or (small(z) and v) or last():
79+
case 1 if (x > x1 or y < y1) or (small(z) and v) or first() or \
80+
second() or last():
6781
...
6882
"""
6983

7084
complex_gen_exp = """
7185
(
7286
...
7387
for name in []
74-
if (x > x1 or y < y1) or (small(z) and v) or last()
88+
if (x > x1 or y < y1) or (small(z) and v) or (b() and g()) or \
89+
second() or last()
7590
)
7691
"""
7792

@@ -89,6 +104,7 @@
89104
condition_with_inline_for,
90105
condition_with_simple_inline_for,
91106
while_with_condition,
107+
if_with_nested_conditions,
92108
],
93109
)
94110
def test_module_condition_counts_normal(
@@ -111,6 +127,7 @@ def test_module_condition_counts_normal(
111127
[
112128
complex_assignment,
113129
complex_condition,
130+
complex_list_comprehension,
114131
complex_while,
115132
complex_match,
116133
complex_gen_exp,
@@ -138,6 +155,7 @@ def test_module_condition_real_config(
138155
[
139156
complex_assignment,
140157
complex_condition,
158+
complex_list_comprehension,
141159
complex_while,
142160
complex_match,
143161
complex_gen_exp,

wemake_python_styleguide/visitors/ast/complexity/counts.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,21 @@ def _post_visit(self) -> None:
7878

7979
@final
8080
class ConditionsVisitor(BaseNodeVisitor):
81-
"""Checks booleans for condition counts."""
81+
"""Checks booleans for condition counts.
82+
83+
.. versionchanged:: 1.6.1
84+
Stopped recursive counting of nested ``ast.BoolOp`` nodes.
85+
86+
Example::
87+
88+
# 3 conditions:
89+
if (a is None or (b() and c) or d)``:
90+
pass
91+
92+
:meth:`_count_conditions` returns ``3`` for this example
93+
and evaluating the ``(b() and c)`` as a single condition.
94+
95+
"""
8296

8397
def visit_BoolOp(self, node: ast.BoolOp) -> None:
8498
"""Counts the number of conditions."""
@@ -91,13 +105,7 @@ def visit_Compare(self, node: ast.Compare) -> None:
91105
self.generic_visit(node)
92106

93107
def _count_conditions(self, node: ast.BoolOp) -> int:
94-
counter = 0
95-
for condition in node.values:
96-
if isinstance(condition, ast.BoolOp):
97-
counter += self._count_conditions(condition)
98-
else:
99-
counter += 1
100-
return counter
108+
return len(node.values)
101109

102110
def _check_conditions(self, node: ast.BoolOp) -> None:
103111
conditions_count = self._count_conditions(node)

0 commit comments

Comments
 (0)