19 Class implementing a checker for miscellaneous checks. |
19 Class implementing a checker for miscellaneous checks. |
20 """ |
20 """ |
21 Codes = [ |
21 Codes = [ |
22 "M101", "M102", |
22 "M101", "M102", |
23 "M111", "M112", |
23 "M111", "M112", |
24 "M121", |
|
25 "M131", "M132", |
24 "M131", "M132", |
26 |
25 |
27 "M191", "M192", "M193", "M194", |
26 "M191", "M192", "M193", "M194", |
28 "M195", "M196", "M197", "M198", |
27 "M195", "M196", "M197", "M198", |
29 |
28 |
75 self.__repeat = repeat |
74 self.__repeat = repeat |
76 self.__filename = filename |
75 self.__filename = filename |
77 self.__source = source[:] |
76 self.__source = source[:] |
78 self.__args = args |
77 self.__args = args |
79 |
78 |
80 self.__blindExceptRegex = re.compile( |
|
81 r'(\bexcept:)') # __IGNORE_WARNING__ |
|
82 self.__pep3101FormatRegex = re.compile( |
79 self.__pep3101FormatRegex = re.compile( |
83 r'^(?:[^\'"]*[\'"][^\'"]*[\'"])*\s*%|^\s*%') |
80 r'^(?:[^\'"]*[\'"][^\'"]*[\'"])*\s*%|^\s*%') |
84 |
81 |
85 if sys.version_info >= (3, 0): |
82 if sys.version_info >= (3, 0): |
86 import builtins |
83 import builtins |
98 self.errors = [] |
95 self.errors = [] |
99 |
96 |
100 checkersWithCodes = [ |
97 checkersWithCodes = [ |
101 (self.__checkCoding, ("M101", "M102")), |
98 (self.__checkCoding, ("M101", "M102")), |
102 (self.__checkCopyright, ("M111", "M112")), |
99 (self.__checkCopyright, ("M111", "M112")), |
103 (self.__checkBlindExcept, ("M121",)), |
|
104 (self.__checkBuiltins, ("M131", "M132")), |
100 (self.__checkBuiltins, ("M131", "M132")), |
105 (self.__checkComprehensions, ("M191", "M192", "M193", "M194", |
101 (self.__checkComprehensions, ("M191", "M192", "M193", "M194", |
106 "M195", "M196", "M197", "M198")), |
102 "M195", "M196", "M197", "M198")), |
107 (self.__checkPep3101, ("M601",)), |
103 (self.__checkPep3101, ("M601",)), |
108 (self.__checkFormatString, ("M611", "M612", "M613", |
104 (self.__checkFormatString, ("M611", "M612", "M613", |
277 copyrightAuthorRe = re.compile( |
273 copyrightAuthorRe = re.compile( |
278 copyrightRegexStr.format(author=copyrightAuthor), |
274 copyrightRegexStr.format(author=copyrightAuthor), |
279 re.IGNORECASE) |
275 re.IGNORECASE) |
280 if not copyrightAuthorRe.search(topOfSource): |
276 if not copyrightAuthorRe.search(topOfSource): |
281 self.__error(0, 0, "M112") |
277 self.__error(0, 0, "M112") |
282 |
|
283 def __checkBlindExcept(self): |
|
284 """ |
|
285 Private method to check for blind except statements. |
|
286 """ |
|
287 for lineno, line in enumerate(self.__source): |
|
288 match = self.__blindExceptRegex.search(line) |
|
289 if match: |
|
290 self.__error(lineno, match.start(), "M121") |
|
291 |
278 |
292 def __checkPrintStatements(self): |
279 def __checkPrintStatements(self): |
293 """ |
280 """ |
294 Private method to check for print statements. |
281 Private method to check for print statements. |
295 """ |
282 """ |
508 if isinstance(node, ast.Assign): |
495 if isinstance(node, ast.Assign): |
509 # assign statement |
496 # assign statement |
510 for element in node.targets: |
497 for element in node.targets: |
511 if isinstance(element, ast.Name) and \ |
498 if isinstance(element, ast.Name) and \ |
512 element.id in self.__builtins: |
499 element.id in self.__builtins: |
|
500 value = node.value |
|
501 if isinstance(value, ast.Name) and \ |
|
502 value.id in ["unicode", "unichr"]: |
|
503 # ignore compatibility assignments |
|
504 # TODO: make this configurable |
|
505 continue |
513 self.__error(element.lineno - 1, element.col_offset, |
506 self.__error(element.lineno - 1, element.col_offset, |
514 "M131", element.id) |
507 "M131", element.id) |
515 elif isinstance(element, (ast.Tuple, ast.List)): |
508 elif isinstance(element, (ast.Tuple, ast.List)): |
516 for tupleElement in element.elts: |
509 for tupleElement in element.elts: |
517 if isinstance(tupleElement, ast.Name) and \ |
510 if isinstance(tupleElement, ast.Name) and \ |