Plugins/CheckerPlugins/CodeStyleChecker/MiscellaneousChecker.py

changeset 4509
7797ee4a45f9
parent 4508
a3b38825acf0
child 4510
43437fc9f4c9
equal deleted inserted replaced
4508:a3b38825acf0 4509:7797ee4a45f9
21 Codes = [ 21 Codes = [
22 "M101", "M102", 22 "M101", "M102",
23 "M111", "M112", 23 "M111", "M112",
24 "M121", 24 "M121",
25 "M131", 25 "M131",
26 "M701", "M702", "M703", "M704", "M705", "M706", 26 "M701", "M702",
27 "M721", "M722", "M723", "M724", "M725", "M726",
28 "M801", 27 "M801",
29 "M811", 28 "M811",
30 29
31 "M901", 30 "M901",
32 ] 31 ]
62 self.__blindExceptRegex = re.compile( 61 self.__blindExceptRegex = re.compile(
63 r'(except:)') # __IGNORE_WARNING__ 62 r'(except:)') # __IGNORE_WARNING__
64 self.__pep3101FormatRegex = re.compile( 63 self.__pep3101FormatRegex = re.compile(
65 r'^(?:[^\'"]*[\'"][^\'"]*[\'"])*\s*%|^\s*%') 64 r'^(?:[^\'"]*[\'"][^\'"]*[\'"])*\s*%|^\s*%')
66 65
67 self.__availableFutureImports = {
68 # future import: (code missing, code present)
69 'division': ("M701", "M721"),
70 'absolute_import': ("M702", "M722"),
71 'with_statement': ("M703", "M723"),
72 'print_function': ("M704", "M724"),
73 'unicode_literals': ("M705", "M725"),
74 'generator_stop': ("M706", "M726"),
75 }
76
77 # statistics counters 66 # statistics counters
78 self.counters = {} 67 self.counters = {}
79 68
80 # collection of detected errors 69 # collection of detected errors
81 self.errors = [] 70 self.errors = []
86 (self.__checkCopyright, ("M111", "M112")), 75 (self.__checkCopyright, ("M111", "M112")),
87 (self.__checkBlindExcept, ("M121",)), 76 (self.__checkBlindExcept, ("M121",)),
88 (self.__checkPep3101, ("M131",)), 77 (self.__checkPep3101, ("M131",)),
89 (self.__checkPrintStatements, ("M801",)), 78 (self.__checkPrintStatements, ("M801",)),
90 (self.__checkTuple, ("M811", )), 79 (self.__checkTuple, ("M811", )),
91 (self.__checkFuture, ("M701", "M702", "M703", "M704", "M705", 80 (self.__checkFuture, ("M701", "M702")),
92 "M706", "M721", "M722", "M723", "M724",
93 "M725", "M726")),
94 ] 81 ]
95 82
96 self.__defaultArgs = { 83 self.__defaultArgs = {
97 "CodingChecker": 'latin-1, utf-8', 84 "CodingChecker": 'latin-1, utf-8',
98 "CopyrightChecker": { 85 "CopyrightChecker": {
294 281
295 def __checkFuture(self): 282 def __checkFuture(self):
296 """ 283 """
297 Private method to check the __future__ imports. 284 Private method to check the __future__ imports.
298 """ 285 """
299 visitor = FutureImportVisitor() 286 expectedImports = set(
300 visitor.visit(self.__tree) 287 [i.strip()
301 if not visitor.hasCode: 288 for i in self.__args.get("FutureChecker", "").split(",")
302 return 289 if bool(i.strip())])
303 290 if len(expectedImports) == 0:
304 present = set() 291 # nothing to check for; disabling the check
305 for importNode in visitor.futureImports: 292 return
306 for alias in importNode.names: 293
307 if alias.name not in self.__availableFutureImports: 294 imports = set()
308 # unknown code 295 node = None
309 continue 296
310 self.__error(importNode.lineno - 1, 0, 297 for node in ast.walk(self.__tree):
311 self.__availableFutureImports[alias.name][1]) 298 if (isinstance(node, ast.ImportFrom) and
312 present.add(alias.name) 299 node.module == '__future__'):
313 for name in self.__availableFutureImports: 300 imports |= set(name.name for name in node.names)
314 if name not in present: 301 elif isinstance(node, ast.Expr):
315 self.__error(0, 0, 302 if not isinstance(node.value, ast.Str):
316 self.__availableFutureImports[name][0]) 303 break
317 304 elif not isinstance(node, ast.Module):
318 305 break
319 class FutureImportVisitor(ast.NodeVisitor): 306
320 """ 307 if isinstance(node, ast.Module):
321 Class implementing a node visitor to look for __future__ imports. 308 return
322 """ 309
323 def __init__(self): 310 if not (imports >= expectedImports):
324 """ 311 if imports:
325 Constructor 312 self.__error(node.lineno - 1, node.col_offset, "M701",
326 """ 313 ", ".join(expectedImports), ", ".join(imports))
327 super(FutureImportVisitor, self).__init__() 314 else:
328 self.futureImports = [] 315 self.__error(node.lineno - 1, node.col_offset, "M702",
329 self.__hasCode = False 316 ", ".join(expectedImports))
330
331 def visit_ImportFrom(self, node):
332 """
333 Public method to analyze an 'from ... import ...' node.
334
335 @param node reference to the ImportFrom node
336 @type ast.AST
337 """
338 if node.module == '__future__':
339 self.futureImports += [node]
340
341 def visit_Expr(self, node):
342 """
343 Public method to analyze an expression node.
344
345 @param node reference to the expression node
346 @type ast.AST
347 """
348 if not isinstance(node.value, ast.Str) or node.value.col_offset != 0:
349 self.__hasCode = True
350
351 def generic_visit(self, node):
352 """
353 Public method to analyze any other node.
354
355 @param node reference to the node
356 @type ast.AST
357 """
358 if not isinstance(node, ast.Module):
359 self.__hasCode = True
360 super(FutureImportVisitor, self).generic_visit(node)
361
362 @property
363 def hasCode(self):
364 """
365 Public method to check for the presence of some code.
366 """
367 return self.__hasCode or self.futureImports

eric ide

mercurial