eric6/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/MiscellaneousChecker.py

branch
maintenance
changeset 8043
0acf98cd089a
parent 7924
8a96736d465e
parent 7988
c4c17121eff8
child 8176
31965986ecd1
equal deleted inserted replaced
7991:866adc8c315b 8043:0acf98cd089a
15 from collections import defaultdict 15 from collections import defaultdict
16 import tokenize 16 import tokenize
17 17
18 import AstUtilities 18 import AstUtilities
19 19
20 from eradicate import Eradicator
21
22 from .MiscellaneousDefaults import MiscellaneousCheckerDefaultArgs
23
20 24
21 def composeCallPath(node): 25 def composeCallPath(node):
22 """ 26 """
23 Generator function to assemble the call path of a given node. 27 Generator function to assemble the call path of a given node.
24 28
25 @param node node to assemble call path for 29 @param node node to assemble call path for
26 @type ast.Node 30 @type ast.Node
27 @return call path components 31 @yield call path components
28 @rtype str 32 @ytype str
29 """ 33 """
30 if isinstance(node, ast.Attribute): 34 if isinstance(node, ast.Attribute):
31 for v in composeCallPath(node.value): 35 for v in composeCallPath(node.value):
32 yield v 36 yield v
33 yield node.attr 37 yield node.attr
152 r'^(?:[^\'"]*[\'"][^\'"]*[\'"])*\s*%|^\s*%') 156 r'^(?:[^\'"]*[\'"][^\'"]*[\'"])*\s*%|^\s*%')
153 157
154 import builtins 158 import builtins
155 self.__builtins = [b for b in dir(builtins) 159 self.__builtins = [b for b in dir(builtins)
156 if b not in self.BuiltinsWhiteList] 160 if b not in self.BuiltinsWhiteList]
161
162 self.__eradicator = Eradicator()
157 163
158 # statistics counters 164 # statistics counters
159 self.counters = {} 165 self.counters = {}
160 166
161 # collection of detected errors 167 # collection of detected errors
193 (self.__checkReturn, ("M831", "M832", "M833", "M834")), 199 (self.__checkReturn, ("M831", "M832", "M833", "M834")),
194 (self.__checkLineContinuation, ("M841",)), 200 (self.__checkLineContinuation, ("M841",)),
195 (self.__checkCommentedCode, ("M891",)), 201 (self.__checkCommentedCode, ("M891",)),
196 ] 202 ]
197 203
198 self.__defaultArgs = { 204 # the eradicate whitelist
199 "BuiltinsChecker": { 205 commentedCodeCheckerArgs = self.__args.get(
200 "chr": ["unichr", ], 206 "CommentedCodeChecker",
201 "str": ["unicode", ], 207 MiscellaneousCheckerDefaultArgs["CommentedCodeChecker"])
202 }, 208 commentedCodeCheckerWhitelist = commentedCodeCheckerArgs.get(
203 "CodingChecker": 'latin-1, utf-8', 209 "WhiteList",
204 "CopyrightChecker": { 210 MiscellaneousCheckerDefaultArgs[
205 "Author": "", 211 "CommentedCodeChecker"]["WhiteList"])
206 "MinFilesize": 0, 212 self.__eradicator.update_whitelist(commentedCodeCheckerWhitelist,
207 }, 213 extend_default=False)
208 "CommentedCodeChecker": {
209 "Aggressive": False,
210 }
211 }
212 214
213 self.__checkers = [] 215 self.__checkers = []
214 for checker, codes in checkersWithCodes: 216 for checker, codes in checkersWithCodes:
215 if any(not (code and self.__ignoreCode(code)) 217 if any(not (code and self.__ignoreCode(code))
216 for code in codes): 218 for code in codes):
334 if len(self.__source) == 0: 336 if len(self.__source) == 0:
335 return 337 return
336 338
337 encodings = [e.lower().strip() 339 encodings = [e.lower().strip()
338 for e in self.__args.get( 340 for e in self.__args.get(
339 "CodingChecker", self.__defaultArgs["CodingChecker"]) 341 "CodingChecker",
342 MiscellaneousCheckerDefaultArgs["CodingChecker"])
340 .split(",")] 343 .split(",")]
341 lineno, coding = self.__getCoding() 344 lineno, coding = self.__getCoding()
342 if coding: 345 if coding:
343 if coding.lower() not in encodings: 346 if coding.lower() not in encodings:
344 self.__error(lineno, 0, "M102", coding) 347 self.__error(lineno, 0, "M102", coding)
349 """ 352 """
350 Private method to check the presence of a copyright statement. 353 Private method to check the presence of a copyright statement.
351 """ 354 """
352 source = "".join(self.__source) 355 source = "".join(self.__source)
353 copyrightArgs = self.__args.get( 356 copyrightArgs = self.__args.get(
354 "CopyrightChecker", self.__defaultArgs["CopyrightChecker"]) 357 "CopyrightChecker",
358 MiscellaneousCheckerDefaultArgs["CopyrightChecker"])
355 copyrightMinFileSize = copyrightArgs.get( 359 copyrightMinFileSize = copyrightArgs.get(
356 "MinFilesize", 360 "MinFilesize",
357 self.__defaultArgs["CopyrightChecker"]["MinFilesize"]) 361 MiscellaneousCheckerDefaultArgs["CopyrightChecker"]["MinFilesize"])
358 copyrightAuthor = copyrightArgs.get( 362 copyrightAuthor = copyrightArgs.get(
359 "Author", 363 "Author",
360 self.__defaultArgs["CopyrightChecker"]["Author"]) 364 MiscellaneousCheckerDefaultArgs["CopyrightChecker"]["Author"])
361 copyrightRegexStr = ( 365 copyrightRegexStr = (
362 r"Copyright\s+(\(C\)\s+)?(\d{{4}}\s+-\s+)?\d{{4}}\s+{author}" 366 r"Copyright\s+(\(C\)\s+)?(\d{{4}}\s+-\s+)?\d{{4}}\s+{author}"
363 ) 367 )
364 368
365 tocheck = max(1024, copyrightMinFileSize) 369 tocheck = max(1024, copyrightMinFileSize)
382 386
383 def __checkCommentedCode(self): 387 def __checkCommentedCode(self):
384 """ 388 """
385 Private method to check for commented code. 389 Private method to check for commented code.
386 """ 390 """
387 from eradicate import commented_out_code_line_numbers
388
389 source = "".join(self.__source) 391 source = "".join(self.__source)
390 commentedCodeCheckerArgs = self.__args.get( 392 commentedCodeCheckerArgs = self.__args.get(
391 "CommentedCodeChecker", self.__defaultArgs["CommentedCodeChecker"]) 393 "CommentedCodeChecker",
394 MiscellaneousCheckerDefaultArgs["CommentedCodeChecker"])
392 aggressive = commentedCodeCheckerArgs.get( 395 aggressive = commentedCodeCheckerArgs.get(
393 "Aggressive", 396 "Aggressive",
394 self.__defaultArgs["CommentedCodeChecker"]["Aggressive"]) 397 MiscellaneousCheckerDefaultArgs[
395 for markedLine in commented_out_code_line_numbers( 398 "CommentedCodeChecker"]["Aggressive"])
399 for markedLine in self.__eradicator.commented_out_code_line_numbers(
396 source, aggressive=aggressive): 400 source, aggressive=aggressive):
397 self.__error(markedLine - 1, 0, "M891") 401 self.__error(markedLine - 1, 0, "M891")
398 402
399 def __checkLineContinuation(self): 403 def __checkLineContinuation(self):
400 """ 404 """
556 560
557 keywords = {keyword.arg for keyword in call.keywords} 561 keywords = {keyword.arg for keyword in call.keywords}
558 numArgs = len(call.args) 562 numArgs = len(call.args)
559 if strArgs: 563 if strArgs:
560 numArgs -= 1 564 numArgs -= 1
561 if sys.version_info < (3, 5): 565 hasKwArgs = any(kw.arg is None for kw in call.keywords)
562 hasKwArgs = bool(call.kwargs) 566 hasStarArgs = sum(1 for arg in call.args
563 hasStarArgs = bool(call.starargs) 567 if isinstance(arg, ast.Starred))
564 else: 568
565 hasKwArgs = any(kw.arg is None for kw in call.keywords) 569 if hasKwArgs:
566 hasStarArgs = sum(1 for arg in call.args 570 keywords.discard(None)
567 if isinstance(arg, ast.Starred)) 571 if hasStarArgs:
568 572 numArgs -= 1
569 if hasKwArgs:
570 keywords.discard(None)
571 if hasStarArgs:
572 numArgs -= 1
573 573
574 # if starargs or kwargs is not None, it can't count the 574 # if starargs or kwargs is not None, it can't count the
575 # parameters but at least check if the args are used 575 # parameters but at least check if the args are used
576 if hasKwArgs: 576 if hasKwArgs:
577 if not names: 577 if not names:
647 functionDefs.append(ast.AsyncFunctionDef) 647 functionDefs.append(ast.AsyncFunctionDef)
648 except AttributeError: 648 except AttributeError:
649 pass 649 pass
650 650
651 ignoreBuiltinAssignments = self.__args.get( 651 ignoreBuiltinAssignments = self.__args.get(
652 "BuiltinsChecker", self.__defaultArgs["BuiltinsChecker"]) 652 "BuiltinsChecker",
653 MiscellaneousCheckerDefaultArgs["BuiltinsChecker"])
653 654
654 for node in ast.walk(self.__tree): 655 for node in ast.walk(self.__tree):
655 if isinstance(node, ast.Assign): 656 if isinstance(node, ast.Assign):
656 # assign statement 657 # assign statement
657 for element in node.targets: 658 for element in node.targets:
1292 Public method to handle f-string arguments. 1293 Public method to handle f-string arguments.
1293 1294
1294 @param node reference to the node to be processed 1295 @param node reference to the node to be processed
1295 @type ast.JoinedStr 1296 @type ast.JoinedStr
1296 """ 1297 """
1297 if sys.version_info >= (3, 6): 1298 if self.__withinLoggingStatement():
1298 if self.__withinLoggingStatement(): 1299 if any(isinstance(i, ast.FormattedValue) for i in node.values):
1299 if any(isinstance(i, ast.FormattedValue) for i in node.values): 1300 if self.__withinLoggingArgument():
1300 if self.__withinLoggingArgument(): 1301 self.violations.append((node, "M654"))
1301 self.violations.append((node, "M654")) 1302
1302 1303 super(LoggingVisitor, self).generic_visit(node)
1303 super(LoggingVisitor, self).generic_visit(node)
1304 1304
1305 1305
1306 class BugBearVisitor(ast.NodeVisitor): 1306 class BugBearVisitor(ast.NodeVisitor):
1307 """ 1307 """
1308 Class implementing a node visitor to check for various topics. 1308 Class implementing a node visitor to check for various topics.
1502 Public method to handle f-string arguments. 1502 Public method to handle f-string arguments.
1503 1503
1504 @param node reference to the node to be processed 1504 @param node reference to the node to be processed
1505 @type ast.JoinedStr 1505 @type ast.JoinedStr
1506 """ 1506 """
1507 if sys.version_info >= (3, 6): 1507 for value in node.values:
1508 for value in node.values: 1508 if isinstance(value, ast.FormattedValue):
1509 if isinstance(value, ast.FormattedValue): 1509 return
1510 return 1510
1511 1511 self.violations.append((node, "M508"))
1512 self.violations.append((node, "M508"))
1513 1512
1514 def __checkForM502(self, node): 1513 def __checkForM502(self, node):
1515 """ 1514 """
1516 Private method to check the use of *strip(). 1515 Private method to check the use of *strip().
1517 1516

eric ide

mercurial