Skip to content

Commit 71ac99b

Browse files
committed
Fix bug causing false positives for PLU002
When an inner class or function was immediately followed by a `return`, false positives could occur because other linters and formatters may require a specific number of blanks after classes and functions. One example is Black.
1 parent 112d65c commit 71ac99b

File tree

5 files changed

+72
-10
lines changed

5 files changed

+72
-10
lines changed

flake8_plus/visitors/base_visitor.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Base class for visitors used in Flake8-plus."""
22
import ast
3+
from typing import Any
34

45
from ..config import Config
56
from ..exceptions import MultipleStatementsError
@@ -20,6 +21,21 @@ def __init__(self, lines: list[str], config: Config):
2021
self.problems: list[Problem] = []
2122
self._lines = lines
2223
self.config = config
24+
self._previous_node = None
25+
26+
def visit(self, node: ast.AST) -> Any:
27+
"""
28+
Visit an `AST` instance.
29+
30+
Args:
31+
node (ast.AST): The abstract syntax tree to visit.
32+
33+
Returns:
34+
Any: The result of calling `visit` on the super class.
35+
"""
36+
result = super().visit(node)
37+
self._previous_node = node
38+
return result
2339

2440
def compute_blanks_before(self, node: ast.AST) -> int:
2541
"""

flake8_plus/visitors/plu002_visitor.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,21 @@ def visit_Return(self, node: ast.Return) -> Any:
4949
Any: The result of calling `generic_visit`.
5050
"""
5151
# pylint: disable=invalid-name
52+
if not isinstance(self._previous_node, ast.FunctionDef | ast.ClassDef):
53+
self._process_node(node)
54+
return self.generic_visit(node)
55+
56+
def _process_node(self, node: ast.Return):
5257
try:
5358
actual = self.compute_blanks_before(node)
54-
if actual != self.config.blanks_before_return:
55-
problem = PLU002Problem(
56-
node.lineno,
57-
node.col_offset,
58-
actual,
59-
self.config.blanks_before_return,
60-
)
61-
self.problems.append(problem)
6259
except MultipleStatementsError:
63-
pass
64-
return self.generic_visit(node)
60+
return
61+
62+
if actual != self.config.blanks_before_return:
63+
problem = PLU002Problem(
64+
node.lineno,
65+
node.col_offset,
66+
actual,
67+
self.config.blanks_before_return,
68+
)
69+
self.problems.append(problem)

tests/case_files/plu002/cases.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,32 @@
1212
}
1313
]
1414
},
15+
{
16+
"filename": "inner_class.py",
17+
"cases": [
18+
{
19+
"expectation": { "blanks_expected": 0 },
20+
"problems": []
21+
},
22+
{
23+
"expectation": { "blanks_expected": 1 },
24+
"problems": []
25+
}
26+
]
27+
},
28+
{
29+
"filename": "inner_function.py",
30+
"cases": [
31+
{
32+
"expectation": { "blanks_expected": 0 },
33+
"problems": []
34+
},
35+
{
36+
"expectation": { "blanks_expected": 1 },
37+
"problems": [{ "line_number": 7, "col_offset": 12, "blanks_actual": 0 }]
38+
}
39+
]
40+
},
1541
{
1642
"filename": "no_blanks.py",
1743
"cases": [
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class SomeClass:
2+
def some_func(self) -> type:
3+
class SomeInnerClass:
4+
pass
5+
6+
return SomeInnerClass
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from typing import Callable
2+
3+
4+
class SomeClass:
5+
def some_func(self) -> Callable[..., int]:
6+
def inner_func() -> int:
7+
return 27
8+
9+
return inner_func

0 commit comments

Comments
 (0)