flake8_simplify 0.20.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flake8_simplify/__init__.py +177 -0
- flake8_simplify/constants.py +7 -0
- flake8_simplify/rules/__init__.py +0 -0
- flake8_simplify/rules/ast_assign.py +116 -0
- flake8_simplify/rules/ast_bool_op.py +219 -0
- flake8_simplify/rules/ast_call.py +235 -0
- flake8_simplify/rules/ast_classdef.py +24 -0
- flake8_simplify/rules/ast_compare.py +90 -0
- flake8_simplify/rules/ast_expr.py +103 -0
- flake8_simplify/rules/ast_for.py +207 -0
- flake8_simplify/rules/ast_if.py +515 -0
- flake8_simplify/rules/ast_ifexp.py +68 -0
- flake8_simplify/rules/ast_subscript.py +59 -0
- flake8_simplify/rules/ast_try.py +96 -0
- flake8_simplify/rules/ast_unary_op.py +106 -0
- flake8_simplify/rules/ast_with.py +62 -0
- flake8_simplify/utils.py +247 -0
- flake8_simplify-0.20.0.dist-info/LICENSE +21 -0
- flake8_simplify-0.20.0.dist-info/METADATA +656 -0
- flake8_simplify-0.20.0.dist-info/RECORD +22 -0
- flake8_simplify-0.20.0.dist-info/WHEEL +4 -0
- flake8_simplify-0.20.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Core Library
|
|
2
|
+
import ast
|
|
3
|
+
import logging
|
|
4
|
+
import sys
|
|
5
|
+
from typing import Any, Generator, List, Tuple, Type
|
|
6
|
+
|
|
7
|
+
# First party
|
|
8
|
+
from flake8_simplify.rules.ast_assign import get_sim904, get_sim909
|
|
9
|
+
from flake8_simplify.rules.ast_bool_op import (
|
|
10
|
+
get_sim101,
|
|
11
|
+
get_sim109,
|
|
12
|
+
get_sim220,
|
|
13
|
+
get_sim221,
|
|
14
|
+
get_sim222,
|
|
15
|
+
get_sim223,
|
|
16
|
+
)
|
|
17
|
+
from flake8_simplify.rules.ast_call import (
|
|
18
|
+
get_sim115,
|
|
19
|
+
get_sim901,
|
|
20
|
+
get_sim905,
|
|
21
|
+
get_sim906,
|
|
22
|
+
get_sim910,
|
|
23
|
+
)
|
|
24
|
+
from flake8_simplify.rules.ast_classdef import get_sim120
|
|
25
|
+
from flake8_simplify.rules.ast_compare import get_sim118, get_sim300
|
|
26
|
+
from flake8_simplify.rules.ast_expr import get_sim112
|
|
27
|
+
from flake8_simplify.rules.ast_for import (
|
|
28
|
+
get_sim104,
|
|
29
|
+
get_sim110_sim111,
|
|
30
|
+
get_sim113,
|
|
31
|
+
)
|
|
32
|
+
from flake8_simplify.rules.ast_if import (
|
|
33
|
+
get_sim102,
|
|
34
|
+
get_sim103,
|
|
35
|
+
get_sim108,
|
|
36
|
+
get_sim114,
|
|
37
|
+
get_sim116,
|
|
38
|
+
get_sim401,
|
|
39
|
+
get_sim908,
|
|
40
|
+
)
|
|
41
|
+
from flake8_simplify.rules.ast_ifexp import get_sim210, get_sim211, get_sim212
|
|
42
|
+
from flake8_simplify.rules.ast_subscript import get_sim907
|
|
43
|
+
from flake8_simplify.rules.ast_try import get_sim105, get_sim107
|
|
44
|
+
from flake8_simplify.rules.ast_unary_op import (
|
|
45
|
+
get_sim201,
|
|
46
|
+
get_sim202,
|
|
47
|
+
get_sim203,
|
|
48
|
+
get_sim208,
|
|
49
|
+
)
|
|
50
|
+
from flake8_simplify.rules.ast_with import get_sim117
|
|
51
|
+
from flake8_simplify.utils import Assign, Call, For, If, UnaryOp
|
|
52
|
+
|
|
53
|
+
logger = logging.getLogger(__name__)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
if sys.version_info < (3, 8): # pragma: no cover (<PY38)
|
|
57
|
+
# Third party
|
|
58
|
+
import importlib_metadata
|
|
59
|
+
else: # pragma: no cover (PY38+)
|
|
60
|
+
# Core Library
|
|
61
|
+
import importlib.metadata as importlib_metadata
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class Visitor(ast.NodeVisitor):
|
|
65
|
+
def __init__(self) -> None:
|
|
66
|
+
self.errors: List[Tuple[int, int, str]] = []
|
|
67
|
+
|
|
68
|
+
def visit_Assign(self, node: ast.Assign) -> Any:
|
|
69
|
+
self.errors += get_sim904(node)
|
|
70
|
+
self.errors += get_sim909(Assign(node))
|
|
71
|
+
self.generic_visit(node)
|
|
72
|
+
|
|
73
|
+
def visit_Call(self, node: ast.Call) -> Any:
|
|
74
|
+
self.errors += get_sim115(Call(node))
|
|
75
|
+
self.errors += get_sim901(node)
|
|
76
|
+
self.errors += get_sim905(node)
|
|
77
|
+
self.errors += get_sim906(node)
|
|
78
|
+
self.errors += get_sim910(Call(node))
|
|
79
|
+
self.generic_visit(node)
|
|
80
|
+
|
|
81
|
+
def visit_With(self, node: ast.With) -> Any:
|
|
82
|
+
self.errors += get_sim117(node)
|
|
83
|
+
self.generic_visit(node)
|
|
84
|
+
|
|
85
|
+
def visit_Expr(self, node: ast.Expr) -> None:
|
|
86
|
+
self.errors += get_sim112(node)
|
|
87
|
+
self.generic_visit(node)
|
|
88
|
+
|
|
89
|
+
def visit_BoolOp(self, node: ast.BoolOp) -> None:
|
|
90
|
+
self.errors += get_sim101(node)
|
|
91
|
+
self.errors += get_sim109(node)
|
|
92
|
+
self.errors += get_sim220(node)
|
|
93
|
+
self.errors += get_sim221(node)
|
|
94
|
+
self.errors += get_sim222(node)
|
|
95
|
+
self.errors += get_sim223(node)
|
|
96
|
+
self.generic_visit(node)
|
|
97
|
+
|
|
98
|
+
def visit_If(self, node: ast.If) -> None:
|
|
99
|
+
self.errors += get_sim102(node)
|
|
100
|
+
self.errors += get_sim103(node)
|
|
101
|
+
self.errors += get_sim108(If(node))
|
|
102
|
+
self.errors += get_sim114(node)
|
|
103
|
+
self.errors += get_sim116(node)
|
|
104
|
+
self.errors += get_sim908(node)
|
|
105
|
+
self.errors += get_sim401(node)
|
|
106
|
+
self.generic_visit(node)
|
|
107
|
+
|
|
108
|
+
def visit_For(self, node: ast.For) -> None:
|
|
109
|
+
self.errors += get_sim104(node)
|
|
110
|
+
self.errors += get_sim110_sim111(node)
|
|
111
|
+
self.errors += get_sim113(For(node))
|
|
112
|
+
self.generic_visit(node)
|
|
113
|
+
|
|
114
|
+
def visit_Subscript(self, node: ast.Subscript) -> None:
|
|
115
|
+
self.errors += get_sim907(node)
|
|
116
|
+
self.generic_visit(node)
|
|
117
|
+
|
|
118
|
+
def visit_Try(self, node: ast.Try) -> None:
|
|
119
|
+
self.errors += get_sim105(node)
|
|
120
|
+
self.errors += get_sim107(node)
|
|
121
|
+
self.generic_visit(node)
|
|
122
|
+
|
|
123
|
+
def visit_UnaryOp(self, node_v: ast.UnaryOp) -> None:
|
|
124
|
+
node = UnaryOp(node_v)
|
|
125
|
+
self.errors += get_sim201(node)
|
|
126
|
+
self.errors += get_sim202(node)
|
|
127
|
+
self.errors += get_sim203(node)
|
|
128
|
+
self.errors += get_sim208(node)
|
|
129
|
+
self.generic_visit(node)
|
|
130
|
+
|
|
131
|
+
def visit_IfExp(self, node: ast.IfExp) -> None:
|
|
132
|
+
self.errors += get_sim210(node)
|
|
133
|
+
self.errors += get_sim211(node)
|
|
134
|
+
self.errors += get_sim212(node)
|
|
135
|
+
self.generic_visit(node)
|
|
136
|
+
|
|
137
|
+
def visit_Compare(self, node: ast.Compare) -> None:
|
|
138
|
+
self.errors += get_sim118(node)
|
|
139
|
+
self.errors += get_sim300(node)
|
|
140
|
+
self.generic_visit(node)
|
|
141
|
+
|
|
142
|
+
def visit_ClassDef(self, node: ast.ClassDef) -> None:
|
|
143
|
+
self.errors += get_sim120(node)
|
|
144
|
+
self.generic_visit(node)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class Plugin:
|
|
148
|
+
name = __name__
|
|
149
|
+
version = importlib_metadata.version(__name__) # type: ignore
|
|
150
|
+
|
|
151
|
+
def __init__(self, tree: ast.AST):
|
|
152
|
+
self._tree = tree
|
|
153
|
+
|
|
154
|
+
def run(self) -> Generator[Tuple[int, int, str, Type[Any]], None, None]:
|
|
155
|
+
visitor = Visitor()
|
|
156
|
+
|
|
157
|
+
# Add parent
|
|
158
|
+
add_meta(self._tree)
|
|
159
|
+
visitor.visit(self._tree)
|
|
160
|
+
|
|
161
|
+
for line, col, msg in visitor.errors:
|
|
162
|
+
yield line, col, msg, type(self)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def add_meta(root: ast.AST, level: int = 0) -> None:
|
|
166
|
+
previous_sibling = None
|
|
167
|
+
for node in ast.iter_child_nodes(root):
|
|
168
|
+
if level == 0:
|
|
169
|
+
node.parent = root # type: ignore
|
|
170
|
+
node.previous_sibling = previous_sibling # type: ignore
|
|
171
|
+
node.next_sibling = None # type: ignore
|
|
172
|
+
if previous_sibling:
|
|
173
|
+
node.previous_sibling.next_sibling = node # type: ignore
|
|
174
|
+
previous_sibling = node
|
|
175
|
+
for child in ast.iter_child_nodes(node):
|
|
176
|
+
child.parent = node # type: ignore
|
|
177
|
+
add_meta(node, level=level + 1)
|
|
File without changes
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Core Library
|
|
2
|
+
import ast
|
|
3
|
+
from typing import List, Tuple
|
|
4
|
+
|
|
5
|
+
# First party
|
|
6
|
+
from flake8_simplify.utils import Assign, expression_uses_variable, to_source
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_sim904(node: ast.Assign) -> List[Tuple[int, int, str]]:
|
|
10
|
+
"""
|
|
11
|
+
Assign values to dictionary directly at initialization.
|
|
12
|
+
|
|
13
|
+
Example
|
|
14
|
+
-------
|
|
15
|
+
Code:
|
|
16
|
+
# Bad
|
|
17
|
+
a = { }
|
|
18
|
+
a['b] = 'c'
|
|
19
|
+
|
|
20
|
+
# Good
|
|
21
|
+
a = {'b': 'c'}
|
|
22
|
+
Bad AST:
|
|
23
|
+
[
|
|
24
|
+
Assign(
|
|
25
|
+
targets=[Name(id='a', ctx=Store())],
|
|
26
|
+
value=Dict(keys=[], values=[]),
|
|
27
|
+
type_comment=None,
|
|
28
|
+
),
|
|
29
|
+
Assign(
|
|
30
|
+
targets=[
|
|
31
|
+
Subscript(
|
|
32
|
+
value=Name(id='a', ctx=Load()),
|
|
33
|
+
slice=Constant(value='b', kind=None),
|
|
34
|
+
ctx=Store(),
|
|
35
|
+
),
|
|
36
|
+
],
|
|
37
|
+
value=Constant(value='c', kind=None),
|
|
38
|
+
type_comment=None,
|
|
39
|
+
),
|
|
40
|
+
]
|
|
41
|
+
"""
|
|
42
|
+
RULE = "SIM904 Initialize dictionary '{dict_name}' directly"
|
|
43
|
+
errors: List[Tuple[int, int, str]] = []
|
|
44
|
+
n2 = node.next_sibling # type: ignore
|
|
45
|
+
if not (
|
|
46
|
+
isinstance(node.value, ast.Dict)
|
|
47
|
+
and isinstance(n2, ast.Assign)
|
|
48
|
+
and len(n2.targets) == 1
|
|
49
|
+
and len(node.targets) == 1
|
|
50
|
+
and isinstance(n2.targets[0], ast.Subscript)
|
|
51
|
+
and isinstance(n2.targets[0].value, ast.Name)
|
|
52
|
+
and isinstance(node.targets[0], ast.Name)
|
|
53
|
+
and n2.targets[0].value.id == node.targets[0].id
|
|
54
|
+
):
|
|
55
|
+
return errors
|
|
56
|
+
|
|
57
|
+
dict_name = to_source(node.targets[0])
|
|
58
|
+
# Capture cases where the assigned value uses another dictionary value
|
|
59
|
+
if expression_uses_variable(n2.value, dict_name):
|
|
60
|
+
return errors
|
|
61
|
+
|
|
62
|
+
errors.append(
|
|
63
|
+
(
|
|
64
|
+
node.lineno,
|
|
65
|
+
node.col_offset,
|
|
66
|
+
RULE.format(dict_name=dict_name),
|
|
67
|
+
)
|
|
68
|
+
)
|
|
69
|
+
return errors
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def get_sim909(node: Assign) -> List[Tuple[int, int, str]]:
|
|
73
|
+
"""
|
|
74
|
+
Avoid reflexive assignments
|
|
75
|
+
|
|
76
|
+
Example
|
|
77
|
+
-------
|
|
78
|
+
Code:
|
|
79
|
+
# Bad
|
|
80
|
+
foo = foo
|
|
81
|
+
|
|
82
|
+
# Good: Just remove them
|
|
83
|
+
Bad AST:
|
|
84
|
+
[
|
|
85
|
+
Assign(
|
|
86
|
+
targets=[Name(id='foo', ctx=Store())],
|
|
87
|
+
value=Name(id='foo', ctx=Load()),
|
|
88
|
+
type_comment=None,
|
|
89
|
+
),
|
|
90
|
+
]
|
|
91
|
+
"""
|
|
92
|
+
RULE = "SIM909 Remove reflexive assignment '{code}'"
|
|
93
|
+
errors: List[Tuple[int, int, str]] = []
|
|
94
|
+
|
|
95
|
+
names = []
|
|
96
|
+
if isinstance(node.value, (ast.Name, ast.Subscript, ast.Tuple)):
|
|
97
|
+
names.append(to_source(node.value))
|
|
98
|
+
for target in node.targets:
|
|
99
|
+
names.append(to_source(target))
|
|
100
|
+
|
|
101
|
+
if len(names) == len(set(names)):
|
|
102
|
+
return errors
|
|
103
|
+
|
|
104
|
+
if isinstance(node.parent, ast.ClassDef):
|
|
105
|
+
return errors
|
|
106
|
+
|
|
107
|
+
code = to_source(node.orig)
|
|
108
|
+
|
|
109
|
+
errors.append(
|
|
110
|
+
(
|
|
111
|
+
node.lineno,
|
|
112
|
+
node.col_offset,
|
|
113
|
+
RULE.format(code=code),
|
|
114
|
+
)
|
|
115
|
+
)
|
|
116
|
+
return errors
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Core Library
|
|
2
|
+
import ast
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from typing import Dict, List, Tuple
|
|
5
|
+
|
|
6
|
+
# First party
|
|
7
|
+
from flake8_simplify.constants import BOOL_CONST_TYPES
|
|
8
|
+
from flake8_simplify.utils import (
|
|
9
|
+
_get_duplicated_isinstance_call_by_node,
|
|
10
|
+
is_same_expression,
|
|
11
|
+
to_source,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_sim101(
|
|
16
|
+
node: ast.BoolOp,
|
|
17
|
+
) -> List[Tuple[int, int, str]]:
|
|
18
|
+
"""Get a positions where the duplicate isinstance problem appears."""
|
|
19
|
+
errors: List[Tuple[int, int, str]] = []
|
|
20
|
+
if not isinstance(node.op, ast.Or):
|
|
21
|
+
return errors
|
|
22
|
+
|
|
23
|
+
RULE = (
|
|
24
|
+
"SIM101 Multiple isinstance-calls which can be merged into a single "
|
|
25
|
+
"call for variable '{var}'"
|
|
26
|
+
)
|
|
27
|
+
for var in _get_duplicated_isinstance_call_by_node(node):
|
|
28
|
+
errors.append((node.lineno, node.col_offset, RULE.format(var=var)))
|
|
29
|
+
return errors
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_sim109(node: ast.BoolOp) -> List[Tuple[int, int, str]]:
|
|
33
|
+
"""
|
|
34
|
+
Check if multiple equalities with the same value are combined via "or".
|
|
35
|
+
|
|
36
|
+
BoolOp(
|
|
37
|
+
op=Or(),
|
|
38
|
+
values=[
|
|
39
|
+
Compare(
|
|
40
|
+
left=Name(id='a', ctx=Load()),
|
|
41
|
+
ops=[Eq()],
|
|
42
|
+
comparators=[Name(id='b', ctx=Load())],
|
|
43
|
+
),
|
|
44
|
+
Compare(
|
|
45
|
+
left=Name(id='a', ctx=Load()),
|
|
46
|
+
ops=[Eq()],
|
|
47
|
+
comparators=[Name(id='c', ctx=Load())],
|
|
48
|
+
),
|
|
49
|
+
],
|
|
50
|
+
)
|
|
51
|
+
"""
|
|
52
|
+
errors: List[Tuple[int, int, str]] = []
|
|
53
|
+
if not isinstance(node.op, ast.Or):
|
|
54
|
+
return errors
|
|
55
|
+
equalities = [
|
|
56
|
+
value
|
|
57
|
+
for value in node.values
|
|
58
|
+
if isinstance(value, ast.Compare)
|
|
59
|
+
and len(value.ops) == 1
|
|
60
|
+
and isinstance(value.ops[0], ast.Eq)
|
|
61
|
+
]
|
|
62
|
+
id2vals: Dict[str, List[ast.Name]] = defaultdict(list)
|
|
63
|
+
for eq in equalities:
|
|
64
|
+
if (
|
|
65
|
+
isinstance(eq.left, ast.Name)
|
|
66
|
+
and len(eq.comparators) == 1
|
|
67
|
+
and isinstance(eq.comparators[0], ast.Name)
|
|
68
|
+
):
|
|
69
|
+
id2vals[eq.left.id].append(eq.comparators[0])
|
|
70
|
+
RULE = "SIM109 Use '{value} in {values}' instead of '{or_op}'"
|
|
71
|
+
for value, values in id2vals.items():
|
|
72
|
+
if len(values) == 1:
|
|
73
|
+
continue
|
|
74
|
+
errors.append(
|
|
75
|
+
(
|
|
76
|
+
node.lineno,
|
|
77
|
+
node.col_offset,
|
|
78
|
+
RULE.format(
|
|
79
|
+
or_op=to_source(node),
|
|
80
|
+
value=value,
|
|
81
|
+
values=f"({to_source(ast.Tuple(elts=values))})",
|
|
82
|
+
),
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
return errors
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_sim220(node: ast.BoolOp) -> List[Tuple[int, int, str]]:
|
|
89
|
+
"""
|
|
90
|
+
Get a list of all calls of the type "a and not a".
|
|
91
|
+
|
|
92
|
+
BoolOp(
|
|
93
|
+
op=And(),
|
|
94
|
+
values=[
|
|
95
|
+
Name(id='a', ctx=Load()),
|
|
96
|
+
UnaryOp(
|
|
97
|
+
op=Not(),
|
|
98
|
+
operand=Name(id='a', ctx=Load()),
|
|
99
|
+
),
|
|
100
|
+
],
|
|
101
|
+
)
|
|
102
|
+
"""
|
|
103
|
+
errors: List[Tuple[int, int, str]] = []
|
|
104
|
+
if not (isinstance(node.op, ast.And) and len(node.values) >= 2):
|
|
105
|
+
return errors
|
|
106
|
+
# We have a boolean And. Let's make sure there is two times the same
|
|
107
|
+
# expression, but once with a "not"
|
|
108
|
+
negated_expressions = []
|
|
109
|
+
non_negated_expressions = []
|
|
110
|
+
for exp in node.values:
|
|
111
|
+
if isinstance(exp, ast.UnaryOp) and isinstance(exp.op, ast.Not):
|
|
112
|
+
negated_expressions.append(exp.operand)
|
|
113
|
+
else:
|
|
114
|
+
non_negated_expressions.append(exp)
|
|
115
|
+
if len(negated_expressions) == 0:
|
|
116
|
+
return errors
|
|
117
|
+
|
|
118
|
+
RULE = "SIM220 Use 'False' instead of '{a} and not {a}'"
|
|
119
|
+
for negated_expression in negated_expressions:
|
|
120
|
+
for non_negated_expression in non_negated_expressions:
|
|
121
|
+
if is_same_expression(negated_expression, non_negated_expression):
|
|
122
|
+
a = to_source(negated_expression)
|
|
123
|
+
errors.append((node.lineno, node.col_offset, RULE.format(a=a)))
|
|
124
|
+
return errors
|
|
125
|
+
return errors
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def get_sim221(node: ast.BoolOp) -> List[Tuple[int, int, str]]:
|
|
129
|
+
"""
|
|
130
|
+
Get a list of all calls of the type "a or not a".
|
|
131
|
+
|
|
132
|
+
BoolOp(
|
|
133
|
+
op=Or(),
|
|
134
|
+
values=[
|
|
135
|
+
Name(id='a', ctx=Load()),
|
|
136
|
+
UnaryOp(
|
|
137
|
+
op=Not(),
|
|
138
|
+
operand=Name(id='a', ctx=Load()),
|
|
139
|
+
),
|
|
140
|
+
],
|
|
141
|
+
)
|
|
142
|
+
"""
|
|
143
|
+
errors: List[Tuple[int, int, str]] = []
|
|
144
|
+
if not (isinstance(node.op, ast.Or) and len(node.values) >= 2):
|
|
145
|
+
return errors
|
|
146
|
+
# We have a boolean OR. Let's make sure there is two times the same
|
|
147
|
+
# expression, but once with a "not"
|
|
148
|
+
negated_expressions = []
|
|
149
|
+
non_negated_expressions = []
|
|
150
|
+
for exp in node.values:
|
|
151
|
+
if isinstance(exp, ast.UnaryOp) and isinstance(exp.op, ast.Not):
|
|
152
|
+
negated_expressions.append(exp.operand)
|
|
153
|
+
else:
|
|
154
|
+
non_negated_expressions.append(exp)
|
|
155
|
+
if len(negated_expressions) == 0:
|
|
156
|
+
return errors
|
|
157
|
+
|
|
158
|
+
RULE = "SIM221 Use 'True' instead of '{a} or not {a}'"
|
|
159
|
+
for negated_expression in negated_expressions:
|
|
160
|
+
for non_negated_expression in non_negated_expressions:
|
|
161
|
+
if is_same_expression(negated_expression, non_negated_expression):
|
|
162
|
+
a = to_source(negated_expression)
|
|
163
|
+
errors.append((node.lineno, node.col_offset, RULE.format(a=a)))
|
|
164
|
+
return errors
|
|
165
|
+
return errors
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def get_sim222(node: ast.BoolOp) -> List[Tuple[int, int, str]]:
|
|
169
|
+
"""
|
|
170
|
+
Get a list of all calls of the type "... or True".
|
|
171
|
+
|
|
172
|
+
BoolOp(
|
|
173
|
+
op=Or(),
|
|
174
|
+
values=[
|
|
175
|
+
Name(id='a', ctx=Load()),
|
|
176
|
+
UnaryOp(
|
|
177
|
+
op=Not(),
|
|
178
|
+
operand=Name(id='a', ctx=Load()),
|
|
179
|
+
),
|
|
180
|
+
],
|
|
181
|
+
)
|
|
182
|
+
"""
|
|
183
|
+
errors: List[Tuple[int, int, str]] = []
|
|
184
|
+
if not (isinstance(node.op, ast.Or)):
|
|
185
|
+
return errors
|
|
186
|
+
|
|
187
|
+
RULE = "SIM222 Use 'True' instead of '... or True'"
|
|
188
|
+
for exp in node.values:
|
|
189
|
+
if isinstance(exp, BOOL_CONST_TYPES) and exp.value is True:
|
|
190
|
+
errors.append((node.lineno, node.col_offset, RULE))
|
|
191
|
+
return errors
|
|
192
|
+
return errors
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def get_sim223(node: ast.BoolOp) -> List[Tuple[int, int, str]]:
|
|
196
|
+
"""
|
|
197
|
+
Get a list of all calls of the type "... and False".
|
|
198
|
+
|
|
199
|
+
BoolOp(
|
|
200
|
+
op=And(),
|
|
201
|
+
values=[
|
|
202
|
+
Name(id='a', ctx=Load()),
|
|
203
|
+
UnaryOp(
|
|
204
|
+
op=Not(),
|
|
205
|
+
operand=Name(id='a', ctx=Load()),
|
|
206
|
+
),
|
|
207
|
+
],
|
|
208
|
+
)
|
|
209
|
+
"""
|
|
210
|
+
errors: List[Tuple[int, int, str]] = []
|
|
211
|
+
if not (isinstance(node.op, ast.And)):
|
|
212
|
+
return errors
|
|
213
|
+
|
|
214
|
+
RULE = "SIM223 Use 'False' instead of '... and False'"
|
|
215
|
+
for exp in node.values:
|
|
216
|
+
if isinstance(exp, BOOL_CONST_TYPES) and exp.value is False:
|
|
217
|
+
errors.append((node.lineno, node.col_offset, RULE))
|
|
218
|
+
return errors
|
|
219
|
+
return errors
|