Skip to content

Commit 6736e6f

Browse files
committed
REFINE VARIABLE NAMING AND CHECK LOGIC IN FLAKE8 PLUGIN
- Rename loop variables for clarity across multiple files - Improve Protocol inheritance detection in final class check - Update violation description for COP011 to be more precise - Remove unused import and inline constant in function verb check - Adjust temp var check to handle AnnAssign nodes - Add 'cache' to verb prefixes whitelist - Delete redundant test file for COP011 logic
1 parent f83118a commit 6736e6f

11 files changed

Lines changed: 196 additions & 218 deletions

File tree

src/community_of_python_flake8_plugin/checks/final_class.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import ast
33
import typing
44

5-
from community_of_python_flake8_plugin.constants import FINAL_CLASS_EXCLUDED_BASES
65
from community_of_python_flake8_plugin.utils import check_inherits_from_bases
76
from community_of_python_flake8_plugin.violation_codes import ViolationCodes
87
from community_of_python_flake8_plugin.violations import Violation
@@ -27,13 +26,18 @@ def is_protocol_class(class_node: ast.ClassDef) -> bool:
2726
# Check for attributed Protocol reference: class MyClass(typing.Protocol):
2827
if isinstance(one_base, ast.Attribute) and one_base.attr == "Protocol":
2928
return True
29+
# Check for subscripted Protocol reference: class MyClass(Protocol[SomeType]):
30+
if isinstance(one_base, ast.Subscript):
31+
if isinstance(one_base.value, ast.Name) and one_base.value.id == "Protocol":
32+
return True
33+
if isinstance(one_base.value, ast.Attribute) and one_base.value.attr == "Protocol":
34+
return True
3035
return False
3136

3237

3338
def is_model_factory_class(class_node: ast.ClassDef) -> bool:
3439
"""Check if the class inherits from ModelFactory or SQLAlchemyFactory."""
35-
model_factory_bases: typing.Final = {"ModelFactory", "SQLAlchemyFactory"}
36-
return check_inherits_from_bases(class_node, model_factory_bases)
40+
return check_inherits_from_bases(class_node, {"ModelFactory", "SQLAlchemyFactory"})
3741

3842

3943
@typing.final
@@ -47,11 +51,7 @@ def visit_ClassDef(self, ast_node: ast.ClassDef) -> None:
4751

4852
def _check_final_decorator(self, ast_node: ast.ClassDef) -> None:
4953
# Skip Protocol classes, test classes, and ModelFactory classes
50-
if (
51-
is_protocol_class(ast_node)
52-
or ast_node.name.startswith("Test")
53-
or is_model_factory_class(ast_node)
54-
):
54+
if is_protocol_class(ast_node) or ast_node.name.startswith("Test") or is_model_factory_class(ast_node):
5555
return
5656

5757
if not contains_final_decorator(ast_node):

src/community_of_python_flake8_plugin/checks/function_verb.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ def check_is_ignored_name(identifier: str) -> bool:
1717

1818

1919
def check_is_verb_name(identifier: str) -> bool:
20-
return any(identifier == verb_name or identifier.startswith(f"{verb_name}_") for verb_name in VERB_PREFIXES)
20+
return any(
21+
identifier == one_verb_name or identifier.startswith(f"{one_verb_name}_") for one_verb_name in VERB_PREFIXES
22+
)
2123

2224

2325
def check_is_property(function_node: ast.AST) -> bool:
2426
if not isinstance(function_node, (ast.FunctionDef, ast.AsyncFunctionDef)):
2527
return False
26-
return any(check_is_property_decorator(decorator) for decorator in function_node.decorator_list) # noqa: COP011
28+
return any(check_is_property_decorator(one_decorator) for one_decorator in function_node.decorator_list) # noqa: COP011
2729

2830

2931
def check_is_property_decorator(decorator: ast.expr) -> bool: # noqa: PLR0911
@@ -56,7 +58,7 @@ def check_is_property_decorator(decorator: ast.expr) -> bool: # noqa: PLR0911
5658
def check_is_pytest_fixture(function_node: ast.AST) -> bool:
5759
if not isinstance(function_node, (ast.FunctionDef, ast.AsyncFunctionDef)):
5860
return False
59-
return any(check_is_fixture_decorator(decorator) for decorator in function_node.decorator_list) # noqa: COP011
61+
return any(check_is_fixture_decorator(one_decorator) for one_decorator in function_node.decorator_list) # noqa: COP011
6062

6163

6264
def check_is_fixture_decorator(decorator: ast.expr) -> bool:

src/community_of_python_flake8_plugin/checks/mapping_proxy.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ def __init__(self, syntax_tree: ast.AST) -> None: # noqa: ARG002
7171
self.violations: list[Violation] = []
7272

7373
def visit_Module(self, ast_node: ast.Module) -> None:
74-
for statement in ast_node.body:
75-
if isinstance(statement, (ast.Assign, ast.AnnAssign)):
76-
self._check_mapping_assignment(statement)
74+
for one_statement in ast_node.body:
75+
if isinstance(one_statement, (ast.Assign, ast.AnnAssign)):
76+
self._check_mapping_assignment(one_statement)
7777
self.generic_visit(ast_node)
7878

7979
def _check_mapping_assignment(self, ast_node: ast.Assign | ast.AnnAssign) -> None:
@@ -99,8 +99,8 @@ def _check_mapping_assignment(self, ast_node: ast.Assign | ast.AnnAssign) -> Non
9999
# Only check module-level assignments (no parent function/class)
100100
if assigned_value is not None and isinstance(assigned_value, ast.Dict) and assignment_targets:
101101
# Check if this is a module-level assignment
102-
for target in assignment_targets: # noqa: COP011
103-
if isinstance(target, ast.Name):
102+
for one_target in assignment_targets: # noqa: COP011
103+
if isinstance(one_target, ast.Name):
104104
self.violations.append(
105105
Violation(
106106
line_number=ast_node.lineno,

src/community_of_python_flake8_plugin/checks/name_length.py

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
import typing
44

55
from community_of_python_flake8_plugin.constants import FINAL_CLASS_EXCLUDED_BASES, MIN_NAME_LENGTH
6-
from community_of_python_flake8_plugin.utils import check_inherits_from_bases, find_parent_class_definition, find_parent_function_definition
6+
from community_of_python_flake8_plugin.utils import (
7+
check_inherits_from_bases,
8+
find_parent_class_definition,
9+
find_parent_function_definition,
10+
)
711
from community_of_python_flake8_plugin.violation_codes import ViolationCodes
812
from community_of_python_flake8_plugin.violations import Violation
913

@@ -33,7 +37,7 @@ def check_is_whitelisted_annotation(annotation: ast.expr | None) -> bool:
3337
def check_is_pytest_fixture(ast_node: ast.AST) -> bool:
3438
if not isinstance(ast_node, (ast.FunctionDef, ast.AsyncFunctionDef)):
3539
return False
36-
return any(check_is_fixture_decorator(decorator) for decorator in ast_node.decorator_list) # noqa: COP011
40+
return any(check_is_fixture_decorator(one_decorator) for one_decorator in ast_node.decorator_list) # noqa: COP011
3741

3842

3943
def check_is_fixture_decorator(decorator: ast.expr) -> bool:
@@ -58,9 +62,11 @@ def visit_AnnAssign(self, ast_node: ast.AnnAssign) -> None:
5862
self.generic_visit(ast_node)
5963

6064
def visit_Assign(self, ast_node: ast.Assign) -> None:
61-
for target in ast_node.targets:
62-
if isinstance(target, ast.Name):
63-
self.validate_name_length(target.id, ast_node, find_parent_class_definition(self.syntax_tree, ast_node))
65+
for one_target in ast_node.targets:
66+
if isinstance(one_target, ast.Name):
67+
self.validate_name_length(
68+
one_target.id, ast_node, find_parent_class_definition(self.syntax_tree, ast_node)
69+
)
6470
self.generic_visit(ast_node)
6571

6672
def visit_FunctionDef(self, ast_node: ast.FunctionDef) -> None:
@@ -79,28 +85,28 @@ def visit_ClassDef(self, ast_node: ast.ClassDef) -> None:
7985
self.generic_visit(ast_node)
8086

8187
def visit_ListComp(self, ast_node: ast.ListComp) -> None:
82-
for comprehension in ast_node.generators:
83-
self._validate_comprehension_target(comprehension.target)
88+
for one_comprehension in ast_node.generators:
89+
self._validate_comprehension_target(one_comprehension.target)
8490
self.generic_visit(ast_node)
8591

8692
def visit_SetComp(self, ast_node: ast.SetComp) -> None:
87-
for comprehension in ast_node.generators:
88-
self._validate_comprehension_target(comprehension.target)
93+
for one_comprehension in ast_node.generators:
94+
self._validate_comprehension_target(one_comprehension.target)
8995
self.generic_visit(ast_node)
9096

9197
def visit_DictComp(self, ast_node: ast.DictComp) -> None:
92-
for comprehension in ast_node.generators:
93-
self._validate_comprehension_target(comprehension.target)
98+
for one_comprehension in ast_node.generators:
99+
self._validate_comprehension_target(one_comprehension.target)
94100
self.generic_visit(ast_node)
95101

96102
def visit_Lambda(self, ast_node: ast.Lambda) -> None:
97103
self._validate_function_args(ast_node.args)
98104
self.generic_visit(ast_node)
99105

100106
def visit_With(self, ast_node: ast.With) -> None:
101-
for item in ast_node.items:
102-
if item.optional_vars is not None:
103-
self._validate_with_target(item.optional_vars)
107+
for one_item in ast_node.items:
108+
if one_item.optional_vars is not None:
109+
self._validate_with_target(one_item.optional_vars)
104110
self.generic_visit(ast_node)
105111

106112
def visit_ExceptHandler(self, ast_node: ast.ExceptHandler) -> None:
@@ -109,18 +115,18 @@ def visit_ExceptHandler(self, ast_node: ast.ExceptHandler) -> None:
109115
self.generic_visit(ast_node)
110116

111117
def visit_GeneratorExp(self, ast_node: ast.GeneratorExp) -> None:
112-
for comprehension in ast_node.generators:
113-
self._validate_comprehension_target(comprehension.target)
118+
for one_comprehension in ast_node.generators:
119+
self._validate_comprehension_target(one_comprehension.target)
114120
self.generic_visit(ast_node)
115121

116122
def _validate_function_args(self, arguments_node: ast.arguments) -> None:
117123
# Process all argument types
118-
for argument in arguments_node.posonlyargs:
119-
self._validate_argument_name_length(argument)
120-
for argument in arguments_node.args:
121-
self._validate_argument_name_length(argument)
122-
for argument in arguments_node.kwonlyargs:
123-
self._validate_argument_name_length(argument)
124+
for one_argument in arguments_node.posonlyargs:
125+
self._validate_argument_name_length(one_argument)
126+
for one_argument in arguments_node.args:
127+
self._validate_argument_name_length(one_argument)
128+
for one_argument in arguments_node.kwonlyargs:
129+
self._validate_argument_name_length(one_argument)
124130

125131
if arguments_node.vararg is not None:
126132
self._validate_argument_name_length(arguments_node.vararg)
@@ -157,8 +163,8 @@ def _validate_comprehension_target(self, comprehension_target: ast.expr) -> None
157163
)
158164
elif isinstance(comprehension_target, ast.Tuple):
159165
# Handle tuple unpacking in comprehensions like [(a, b) for a, b in pairs]
160-
for elt in comprehension_target.elts:
161-
self._validate_comprehension_target(elt)
166+
for one_elt in comprehension_target.elts:
167+
self._validate_comprehension_target(one_elt)
162168

163169
def _validate_with_target(self, target_node: ast.expr) -> None:
164170
if isinstance(target_node, ast.Name):
@@ -173,8 +179,8 @@ def _validate_with_target(self, target_node: ast.expr) -> None:
173179
)
174180
elif isinstance(target_node, ast.Tuple):
175181
# Handle tuple unpacking in with statements like with open(f1) as f1, open(f2) as f2:
176-
for elt in target_node.elts:
177-
self._validate_with_target(elt)
182+
for one_elt in target_node.elts:
183+
self._validate_with_target(one_elt)
178184

179185
def _validate_except_target(self, ast_node: ast.ExceptHandler) -> None:
180186
# For except targets, we'll treat them as variables
@@ -205,19 +211,17 @@ def validate_name_length(self, identifier: str, ast_node: ast.stmt, parent_class
205211

206212
if len(identifier) < MIN_NAME_LENGTH:
207213
# Determine if this is an attribute (inside a class but not in a method) or variable
208-
parent_function = find_parent_function_definition(self.syntax_tree, ast_node)
209-
214+
parent_function: typing.Final = find_parent_function_definition(self.syntax_tree, ast_node)
215+
210216
# It's an attribute only if it's in a class but NOT in a function/method
211-
is_attribute = parent_class is not None and parent_function is None
212-
217+
is_attribute: typing.Final = parent_class is not None and parent_function is None
218+
213219
self.violations.append(
214220
Violation(
215221
line_number=ast_node.lineno,
216222
column_number=ast_node.col_offset,
217223
violation_code=(
218-
ViolationCodes.ATTRIBUTE_NAME_LENGTH
219-
if is_attribute
220-
else ViolationCodes.VARIABLE_NAME_LENGTH
224+
ViolationCodes.ATTRIBUTE_NAME_LENGTH if is_attribute else ViolationCodes.VARIABLE_NAME_LENGTH
221225
),
222226
)
223227
)
@@ -245,12 +249,12 @@ def validate_function_name(
245249

246250
def validate_function_args(self, ast_node: ast.FunctionDef | ast.AsyncFunctionDef) -> None:
247251
# Process all argument types
248-
for argument in ast_node.args.posonlyargs:
249-
self.validate_argument_name_length(argument)
250-
for argument in ast_node.args.args:
251-
self.validate_argument_name_length(argument)
252-
for argument in ast_node.args.kwonlyargs:
253-
self.validate_argument_name_length(argument)
252+
for one_argument in ast_node.args.posonlyargs:
253+
self.validate_argument_name_length(one_argument)
254+
for one_argument in ast_node.args.args:
255+
self.validate_argument_name_length(one_argument)
256+
for one_argument in ast_node.args.kwonlyargs:
257+
self.validate_argument_name_length(one_argument)
254258

255259
if ast_node.args.vararg is not None:
256260
self.validate_argument_name_length(ast_node.args.vararg)

0 commit comments

Comments
 (0)