Skip to content

Commit 18ae828

Browse files
authored
WPS330: fix false positive when alternating operators (#3614)
1 parent ce23489 commit 18ae828

4 files changed

Lines changed: 24 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Semantic versioning in our case means:
2222
### Bugfixes
2323

2424
- Fixes false positive `WPS366` allowing the use of a single constant in `or`, #3610
25+
- Fixes the false positive `WPS330` when alternating unary operators, #3594
2526

2627
## 1.6.0
2728

tests/test_visitors/test_ast/test_operators/test_useless_operators_before_numbers.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,23 @@ def function_name(param1, param2={0}):
5050
'---5',
5151
'~~5',
5252
'~~~5',
53+
'~~-5',
54+
'~---5',
5355
'(not not 5)',
5456
'(not not None)',
5557
'(not not not True)',
5658
'(not not False)',
5759
],
5860
)
59-
def test_plus_sign_before_numbers(
61+
def test_useless_unary_operator(
6062
assert_errors,
6163
parse_ast_tree,
6264
code,
6365
number,
6466
default_options,
6567
mode,
6668
):
67-
"""Testing that there is no useless plus sign before a number."""
69+
"""Testing that one of the unary operators before a number is useless."""
6870
tree = parse_ast_tree(mode(code.format(number)))
6971

7072
visitor = UselessOperatorsVisitor(default_options, tree=tree)
@@ -84,19 +86,21 @@ def test_plus_sign_before_numbers(
8486
'5',
8587
'-5',
8688
'~5',
89+
'~-~5',
90+
'-~-5',
8791
'(not 5)',
8892
'(not True)',
8993
],
9094
)
91-
def test_plus_sign_before_numbers_valid(
95+
def test_useful_unary_operator(
9296
assert_errors,
9397
parse_ast_tree,
9498
code,
9599
number,
96100
default_options,
97101
mode,
98102
):
99-
"""Testing that there is no useless plus sign before a number."""
103+
"""Testing that there is no useless unary operator before a number."""
100104
tree = parse_ast_tree(mode(code.format(number)))
101105

102106
visitor = UselessOperatorsVisitor(default_options, tree=tree)

wemake_python_styleguide/logic/tree/operators.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,24 @@ def get_parent_ignoring_unary(node: ast.AST) -> ast.AST | None:
3535
node = parent
3636

3737

38-
def count_unary_operator(
38+
def count_consecutive_unary_operator(
3939
node: ast.AST,
4040
operator: type[ast.unaryop],
41-
amount: int = 0,
41+
counter: int = 0,
42+
max_counter: int = 0,
4243
) -> int:
43-
"""Returns amount of unary operators matching input."""
44+
"""Counts the maximum number of consecutive identical unary operators."""
4445
parent = get_parent(node)
45-
if parent is None or not isinstance(parent, ast.UnaryOp):
46-
return amount
46+
if not isinstance(parent, ast.UnaryOp):
47+
return max(counter, max_counter)
48+
4749
if isinstance(parent.op, operator):
48-
return count_unary_operator(parent, operator, amount + 1)
49-
return count_unary_operator(parent, operator, amount)
50+
return count_consecutive_unary_operator(
51+
parent, operator, counter + 1, max_counter
52+
)
53+
if counter > max_counter:
54+
return count_consecutive_unary_operator(parent, operator, 0, counter)
55+
return count_consecutive_unary_operator(parent, operator, 0, max_counter)
5056

5157

5258
def get_reduced_unary_operators(

wemake_python_styleguide/visitors/ast/operators.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from wemake_python_styleguide.logic import walk
88
from wemake_python_styleguide.logic.nodes import get_parent
99
from wemake_python_styleguide.logic.tree.operators import (
10-
count_unary_operator,
10+
count_consecutive_unary_operator,
1111
get_reduced_unary_operators,
1212
unwrap_unary_node,
1313
)
@@ -105,7 +105,7 @@ def visit_AugAssign(self, node: ast.AugAssign) -> None:
105105

106106
def _check_operator_count(self, node: ast.Constant) -> None:
107107
for node_type, limit in self._unary_limits.items():
108-
if count_unary_operator(node, node_type) > limit:
108+
if count_consecutive_unary_operator(node, node_type) > limit:
109109
self.add_violation(
110110
consistency.UselessOperatorsViolation(
111111
node,

0 commit comments

Comments
 (0)