Thu, 27 Feb 2025 14:42:39 +0100
Code Style Checkers
- Refactored the various code style checkers for better maintainability.
10052 | 1 | # -*- coding: utf-8 -*- |
2 | ||
11090
f5f5f5803935
Updated copyright for 2025.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10439
diff
changeset
|
3 | # Copyright (c) 2023 - 2025 Detlev Offenbach <detlev@die-offenbachs.de> |
10052 | 4 | # |
5 | ||
6 | """ | |
7 | Module implementing a checker for unused arguments, variables, ... . | |
8 | """ | |
9 | ||
10 | import ast | |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
11 | import collections |
10052 | 12 | |
13 | import AstUtilities | |
14 | ||
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
15 | from CodeStyleTopicChecker import CodeStyleTopicChecker |
10052 | 16 | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
17 | |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
18 | class UnusedChecker(CodeStyleTopicChecker): |
10052 | 19 | """ |
20 | Class implementing a checker for unused arguments, variables, ... . | |
21 | """ | |
22 | ||
23 | Codes = [ | |
24 | ## Unused Arguments | |
11147
dee6e106b4d3
Modified the code style checker such, that the issue category and issue number are separated by a '-' to make up the issue code (e.g E-901).
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11145
diff
changeset
|
25 | "U-100", |
dee6e106b4d3
Modified the code style checker such, that the issue category and issue number are separated by a '-' to make up the issue code (e.g E-901).
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11145
diff
changeset
|
26 | "U-101", |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
27 | ## Unused Globals |
11147
dee6e106b4d3
Modified the code style checker such, that the issue category and issue number are separated by a '-' to make up the issue code (e.g E-901).
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11145
diff
changeset
|
28 | "U-200", |
10052 | 29 | ] |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
30 | Category = "U" |
10052 | 31 | |
32 | def __init__(self, source, filename, tree, select, ignore, expected, repeat, args): | |
33 | """ | |
34 | Constructor | |
35 | ||
36 | @param source source code to be checked | |
37 | @type list of str | |
38 | @param filename name of the source file | |
39 | @type str | |
40 | @param tree AST tree of the source code | |
41 | @type ast.Module | |
42 | @param select list of selected codes | |
43 | @type list of str | |
44 | @param ignore list of codes to be ignored | |
45 | @type list of str | |
46 | @param expected list of expected codes | |
47 | @type list of str | |
48 | @param repeat flag indicating to report each occurrence of a code | |
49 | @type bool | |
50 | @param args dictionary of arguments for the various checks | |
51 | @type dict | |
52 | """ | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
53 | super().__init__( |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
54 | UnusedChecker.Category, |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
55 | source, |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
56 | filename, |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
57 | tree, |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
58 | select, |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
59 | ignore, |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
60 | expected, |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
61 | repeat, |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
62 | args, |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
63 | ) |
10052 | 64 | |
65 | checkersWithCodes = [ | |
11147
dee6e106b4d3
Modified the code style checker such, that the issue category and issue number are separated by a '-' to make up the issue code (e.g E-901).
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11145
diff
changeset
|
66 | (self.__checkUnusedArguments, ("U-100", "U-101")), |
dee6e106b4d3
Modified the code style checker such, that the issue category and issue number are separated by a '-' to make up the issue code (e.g E-901).
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11145
diff
changeset
|
67 | (self.__checkUnusedGlobals, ("U-200",)), |
10052 | 68 | ] |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
69 | self._initializeCheckers(checkersWithCodes) |
10052 | 70 | |
71 | ####################################################################### | |
72 | ## Unused Arguments | |
73 | ## | |
74 | ## adapted from: flake8-unused-arguments v0.0.13 | |
75 | ####################################################################### | |
76 | ||
77 | def __checkUnusedArguments(self): | |
78 | """ | |
79 | Private method to check function and method definitions for unused arguments. | |
80 | """ | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
81 | finder = FunctionFinder(self.args["IgnoreNestedFunctions"]) |
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
82 | finder.visit(self.tree) |
10052 | 83 | |
84 | for functionNode in finder.functionNodes(): | |
85 | decoratorNames = set(self.__getDecoratorNames(functionNode)) | |
86 | ||
87 | # ignore overload functions, it's not a surprise when they're empty | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
88 | if self.args["IgnoreOverload"] and "overload" in decoratorNames: |
10052 | 89 | continue |
90 | ||
91 | # ignore overridden functions | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
92 | if self.args["IgnoreOverride"] and "override" in decoratorNames: |
10052 | 93 | continue |
94 | ||
95 | # ignore abstractmethods, it's not a surprise when they're empty | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
96 | if self.args["IgnoreAbstract"] and "abstractmethod" in decoratorNames: |
10052 | 97 | continue |
98 | ||
99 | # ignore Qt slot methods | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
100 | if self.args["IgnoreSlotMethods"] and ( |
10052 | 101 | "pyqtSlot" in decoratorNames or "Slot" in decoratorNames |
102 | ): | |
103 | continue | |
104 | ||
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
105 | if self.args["IgnoreEventHandlerMethods"] and self.__isEventHandlerMethod( |
10066
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
106 | functionNode |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
107 | ): |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
108 | continue |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
109 | |
10052 | 110 | # ignore stub functions |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
111 | if self.args["IgnoreStubs"] and self.__isStubFunction(functionNode): |
10052 | 112 | continue |
113 | ||
114 | # ignore lambdas | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
115 | if self.args["IgnoreLambdas"] and isinstance(functionNode, ast.Lambda): |
10052 | 116 | continue |
117 | ||
118 | # ignore __double_underscore_methods__() | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
119 | if self.args["IgnoreDunderMethods"] and self.__isDunderMethod(functionNode): |
10052 | 120 | continue |
121 | ||
122 | for i, argument in self.__getUnusedArguments(functionNode): | |
123 | name = argument.arg | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
124 | if self.args["IgnoreVariadicNames"]: |
10052 | 125 | if ( |
126 | functionNode.args.vararg | |
127 | and functionNode.args.vararg.arg == name | |
128 | ): | |
129 | continue | |
130 | if functionNode.args.kwarg and functionNode.args.kwarg.arg == name: | |
131 | continue | |
132 | ||
133 | # ignore self or whatever the first argument is for a classmethod | |
134 | if i == 0 and ( | |
135 | name in ("self", "cls") or "classmethod" in decoratorNames | |
136 | ): | |
137 | continue | |
138 | ||
139 | lineNumber = argument.lineno | |
140 | offset = argument.col_offset | |
141 | ||
11147
dee6e106b4d3
Modified the code style checker such, that the issue category and issue number are separated by a '-' to make up the issue code (e.g E-901).
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11145
diff
changeset
|
142 | errorCode = "U-101" if name.startswith("_") else "U-100" |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
143 | self.addError(lineNumber, offset, errorCode, name) |
10052 | 144 | |
145 | def __getDecoratorNames(self, functionNode): | |
146 | """ | |
147 | Private method to yield the decorator names of the function. | |
148 | ||
149 | @param functionNode reference to the node defining the function or lambda | |
150 | @type ast.AsyncFunctionDef, ast.FunctionDef or ast.Lambda | |
151 | @yield decorator name | |
152 | @ytype str | |
153 | """ | |
154 | if isinstance(functionNode, ast.Lambda): | |
155 | return | |
156 | ||
157 | for decorator in functionNode.decorator_list: | |
158 | if isinstance(decorator, ast.Name): | |
159 | yield decorator.id | |
160 | elif isinstance(decorator, ast.Attribute): | |
161 | yield decorator.attr | |
162 | elif isinstance(decorator, ast.Call): | |
163 | if isinstance(decorator.func, ast.Name): | |
164 | yield decorator.func.id | |
165 | else: | |
166 | yield decorator.func.attr | |
167 | ||
168 | def __isStubFunction(self, functionNode): | |
169 | """ | |
170 | Private method to check, if the given function node defines a stub function. | |
171 | ||
172 | @param functionNode reference to the node defining the function or lambda | |
173 | @type ast.AsyncFunctionDef, ast.FunctionDef or ast.Lambda | |
174 | @return flag indicating a stub function | |
175 | @rtype bool | |
176 | """ | |
177 | if isinstance(functionNode, ast.Lambda): | |
178 | return AstUtilities.isEllipsis(functionNode.body) | |
179 | ||
180 | statement = functionNode.body[0] | |
181 | if isinstance(statement, ast.Expr) and AstUtilities.isString(statement.value): | |
182 | if len(functionNode.body) > 1: | |
183 | # first statement is a docstring, let's skip it | |
184 | statement = functionNode.body[1] | |
185 | else: | |
186 | # it's a function with only a docstring, that's a stub | |
187 | return True | |
188 | ||
189 | if isinstance(statement, ast.Pass): | |
190 | return True | |
191 | if isinstance(statement, ast.Expr) and AstUtilities.isEllipsis(statement.value): | |
192 | return True | |
193 | ||
194 | if isinstance(statement, ast.Raise): | |
195 | # like 'raise NotImplementedError()' | |
196 | if ( | |
197 | isinstance(statement.exc, ast.Call) | |
198 | and hasattr(statement.exc.func, "id") | |
199 | and statement.exc.func.id == "NotImplementedError" | |
200 | ): | |
201 | return True | |
202 | ||
203 | # like 'raise NotImplementedError' | |
204 | elif ( | |
205 | isinstance(statement.exc, ast.Name) | |
206 | and hasattr(statement.exc, "id") | |
207 | and statement.exc.id == "NotImplementedError" | |
208 | ): | |
209 | return True | |
210 | ||
211 | return False | |
212 | ||
213 | def __isDunderMethod(self, functionNode): | |
214 | """ | |
215 | Private method to check, if the function node defines a special function. | |
216 | ||
217 | @param functionNode reference to the node defining the function or lambda | |
218 | @type ast.AsyncFunctionDef, ast.FunctionDef or ast.Lambda | |
219 | @return flag indicating a special function | |
220 | @rtype bool | |
221 | """ | |
222 | if isinstance(functionNode, ast.Lambda): | |
223 | return False | |
224 | ||
225 | if not hasattr(functionNode, "name"): | |
226 | return False | |
227 | ||
228 | name = functionNode.name | |
229 | return len(name) > 4 and name.startswith("__") and name.endswith("__") | |
230 | ||
10066
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
231 | def __isEventHandlerMethod(self, functionNode): |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
232 | """ |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
233 | Private method to check, if the function node defines a Qt event handler. |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
234 | |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
235 | Qt event handler methods are assumed to end with 'Event' or have the name |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
236 | 'event' or 'eventFilter'. Only standard methodes (i.e. ast.FunctionDef) |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
237 | are assumed to be potential event handlers. |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
238 | |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
239 | @param functionNode reference to the node defining the function or lambda |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
240 | @type ast.AsyncFunctionDef, ast.FunctionDef or ast.Lambda |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
241 | @return flag indicating a Qt event handler method |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
242 | @rtype bool |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
243 | """ |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
244 | if isinstance(functionNode, (ast.Lambda, ast.AsyncFunctionDef)): |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
245 | return False |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
246 | |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
247 | if not hasattr(functionNode, "name"): |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
248 | return False |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
249 | |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
250 | name = functionNode.name |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
251 | return name.endswith("Event") or name in ("event", "eventFilter") |
251638443e17
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10056
diff
changeset
|
252 | |
10052 | 253 | def __getUnusedArguments(self, functionNode): |
254 | """ | |
255 | Private method to get a list of unused arguments of the given function. | |
256 | ||
257 | @param functionNode reference to the node defining the function or lambda | |
258 | @type ast.AsyncFunctionDef, ast.FunctionDef or ast.Lambda | |
259 | @return list of tuples of the argument position and the argument | |
260 | @rtype list of tuples of (int, ast.arg) | |
261 | """ | |
262 | arguments = list(enumerate(self.__getArguments(functionNode))) | |
263 | ||
264 | class NameFinder(ast.NodeVisitor): | |
265 | """ | |
266 | Class to find the used argument names. | |
267 | """ | |
268 | ||
269 | def visit_Name(self, name): | |
270 | """ | |
271 | Public method to check a Name node. | |
272 | ||
273 | @param name reference to the name node to be checked | |
274 | @type ast.Name | |
275 | """ | |
276 | nonlocal arguments | |
277 | ||
278 | if isinstance(name.ctx, ast.Store): | |
279 | return | |
280 | ||
281 | arguments = [ | |
282 | (argIndex, arg) for argIndex, arg in arguments if arg.arg != name.id | |
283 | ] | |
284 | ||
285 | NameFinder().visit(functionNode) | |
286 | return arguments | |
287 | ||
288 | def __getArguments(self, functionNode): | |
289 | """ | |
290 | Private method to get all argument names of the given function. | |
291 | ||
292 | @param functionNode reference to the node defining the function or lambda | |
293 | @type ast.AsyncFunctionDef, ast.FunctionDef or ast.Lambda | |
294 | @return list of argument names | |
295 | @rtype list of ast.arg | |
296 | """ | |
297 | args = functionNode.args | |
298 | ||
299 | orderedArguments = [] | |
300 | ||
301 | # plain old args | |
302 | orderedArguments.extend(args.args) | |
303 | ||
304 | # *arg name | |
305 | if args.vararg is not None: | |
306 | orderedArguments.append(args.vararg) | |
307 | ||
308 | # *, key, word, only, args | |
309 | orderedArguments.extend(args.kwonlyargs) | |
310 | ||
311 | # **kwarg name | |
312 | if args.kwarg is not None: | |
313 | orderedArguments.append(args.kwarg) | |
314 | ||
315 | return orderedArguments | |
316 | ||
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
317 | ####################################################################### |
10056
ac1c214e0a05
Corrected some comments.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10054
diff
changeset
|
318 | ## Unused Globals |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
319 | ## |
10185
29e896e9e74e
Updated some codestyle checkers for imports and too complex annotations.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10127
diff
changeset
|
320 | ## adapted from: flake8-unused-globals v0.1.10 |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
321 | ####################################################################### |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
322 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
323 | def __checkUnusedGlobals(self): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
324 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
325 | Private method to check for unused global variables. |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
326 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
327 | errors = {} |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
328 | loadCounter = GlobalVariableLoadCounter() |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
329 | loadCounter.visit(self.tree) |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
330 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
331 | globalVariables = self.__extractGlobalVariables() |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
332 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
333 | for varId, loads in loadCounter.getLoads(): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
334 | if varId in globalVariables and loads == 0: |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
335 | storeInfo = loadCounter.getStoreInfo(varId) |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
336 | errorInfo = (storeInfo.lineno, storeInfo.offset, "U-200", varId) |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
337 | errors[varId] = errorInfo |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
338 | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
339 | for node in self.tree.body[::-1]: |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
340 | if isinstance(node, ast.Assign): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
341 | for target in node.targets: |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
342 | if isinstance(target, ast.Name) and target.id in errors: |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
343 | errors.pop(target.id) |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
344 | elif ( |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
345 | isinstance(node, ast.AnnAssign) |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
346 | and isinstance(node.target, ast.Name) |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
347 | and node.target.id in errors |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
348 | ): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
349 | errors.pop(node.target.id) |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
350 | else: |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
351 | break |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
352 | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
353 | if self.args["IgnoreDunderGlobals"]: |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
354 | # eliminate some special cases |
10373
093dcebe5ecb
Corrected some uses of dict.keys(), dict.values() and dict.items().
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10185
diff
changeset
|
355 | for name in list(errors): |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
356 | if name.startswith("__") and name.endswith("__"): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
357 | errors.pop(name) |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
358 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
359 | for varId in errors: |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
360 | self.addError(*errors[varId]) |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
361 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
362 | def __extractGlobalVariables(self): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
363 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
364 | Private method to get the names of all global variables. |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
365 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
366 | @return set containing the defined global variable names |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
367 | @rtype set of str |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
368 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
369 | variables = set() |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
370 | |
11150
73d80859079c
Code Style Checkers
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
11147
diff
changeset
|
371 | for assignment in self.tree.body: |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
372 | if isinstance(assignment, ast.Assign): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
373 | for target in assignment.targets: |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
374 | if isinstance(target, ast.Name): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
375 | variables.add(target.id) |
10054
d7a47f0cff2b
Regenerated source documentation.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10053
diff
changeset
|
376 | elif isinstance(assignment, ast.AnnAssign) and isinstance( |
d7a47f0cff2b
Regenerated source documentation.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10053
diff
changeset
|
377 | assignment.target, ast.Name |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
378 | ): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
379 | variables.add(assignment.target.id) |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
380 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
381 | return variables |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
382 | |
10054
d7a47f0cff2b
Regenerated source documentation.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10053
diff
changeset
|
383 | |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
384 | ####################################################################### |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
385 | ## Class used by 'Unused Arguments' |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
386 | ## |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
387 | ## adapted from: flake8-unused-arguments v0.0.13 |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
388 | ####################################################################### |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
389 | |
10052 | 390 | |
391 | class FunctionFinder(ast.NodeVisitor): | |
392 | """ | |
393 | Class to find all defined functions and methods. | |
394 | """ | |
395 | ||
396 | def __init__(self, onlyTopLevel=False): | |
397 | """ | |
398 | Constructor | |
399 | ||
400 | @param onlyTopLevel flag indicating to search for top level functions only | |
401 | (defaults to False) | |
402 | @type bool (optional) | |
403 | """ | |
404 | super().__init__() | |
405 | ||
406 | self.__functions = [] | |
407 | self.__onlyTopLevel = onlyTopLevel | |
408 | ||
409 | def functionNodes(self): | |
410 | """ | |
411 | Public method to get the list of detected functions and lambdas. | |
412 | ||
413 | @return list of detected functions and lambdas | |
414 | @rtype list of ast.AsyncFunctionDef, ast.FunctionDef or ast.Lambda | |
415 | """ | |
416 | return self.__functions | |
417 | ||
418 | def __visitFunctionTypes(self, functionNode): | |
419 | """ | |
420 | Private method to handle an AST node defining a function or lambda. | |
421 | ||
422 | @param functionNode reference to the node defining a function or lambda | |
423 | @type ast.AsyncFunctionDef, ast.FunctionDef or ast.Lambda | |
424 | """ | |
425 | self.__functions.append(functionNode) | |
426 | if not self.__onlyTopLevel: | |
427 | if isinstance(functionNode, ast.Lambda): | |
428 | self.visit(functionNode.body) | |
429 | else: | |
430 | for obj in functionNode.body: | |
431 | self.visit(obj) | |
432 | ||
433 | visit_AsyncFunctionDef = visit_FunctionDef = visit_Lambda = __visitFunctionTypes | |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
434 | |
10054
d7a47f0cff2b
Regenerated source documentation.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10053
diff
changeset
|
435 | |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
436 | ####################################################################### |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
437 | ## Class used by 'Unused Globals' |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
438 | ## |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
439 | ## adapted from: flake8-unused-globals v0.1.9 |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
440 | ####################################################################### |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
441 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
442 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
443 | GlobalVariableStoreInfo = collections.namedtuple( |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
444 | "GlobalVariableStoreInfo", ["lineno", "offset"] |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
445 | ) |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
446 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
447 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
448 | class GlobalVariableLoadCounter(ast.NodeVisitor): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
449 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
450 | Class to find all defined global variables and count their usages. |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
451 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
452 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
453 | def __init__(self): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
454 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
455 | Constructor |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
456 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
457 | super().__init__() |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
458 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
459 | self.__loads = {} |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
460 | self.__storeInfo = {} |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
461 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
462 | def visit_Name(self, nameNode): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
463 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
464 | Public method to record the definition and use of a global variable. |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
465 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
466 | @param nameNode reference to the name node to be processed |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
467 | @type ast.Name |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
468 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
469 | if isinstance(nameNode.ctx, ast.Load) and nameNode.id in self.__loads: |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
470 | self.__loads[nameNode.id] += 1 |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
471 | elif ( |
10054
d7a47f0cff2b
Regenerated source documentation.
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10053
diff
changeset
|
472 | isinstance(nameNode.ctx, ast.Store) and nameNode.id not in self.__storeInfo |
10053
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
473 | ): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
474 | self.__loads[nameNode.id] = 0 |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
475 | self.__storeInfo[nameNode.id] = GlobalVariableStoreInfo( |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
476 | lineno=nameNode.lineno, offset=nameNode.col_offset |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
477 | ) |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
478 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
479 | def getLoads(self): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
480 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
481 | Public method to get an iterator of the detected variable loads. |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
482 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
483 | @return DESCRIPTION |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
484 | @rtype TYPE |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
485 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
486 | return self.__loads.items() |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
487 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
488 | def getStoreInfo(self, variableId): |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
489 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
490 | Public method to get the store info data of a given variable ID. |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
491 | |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
492 | @param variableId variable ID to retrieve the store info for |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
493 | @type str |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
494 | @return named tuple containing the line number and column offset |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
495 | @rtype GlobalVariableStoreInfo |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
496 | """ |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
497 | try: |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
498 | return self.__storeInfo[variableId] |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
499 | except KeyError: |
9914b7b4b11c
Code Style Checker
Detlev Offenbach <detlev@die-offenbachs.de>
parents:
10052
diff
changeset
|
500 | return None |