108 @return tuple giving line number, offset within line, code and |
113 @return tuple giving line number, offset within line, code and |
109 checker function |
114 checker function |
110 """ |
115 """ |
111 if isinstance(node, ast.ClassDef): |
116 if isinstance(node, ast.ClassDef): |
112 self.__tagClassFunctions(node) |
117 self.__tagClassFunctions(node) |
113 elif isinstance(node, ast.FunctionDef): |
118 elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
114 self.__findGlobalDefs(node) |
119 self.__findGlobalDefs(node) |
115 |
120 |
116 checkerName = node.__class__.__name__.lower() |
121 checkerName = node.__class__.__name__.lower() |
117 if checkerName in self.__checkers: |
122 if checkerName in self.__checkers: |
118 for checker in self.__checkers[checkerName]: |
123 for checker in self.__checkers[checkerName]: |
140 if isinstance(meth, ast.Name): |
145 if isinstance(meth, ast.Name): |
141 lateDecoration[meth.id] = funcName |
146 lateDecoration[meth.id] = funcName |
142 |
147 |
143 # iterate over all functions and tag them |
148 # iterate over all functions and tag them |
144 for node in ast.iter_child_nodes(classNode): |
149 for node in ast.iter_child_nodes(classNode): |
145 if not isinstance(node, ast.FunctionDef): |
150 if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
146 continue |
151 continue |
147 |
152 |
148 node.function_type = 'method' |
153 node.function_type = 'method' |
149 if node.name == "__new__": |
154 if node.name == "__new__": |
150 node.function_type = "classmethod" |
155 node.function_type = "classmethod" |
169 while nodesToCheck: |
174 while nodesToCheck: |
170 node = nodesToCheck.pop() |
175 node = nodesToCheck.pop() |
171 if isinstance(node, ast.Global): |
176 if isinstance(node, ast.Global): |
172 globalNames.update(node.names) |
177 globalNames.update(node.names) |
173 |
178 |
174 if not isinstance(node, (ast.FunctionDef, ast.ClassDef)): |
179 if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, |
|
180 ast.ClassDef)): |
175 nodesToCheck.extend(ast.iter_child_nodes(node)) |
181 nodesToCheck.extend(ast.iter_child_nodes(node)) |
176 functionNode.global_names = globalNames |
182 functionNode.global_names = globalNames |
177 |
183 |
178 def __getArgNames(self, node): |
184 def __getArgNames(self, node): |
179 """ |
185 """ |
220 lineno = node.lineno |
226 lineno = node.lineno |
221 offset = node.col_offset |
227 offset = node.col_offset |
222 if isinstance(node, ast.ClassDef): |
228 if isinstance(node, ast.ClassDef): |
223 lineno += len(node.decorator_list) |
229 lineno += len(node.decorator_list) |
224 offset += 6 |
230 offset += 6 |
225 elif isinstance(node, ast.FunctionDef): |
231 elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
226 lineno += len(node.decorator_list) |
232 lineno += len(node.decorator_list) |
227 offset += 4 |
233 offset += 4 |
228 return (lineno, offset, code) |
234 return (lineno, offset, code) |
229 |
235 |
230 def __isNameToBeAvoided(self, name): |
236 def __isNameToBeAvoided(self, name): |
243 @param node AST note to check |
249 @param node AST note to check |
244 @param parents list of parent nodes |
250 @param parents list of parent nodes |
245 @return tuple giving line number, offset within line and error code |
251 @return tuple giving line number, offset within line and error code |
246 (integer, integer, string) |
252 (integer, integer, string) |
247 """ |
253 """ |
248 if isinstance(node, (ast.ClassDef, ast.FunctionDef)): |
254 if isinstance(node, (ast.ClassDef, ast.FunctionDef, |
|
255 ast.AsyncFunctionDef)): |
249 name = node.name |
256 name = node.name |
250 if self.__isNameToBeAvoided(name): |
257 if self.__isNameToBeAvoided(name): |
251 yield self.__error(node, "N831") |
258 yield self.__error(node, "N831") |
252 return |
259 return |
253 |
260 |
254 if isinstance(node, ast.FunctionDef): |
261 if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
255 argNames = self.__getArgNames(node) |
262 argNames = self.__getArgNames(node) |
256 for arg in argNames: |
263 for arg in argNames: |
257 if self.__isNameToBeAvoided(arg): |
264 if self.__isNameToBeAvoided(arg): |
258 yield self.__error(node, "N831") |
265 yield self.__error(node, "N831") |
259 return |
266 return |
374 (integer, integer, string) |
381 (integer, integer, string) |
375 """ |
382 """ |
376 for parentFunc in reversed(parents): |
383 for parentFunc in reversed(parents): |
377 if isinstance(parentFunc, ast.ClassDef): |
384 if isinstance(parentFunc, ast.ClassDef): |
378 return |
385 return |
379 if isinstance(parentFunc, ast.FunctionDef): |
386 if isinstance(parentFunc, (ast.FunctionDef, ast.AsyncFunctionDef)): |
380 break |
387 break |
381 else: |
388 else: |
382 return |
389 return |
383 for target in node.targets: |
390 for target in node.targets: |
384 name = isinstance(target, ast.Name) and target.id |
391 name = isinstance(target, ast.Name) and target.id |