11 import ast |
11 import ast |
12 import re |
12 import re |
13 import os |
13 import os |
14 |
14 |
15 try: |
15 try: |
16 ast.AsyncFunctionDef # __IGNORE_EXCEPTION__ |
16 ast.AsyncFunctionDef # __IGNORE_EXCEPTION__ |
17 except AttributeError: |
17 except AttributeError: |
18 ast.AsyncFunctionDef = ast.FunctionDef |
18 ast.AsyncFunctionDef = ast.FunctionDef |
19 |
19 |
20 |
20 |
21 class NamingStyleChecker: |
21 class NamingStyleChecker: |
22 """ |
22 """ |
23 Class implementing a checker for naming conventions. |
23 Class implementing a checker for naming conventions. |
24 """ |
24 """ |
|
25 |
25 LowercaseRegex = re.compile(r"[_a-z][_a-z0-9]*$") |
26 LowercaseRegex = re.compile(r"[_a-z][_a-z0-9]*$") |
26 UppercaseRegexp = re.compile(r"[_A-Z][_A-Z0-9]*$") |
27 UppercaseRegexp = re.compile(r"[_A-Z][_A-Z0-9]*$") |
27 CamelcaseRegexp = re.compile(r"_?[A-Z][a-zA-Z0-9]*$") |
28 CamelcaseRegexp = re.compile(r"_?[A-Z][a-zA-Z0-9]*$") |
28 MixedcaseRegexp = re.compile(r"_?[a-z][a-zA-Z0-9]*$") |
29 MixedcaseRegexp = re.compile(r"_?[a-z][a-zA-Z0-9]*$") |
29 |
30 |
30 Codes = [ |
31 Codes = [ |
31 "N801", "N802", "N803", "N804", "N805", "N806", "N807", "N808", |
32 "N801", |
32 "N811", "N812", "N813", "N814", "N821", "N831" |
33 "N802", |
|
34 "N803", |
|
35 "N804", |
|
36 "N805", |
|
37 "N806", |
|
38 "N807", |
|
39 "N808", |
|
40 "N811", |
|
41 "N812", |
|
42 "N813", |
|
43 "N814", |
|
44 "N821", |
|
45 "N831", |
33 ] |
46 ] |
34 |
47 |
35 def __init__(self, tree, filename, options): |
48 def __init__(self, tree, filename, options): |
36 """ |
49 """ |
37 Constructor (according to 'extended' pycodestyle.py API) |
50 Constructor (according to 'extended' pycodestyle.py API) |
38 |
51 |
39 @param tree AST tree of the source file |
52 @param tree AST tree of the source file |
40 @param filename name of the source file (string) |
53 @param filename name of the source file (string) |
41 @param options options as parsed by pycodestyle.StyleGuide |
54 @param options options as parsed by pycodestyle.StyleGuide |
42 """ |
55 """ |
43 self.__parents = collections.deque() |
56 self.__parents = collections.deque() |
44 self.__tree = tree |
57 self.__tree = tree |
45 self.__filename = filename |
58 self.__filename = filename |
46 |
59 |
47 self.__checkersWithCodes = { |
60 self.__checkersWithCodes = { |
48 "classdef": [ |
61 "classdef": [ |
49 (self.__checkClassName, ("N801",)), |
62 (self.__checkClassName, ("N801",)), |
50 (self.__checkNameToBeAvoided, ("N831",)), |
63 (self.__checkNameToBeAvoided, ("N831",)), |
51 ], |
64 ], |
52 "functiondef": [ |
65 "functiondef": [ |
53 (self.__checkFunctionName, ("N802",)), |
66 (self.__checkFunctionName, ("N802",)), |
54 (self.__checkFunctionArgumentNames, |
67 (self.__checkFunctionArgumentNames, ("N803", "N804", "N805", "N806")), |
55 ("N803", "N804", "N805", "N806")), |
|
56 (self.__checkNameToBeAvoided, ("N831",)), |
68 (self.__checkNameToBeAvoided, ("N831",)), |
57 ], |
69 ], |
58 "assign": [ |
70 "assign": [ |
59 (self.__checkVariablesInFunction, ("N821",)), |
71 (self.__checkVariablesInFunction, ("N821",)), |
60 (self.__checkNameToBeAvoided, ("N831",)), |
72 (self.__checkNameToBeAvoided, ("N831",)), |
64 ], |
76 ], |
65 "module": [ |
77 "module": [ |
66 (self.__checkModule, ("N807", "N808")), |
78 (self.__checkModule, ("N807", "N808")), |
67 ], |
79 ], |
68 } |
80 } |
69 |
81 |
70 self.__checkers = {} |
82 self.__checkers = {} |
71 for key, checkers in self.__checkersWithCodes.items(): |
83 for key, checkers in self.__checkersWithCodes.items(): |
72 for checker, codes in checkers: |
84 for checker, codes in checkers: |
73 if any(not (code and options.ignore_code(code)) |
85 if any(not (code and options.ignore_code(code)) for code in codes): |
74 for code in codes): |
|
75 if key not in self.__checkers: |
86 if key not in self.__checkers: |
76 self.__checkers[key] = [] |
87 self.__checkers[key] = [] |
77 self.__checkers[key].append(checker) |
88 self.__checkers[key].append(checker) |
78 |
89 |
79 def run(self): |
90 def run(self): |
80 """ |
91 """ |
81 Public method run by the pycodestyle.py checker. |
92 Public method run by the pycodestyle.py checker. |
82 |
93 |
83 @return tuple giving line number, offset within line, code and |
94 @return tuple giving line number, offset within line, code and |
84 checker function |
95 checker function |
85 """ |
96 """ |
86 if self.__tree and self.__checkers: |
97 if self.__tree and self.__checkers: |
87 return self.__visitTree(self.__tree) |
98 return self.__visitTree(self.__tree) |
88 else: |
99 else: |
89 return () |
100 return () |
90 |
101 |
91 def __visitTree(self, node): |
102 def __visitTree(self, node): |
92 """ |
103 """ |
93 Private method to scan the given AST tree. |
104 Private method to scan the given AST tree. |
94 |
105 |
95 @param node AST tree node to scan |
106 @param node AST tree node to scan |
96 @yield tuple giving line number, offset within line and error code |
107 @yield tuple giving line number, offset within line and error code |
97 @ytype tuple of (int, int, str) |
108 @ytype tuple of (int, int, str) |
98 """ |
109 """ |
99 yield from self.__visitNode(node) |
110 yield from self.__visitNode(node) |
100 self.__parents.append(node) |
111 self.__parents.append(node) |
101 for child in ast.iter_child_nodes(node): |
112 for child in ast.iter_child_nodes(node): |
102 yield from self.__visitTree(child) |
113 yield from self.__visitTree(child) |
103 self.__parents.pop() |
114 self.__parents.pop() |
104 |
115 |
105 def __visitNode(self, node): |
116 def __visitNode(self, node): |
106 """ |
117 """ |
107 Private method to inspect the given AST node. |
118 Private method to inspect the given AST node. |
108 |
119 |
109 @param node AST tree node to inspect |
120 @param node AST tree node to inspect |
110 @yield tuple giving line number, offset within line and error code |
121 @yield tuple giving line number, offset within line and error code |
111 @ytype tuple of (int, int, str) |
122 @ytype tuple of (int, int, str) |
112 """ |
123 """ |
113 if isinstance(node, ast.ClassDef): |
124 if isinstance(node, ast.ClassDef): |
114 self.__tagClassFunctions(node) |
125 self.__tagClassFunctions(node) |
115 elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
126 elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
116 self.__findGlobalDefs(node) |
127 self.__findGlobalDefs(node) |
117 |
128 |
118 checkerName = node.__class__.__name__.lower() |
129 checkerName = node.__class__.__name__.lower() |
119 if checkerName in self.__checkers: |
130 if checkerName in self.__checkers: |
120 for checker in self.__checkers[checkerName]: |
131 for checker in self.__checkers[checkerName]: |
121 for error in checker(node, self.__parents): |
132 for error in checker(node, self.__parents): |
122 yield error + (self.__checkers[checkerName],) |
133 yield error + (self.__checkers[checkerName],) |
123 |
134 |
124 def __tagClassFunctions(self, classNode): |
135 def __tagClassFunctions(self, classNode): |
125 """ |
136 """ |
126 Private method to tag functions if they are methods, class methods or |
137 Private method to tag functions if they are methods, class methods or |
127 static methods. |
138 static methods. |
128 |
139 |
129 @param classNode AST tree node to tag |
140 @param classNode AST tree node to tag |
130 """ |
141 """ |
131 # try to find all 'old style decorators' |
142 # try to find all 'old style decorators' |
132 # like m = staticmethod(m) |
143 # like m = staticmethod(m) |
133 lateDecoration = {} |
144 lateDecoration = {} |
134 for node in ast.iter_child_nodes(classNode): |
145 for node in ast.iter_child_nodes(classNode): |
135 if not (isinstance(node, ast.Assign) and |
146 if not ( |
136 isinstance(node.value, ast.Call) and |
147 isinstance(node, ast.Assign) |
137 isinstance(node.value.func, ast.Name)): |
148 and isinstance(node.value, ast.Call) |
|
149 and isinstance(node.value.func, ast.Name) |
|
150 ): |
138 continue |
151 continue |
139 funcName = node.value.func.id |
152 funcName = node.value.func.id |
140 if funcName in ("classmethod", "staticmethod"): |
153 if funcName in ("classmethod", "staticmethod"): |
141 meth = (len(node.value.args) == 1 and node.value.args[0]) |
154 meth = len(node.value.args) == 1 and node.value.args[0] |
142 if isinstance(meth, ast.Name): |
155 if isinstance(meth, ast.Name): |
143 lateDecoration[meth.id] = funcName |
156 lateDecoration[meth.id] = funcName |
144 |
157 |
145 # iterate over all functions and tag them |
158 # iterate over all functions and tag them |
146 for node in ast.iter_child_nodes(classNode): |
159 for node in ast.iter_child_nodes(classNode): |
147 if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
160 if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
148 continue |
161 continue |
149 |
162 |
150 node.function_type = 'method' |
163 node.function_type = "method" |
151 if node.name == "__new__": |
164 if node.name == "__new__": |
152 node.function_type = "classmethod" |
165 node.function_type = "classmethod" |
153 |
166 |
154 if node.name in lateDecoration: |
167 if node.name in lateDecoration: |
155 node.function_type = lateDecoration[node.name] |
168 node.function_type = lateDecoration[node.name] |
156 elif node.decorator_list: |
169 elif node.decorator_list: |
157 names = [d.id for d in node.decorator_list |
170 names = [ |
158 if isinstance(d, ast.Name) and |
171 d.id |
159 d.id in ("classmethod", "staticmethod")] |
172 for d in node.decorator_list |
|
173 if isinstance(d, ast.Name) |
|
174 and d.id in ("classmethod", "staticmethod") |
|
175 ] |
160 if names: |
176 if names: |
161 node.function_type = names[0] |
177 node.function_type = names[0] |
162 |
178 |
163 def __findGlobalDefs(self, functionNode): |
179 def __findGlobalDefs(self, functionNode): |
164 """ |
180 """ |
165 Private method amend a node with global definitions information. |
181 Private method amend a node with global definitions information. |
166 |
182 |
167 @param functionNode AST tree node to amend |
183 @param functionNode AST tree node to amend |
168 """ |
184 """ |
169 globalNames = set() |
185 globalNames = set() |
170 nodesToCheck = collections.deque(ast.iter_child_nodes(functionNode)) |
186 nodesToCheck = collections.deque(ast.iter_child_nodes(functionNode)) |
171 while nodesToCheck: |
187 while nodesToCheck: |
172 node = nodesToCheck.pop() |
188 node = nodesToCheck.pop() |
173 if isinstance(node, ast.Global): |
189 if isinstance(node, ast.Global): |
174 globalNames.update(node.names) |
190 globalNames.update(node.names) |
175 |
191 |
176 if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, |
192 if not isinstance( |
177 ast.ClassDef)): |
193 node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef) |
|
194 ): |
178 nodesToCheck.extend(ast.iter_child_nodes(node)) |
195 nodesToCheck.extend(ast.iter_child_nodes(node)) |
179 functionNode.global_names = globalNames |
196 functionNode.global_names = globalNames |
180 |
197 |
181 def __getArgNames(self, node): |
198 def __getArgNames(self, node): |
182 """ |
199 """ |
183 Private method to get the argument names of a function node. |
200 Private method to get the argument names of a function node. |
184 |
201 |
185 @param node AST node to extract arguments names from |
202 @param node AST node to extract arguments names from |
186 @return list of argument names (list of string) |
203 @return list of argument names (list of string) |
187 """ |
204 """ |
188 posArgs = [arg.arg for arg in node.args.args] |
205 posArgs = [arg.arg for arg in node.args.args] |
189 kwOnly = [arg.arg for arg in node.args.kwonlyargs] |
206 kwOnly = [arg.arg for arg in node.args.kwonlyargs] |
190 return posArgs + kwOnly |
207 return posArgs + kwOnly |
191 |
208 |
192 def __error(self, node, code): |
209 def __error(self, node, code): |
193 """ |
210 """ |
194 Private method to build the error information. |
211 Private method to build the error information. |
195 |
212 |
196 @param node AST node to report an error for |
213 @param node AST node to report an error for |
197 @param code error code to report (string) |
214 @param code error code to report (string) |
198 @return tuple giving line number, offset within line and error code |
215 @return tuple giving line number, offset within line and error code |
199 (integer, integer, string) |
216 (integer, integer, string) |
200 """ |
217 """ |
209 offset += 6 |
226 offset += 6 |
210 elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
227 elif isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
211 lineno += len(node.decorator_list) |
228 lineno += len(node.decorator_list) |
212 offset += 4 |
229 offset += 4 |
213 return (lineno, offset, code) |
230 return (lineno, offset, code) |
214 |
231 |
215 def __isNameToBeAvoided(self, name): |
232 def __isNameToBeAvoided(self, name): |
216 """ |
233 """ |
217 Private method to check, if the given name should be avoided. |
234 Private method to check, if the given name should be avoided. |
218 |
235 |
219 @param name name to be checked (string) |
236 @param name name to be checked (string) |
220 @return flag indicating to avoid it (boolen) |
237 @return flag indicating to avoid it (boolen) |
221 """ |
238 """ |
222 return name in ("l", "O", "I") |
239 return name in ("l", "O", "I") |
223 |
240 |
224 def __checkNameToBeAvoided(self, node, parents): |
241 def __checkNameToBeAvoided(self, node, parents): |
225 """ |
242 """ |
226 Private class to check the given node for a name to be avoided (N831). |
243 Private class to check the given node for a name to be avoided (N831). |
227 |
244 |
228 @param node AST note to check |
245 @param node AST note to check |
229 @param parents list of parent nodes |
246 @param parents list of parent nodes |
230 @yield tuple giving line number, offset within line and error code |
247 @yield tuple giving line number, offset within line and error code |
231 @ytype tuple of (int, int, str) |
248 @ytype tuple of (int, int, str) |
232 """ |
249 """ |
233 if isinstance(node, (ast.ClassDef, ast.FunctionDef, |
250 if isinstance(node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)): |
234 ast.AsyncFunctionDef)): |
|
235 name = node.name |
251 name = node.name |
236 if self.__isNameToBeAvoided(name): |
252 if self.__isNameToBeAvoided(name): |
237 yield self.__error(node, "N831") |
253 yield self.__error(node, "N831") |
238 return |
254 return |
239 |
255 |
240 if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
256 if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): |
241 argNames = self.__getArgNames(node) |
257 argNames = self.__getArgNames(node) |
242 for arg in argNames: |
258 for arg in argNames: |
243 if self.__isNameToBeAvoided(arg): |
259 if self.__isNameToBeAvoided(arg): |
244 yield self.__error(node, "N831") |
260 yield self.__error(node, "N831") |
245 return |
261 return |
246 |
262 |
247 if isinstance(node, ast.Assign): |
263 if isinstance(node, ast.Assign): |
248 for target in node.targets: |
264 for target in node.targets: |
249 if isinstance(target, ast.Name): |
265 if isinstance(target, ast.Name): |
250 name = target.id |
266 name = target.id |
251 if not name: |
267 if not name: |
252 return |
268 return |
253 |
269 |
254 if self.__isNameToBeAvoided(name): |
270 if self.__isNameToBeAvoided(name): |
255 yield self.__error(node, "N831") |
271 yield self.__error(node, "N831") |
256 return |
272 return |
257 |
273 |
258 elif isinstance(target, (ast.Tuple, ast.List)): |
274 elif isinstance(target, (ast.Tuple, ast.List)): |
259 for element in target.elts: |
275 for element in target.elts: |
260 if isinstance(element, ast.Name): |
276 if isinstance(element, ast.Name): |
261 name = element.id |
277 name = element.id |
262 if not name: |
278 if not name: |
263 return |
279 return |
264 |
280 |
265 if self.__isNameToBeAvoided(name): |
281 if self.__isNameToBeAvoided(name): |
266 yield self.__error(node, "N831") |
282 yield self.__error(node, "N831") |
267 return |
283 return |
268 |
284 |
269 def __checkClassName(self, node, parents): |
285 def __checkClassName(self, node, parents): |
270 """ |
286 """ |
271 Private class to check the given node for class name |
287 Private class to check the given node for class name |
272 conventions (N801). |
288 conventions (N801). |
273 |
289 |
274 Almost without exception, class names use the CapWords convention. |
290 Almost without exception, class names use the CapWords convention. |
275 Classes for internal use have a leading underscore in addition. |
291 Classes for internal use have a leading underscore in addition. |
276 |
292 |
277 @param node AST note to check |
293 @param node AST note to check |
278 @param parents list of parent nodes |
294 @param parents list of parent nodes |
279 @yield tuple giving line number, offset within line and error code |
295 @yield tuple giving line number, offset within line and error code |
280 @ytype tuple of (int, int, str) |
296 @ytype tuple of (int, int, str) |
281 """ |
297 """ |
282 if not self.CamelcaseRegexp.match(node.name): |
298 if not self.CamelcaseRegexp.match(node.name): |
283 yield self.__error(node, "N801") |
299 yield self.__error(node, "N801") |
284 |
300 |
285 def __checkFunctionName(self, node, parents): |
301 def __checkFunctionName(self, node, parents): |
286 """ |
302 """ |
287 Private class to check the given node for function name |
303 Private class to check the given node for function name |
288 conventions (N802). |
304 conventions (N802). |
289 |
305 |
290 Function names should be lowercase, with words separated by underscores |
306 Function names should be lowercase, with words separated by underscores |
291 as necessary to improve readability. Functions <b>not</b> being |
307 as necessary to improve readability. Functions <b>not</b> being |
292 methods '__' in front and back are not allowed. Mixed case is allowed |
308 methods '__' in front and back are not allowed. Mixed case is allowed |
293 only in contexts where that's already the prevailing style |
309 only in contexts where that's already the prevailing style |
294 (e.g. threading.py), to retain backwards compatibility. |
310 (e.g. threading.py), to retain backwards compatibility. |
295 |
311 |
296 @param node AST note to check |
312 @param node AST note to check |
297 @param parents list of parent nodes |
313 @param parents list of parent nodes |
298 @yield tuple giving line number, offset within line and error code |
314 @yield tuple giving line number, offset within line and error code |
299 @ytype tuple of (int, int, str) |
315 @ytype tuple of (int, int, str) |
300 """ |
316 """ |
301 functionType = getattr(node, "function_type", "function") |
317 functionType = getattr(node, "function_type", "function") |
302 name = node.name |
318 name = node.name |
303 if ( |
319 if ( |
304 (functionType == "function" and "__" in (name[:2], name[-2:])) or |
320 functionType == "function" and "__" in (name[:2], name[-2:]) |
305 not self.LowercaseRegex.match(name) |
321 ) or not self.LowercaseRegex.match(name): |
306 ): |
|
307 yield self.__error(node, "N802") |
322 yield self.__error(node, "N802") |
308 |
323 |
309 def __checkFunctionArgumentNames(self, node, parents): |
324 def __checkFunctionArgumentNames(self, node, parents): |
310 """ |
325 """ |
311 Private class to check the argument names of functions |
326 Private class to check the argument names of functions |
312 (N803, N804, N805, N806). |
327 (N803, N804, N805, N806). |
313 |
328 |
314 The argument names of a function should be lowercase, with words |
329 The argument names of a function should be lowercase, with words |
315 separated by underscores. A class method should have 'cls' as the |
330 separated by underscores. A class method should have 'cls' as the |
316 first argument. A method should have 'self' as the first argument. |
331 first argument. A method should have 'self' as the first argument. |
317 |
332 |
318 @param node AST note to check |
333 @param node AST note to check |
319 @param parents list of parent nodes |
334 @param parents list of parent nodes |
320 @yield tuple giving line number, offset within line and error code |
335 @yield tuple giving line number, offset within line and error code |
321 @ytype tuple of (int, int, str) |
336 @ytype tuple of (int, int, str) |
322 """ |
337 """ |
323 if node.args.kwarg is not None: |
338 if node.args.kwarg is not None: |
324 kwarg = node.args.kwarg.arg |
339 kwarg = node.args.kwarg.arg |
325 if not self.LowercaseRegex.match(kwarg): |
340 if not self.LowercaseRegex.match(kwarg): |
326 yield self.__error(node, "N803") |
341 yield self.__error(node, "N803") |
327 return |
342 return |
328 |
343 |
329 if node.args.vararg is not None: |
344 if node.args.vararg is not None: |
330 vararg = node.args.vararg.arg |
345 vararg = node.args.vararg.arg |
331 if not self.LowercaseRegex.match(vararg): |
346 if not self.LowercaseRegex.match(vararg): |
332 yield self.__error(node, "N803") |
347 yield self.__error(node, "N803") |
333 return |
348 return |
334 |
349 |
335 argNames = self.__getArgNames(node) |
350 argNames = self.__getArgNames(node) |
336 functionType = getattr(node, "function_type", "function") |
351 functionType = getattr(node, "function_type", "function") |
337 |
352 |
338 if not argNames: |
353 if not argNames: |
339 if functionType == "method": |
354 if functionType == "method": |
340 yield self.__error(node, "N805") |
355 yield self.__error(node, "N805") |
341 elif functionType == "classmethod": |
356 elif functionType == "classmethod": |
342 yield self.__error(node, "N804") |
357 yield self.__error(node, "N804") |
343 return |
358 return |
344 |
359 |
345 if ( |
360 if functionType == "method" and argNames[0] != "self": |
346 functionType == "method" and |
|
347 argNames[0] != "self" |
|
348 ): |
|
349 yield self.__error(node, "N805") |
361 yield self.__error(node, "N805") |
350 elif ( |
362 elif functionType == "classmethod" and argNames[0] != "cls": |
351 functionType == "classmethod" and |
|
352 argNames[0] != "cls" |
|
353 ): |
|
354 yield self.__error(node, "N804") |
363 yield self.__error(node, "N804") |
355 elif ( |
364 elif functionType == "staticmethod" and argNames[0] in ("cls", "self"): |
356 functionType == "staticmethod" and |
|
357 argNames[0] in ("cls", "self") |
|
358 ): |
|
359 yield self.__error(node, "N806") |
365 yield self.__error(node, "N806") |
360 for arg in argNames: |
366 for arg in argNames: |
361 if not self.LowercaseRegex.match(arg): |
367 if not self.LowercaseRegex.match(arg): |
362 yield self.__error(node, "N803") |
368 yield self.__error(node, "N803") |
363 return |
369 return |
364 |
370 |
365 def __checkVariablesInFunction(self, node, parents): |
371 def __checkVariablesInFunction(self, node, parents): |
366 """ |
372 """ |
367 Private method to check local variables in functions (N821). |
373 Private method to check local variables in functions (N821). |
368 |
374 |
369 Local variables in functions should be lowercase. |
375 Local variables in functions should be lowercase. |
370 |
376 |
371 @param node AST note to check |
377 @param node AST note to check |
372 @param parents list of parent nodes |
378 @param parents list of parent nodes |
373 @yield tuple giving line number, offset within line and error code |
379 @yield tuple giving line number, offset within line and error code |
374 @ytype tuple of (int, int, str) |
380 @ytype tuple of (int, int, str) |
375 """ |
381 """ |
382 return |
388 return |
383 for target in node.targets: |
389 for target in node.targets: |
384 name = isinstance(target, ast.Name) and target.id |
390 name = isinstance(target, ast.Name) and target.id |
385 if not name or name in parentFunc.global_names: |
391 if not name or name in parentFunc.global_names: |
386 return |
392 return |
387 |
393 |
388 if not self.LowercaseRegex.match(name) and name[:1] != '_': |
394 if not self.LowercaseRegex.match(name) and name[:1] != "_": |
389 yield self.__error(target, "N821") |
395 yield self.__error(target, "N821") |
390 |
396 |
391 def __checkModule(self, node, parents): |
397 def __checkModule(self, node, parents): |
392 """ |
398 """ |
393 Private method to check module naming conventions (N807, N808). |
399 Private method to check module naming conventions (N807, N808). |
394 |
400 |
395 Module and package names should be lowercase. |
401 Module and package names should be lowercase. |
396 |
402 |
397 @param node AST note to check |
403 @param node AST note to check |
398 @param parents list of parent nodes |
404 @param parents list of parent nodes |
399 @yield tuple giving line number, offset within line and error code |
405 @yield tuple giving line number, offset within line and error code |
400 @ytype tuple of (int, int, str) |
406 @ytype tuple of (int, int, str) |
401 """ |
407 """ |
402 if self.__filename: |
408 if self.__filename: |
403 moduleName = os.path.splitext(os.path.basename(self.__filename))[0] |
409 moduleName = os.path.splitext(os.path.basename(self.__filename))[0] |
404 if moduleName.lower() != moduleName: |
410 if moduleName.lower() != moduleName: |
405 yield self.__error(node, "N807") |
411 yield self.__error(node, "N807") |
406 |
412 |
407 if moduleName == "__init__": |
413 if moduleName == "__init__": |
408 # we got a package |
414 # we got a package |
409 packageName = ( |
415 packageName = os.path.split(os.path.dirname(self.__filename))[1] |
410 os.path.split(os.path.dirname(self.__filename))[1] |
|
411 ) |
|
412 if packageName.lower() != packageName: |
416 if packageName.lower() != packageName: |
413 yield self.__error(node, "N808") |
417 yield self.__error(node, "N808") |
414 |
418 |
415 def __checkImportAs(self, node, parents): |
419 def __checkImportAs(self, node, parents): |
416 """ |
420 """ |
417 Private method to check that imports don't change the |
421 Private method to check that imports don't change the |
418 naming convention (N811, N812, N813, N814). |
422 naming convention (N811, N812, N813, N814). |
419 |
423 |
420 @param node AST note to check |
424 @param node AST note to check |
421 @param parents list of parent nodes |
425 @param parents list of parent nodes |
422 @yield tuple giving line number, offset within line and error code |
426 @yield tuple giving line number, offset within line and error code |
423 @ytype tuple of (int, int, str) |
427 @ytype tuple of (int, int, str) |
424 """ |
428 """ |
425 for name in node.names: |
429 for name in node.names: |
426 if not name.asname: |
430 if not name.asname: |
427 continue |
431 continue |
428 |
432 |
429 if self.UppercaseRegexp.match(name.name): |
433 if self.UppercaseRegexp.match(name.name): |
430 if not self.UppercaseRegexp.match(name.asname): |
434 if not self.UppercaseRegexp.match(name.asname): |
431 yield self.__error(node, "N811") |
435 yield self.__error(node, "N811") |
432 elif self.LowercaseRegex.match(name.name): |
436 elif self.LowercaseRegex.match(name.name): |
433 if not self.LowercaseRegex.match(name.asname): |
437 if not self.LowercaseRegex.match(name.asname): |