Plugins/CheckerPlugins/CodeStyleChecker/MiscellaneousChecker.py

changeset 6184
789e88d94899
parent 6183
29384109306c
child 6188
5a6ae3be31e6
equal deleted inserted replaced
6183:29384109306c 6184:789e88d94899
43 "M191", "M192", "M193", "M194", 43 "M191", "M192", "M193", "M194",
44 "M195", "M196", "M197", "M198", 44 "M195", "M196", "M197", "M198",
45 45
46 "M201", 46 "M201",
47 47
48 "M501", "M502", "M503", "M504", "M505", 48 "M501", "M502", "M503", "M504", "M505", "M506", "M507",
49 "M511", "M512", "M513", 49 "M511", "M512", "M513", "M514",
50 50
51 "M601", 51 "M601",
52 "M611", "M612", "M613", 52 "M611", "M612", "M613",
53 "M621", "M622", "M623", "M624", "M625", 53 "M621", "M622", "M623", "M624", "M625",
54 "M631", "M632", 54 "M631", "M632",
128 (self.__checkDictWithSortedKeys, ("M201",)), 128 (self.__checkDictWithSortedKeys, ("M201",)),
129 (self.__checkPep3101, ("M601",)), 129 (self.__checkPep3101, ("M601",)),
130 (self.__checkFormatString, ("M611", "M612", "M613", 130 (self.__checkFormatString, ("M611", "M612", "M613",
131 "M621", "M622", "M623", "M624", "M625", 131 "M621", "M622", "M623", "M624", "M625",
132 "M631", "M632")), 132 "M631", "M632")),
133 (self.__checkBugBear, ("M501", "M502", "M503", "M504", "M505", "M511", "M512", "M513",)), 133 (self.__checkBugBear, ("M501", "M502", "M503", "M504", "M505",
134 "M506", "M507",
135 "M511", "M512", "M513", "M514")),
134 (self.__checkLogging, ("M651", "M652", "M653", "M654", "M655")), 136 (self.__checkLogging, ("M651", "M652", "M653", "M654", "M655")),
135 (self.__checkFuture, ("M701", "M702")), 137 (self.__checkFuture, ("M701", "M702")),
136 (self.__checkGettext, ("M711",)), 138 (self.__checkGettext, ("M711",)),
137 (self.__checkPrintStatements, ("M801",)), 139 (self.__checkPrintStatements, ("M801",)),
138 (self.__checkTuple, ("M811", )), 140 (self.__checkTuple, ("M811", )),
523 525
524 def __checkBuiltins(self): 526 def __checkBuiltins(self):
525 """ 527 """
526 Private method to check, if built-ins are shadowed. 528 Private method to check, if built-ins are shadowed.
527 """ 529 """
530 functionDefs = [ast.FunctionDef]
531 try:
532 functionDefs.append(ast.AsyncFunctionDef)
533 except AttributeError:
534 pass
535
528 ignoreBuiltinAssignments = self.__args.get( 536 ignoreBuiltinAssignments = self.__args.get(
529 "BuiltinsChecker", self.__defaultArgs["BuiltinsChecker"]) 537 "BuiltinsChecker", self.__defaultArgs["BuiltinsChecker"])
530 538
531 for node in ast.walk(self.__tree): 539 for node in ast.walk(self.__tree):
532 if isinstance(node, ast.Assign): 540 if isinstance(node, ast.Assign):
561 if isinstance(element, ast.Name) and \ 569 if isinstance(element, ast.Name) and \
562 element.id in self.__builtins: 570 element.id in self.__builtins:
563 self.__error(element.lineno - 1, 571 self.__error(element.lineno - 1,
564 element.col_offset, 572 element.col_offset,
565 "M131", element.id) 573 "M131", element.id)
566 elif isinstance(node, ast.FunctionDef): 574 elif any(isinstance(node, functionDef)
567 # function definition 575 for functionDef in functionDefs):
576 # (asynchronous) function definition
568 if sys.version_info >= (3, 0): 577 if sys.version_info >= (3, 0):
569 for arg in node.args.args: 578 for arg in node.args.args:
570 if isinstance(arg, ast.arg) and \ 579 if isinstance(arg, ast.arg) and \
571 arg.arg in self.__builtins: 580 arg.arg in self.__builtins:
572 self.__error(arg.lineno - 1, arg.col_offset, 581 self.__error(arg.lineno - 1, arg.col_offset,
638 "deque", 647 "deque",
639 "dict", 648 "dict",
640 "list", 649 "list",
641 "set", 650 "set",
642 ) 651 )
652 functionDefs = [ast.FunctionDef]
653 try:
654 functionDefs.append(ast.AsyncFunctionDef)
655 except AttributeError:
656 pass
643 657
644 for node in ast.walk(self.__tree): 658 for node in ast.walk(self.__tree):
645 if isinstance(node, ast.FunctionDef): 659 if any(isinstance(node, functionDef)
660 for functionDef in functionDefs):
646 for default in node.args.defaults: 661 for default in node.args.defaults:
647 if any(isinstance(default, mutableType) 662 if any(isinstance(default, mutableType)
648 for mutableType in mutableTypes): 663 for mutableType in mutableTypes):
649 typeName = type(default).__name__ 664 typeName = type(default).__name__
650 if isinstance(default, ast.Call): 665 if isinstance(default, ast.Call):
714 """ 729 """
715 Private method to bugbear checks. 730 Private method to bugbear checks.
716 """ 731 """
717 visitor = BugBearVisitor() 732 visitor = BugBearVisitor()
718 visitor.visit(self.__tree) 733 visitor.visit(self.__tree)
719 for node, reason in visitor.violations: 734 for violation in visitor.violations:
720 self.__error(node.lineno - 1, node.col_offset, reason) 735 node = violation[0]
736 reason = violation[1]
737 params = violation[2:]
738 self.__error(node.lineno - 1, node.col_offset, reason, *params)
721 739
722 740
723 class TextVisitor(ast.NodeVisitor): 741 class TextVisitor(ast.NodeVisitor):
724 """ 742 """
725 Class implementing a node visitor for bytes and str instances. 743 Class implementing a node visitor for bytes and str instances.
783 def __visitDefinition(self, node): 801 def __visitDefinition(self, node):
784 """ 802 """
785 Private method handling class and function definitions. 803 Private method handling class and function definitions.
786 804
787 @param node reference to the node to handle 805 @param node reference to the node to handle
788 @type ast.FunctionDef or ast.ClassDef 806 @type ast.FunctionDef, ast.AsyncFunctionDef or ast.ClassDef
789 """ 807 """
790 # Manually traverse class or function definition 808 # Manually traverse class or function definition
791 # * Handle decorators normally 809 # * Handle decorators normally
792 # * Use special check for body content 810 # * Use special check for body content
793 # * Don't handle the rest (e.g. bases) 811 # * Don't handle the rest (e.g. bases)
835 """ 853 """
836 Public method to handle a function definition. 854 Public method to handle a function definition.
837 855
838 @param node reference to the node to handle 856 @param node reference to the node to handle
839 @type ast.FunctionDef 857 @type ast.FunctionDef
858 """
859 # Skipped nodes: ('name', 'args', 'returns')
860 self.__visitDefinition(node)
861
862 def visit_AsyncFunctionDef(self, node):
863 """
864 Public method to handle an asynchronous function definition.
865
866 @param node reference to the node to handle
867 @type ast.AsyncFunctionDef
840 """ 868 """
841 # Skipped nodes: ('name', 'args', 'returns') 869 # Skipped nodes: ('name', 'args', 'returns')
842 self.__visitDefinition(node) 870 self.__visitDefinition(node)
843 871
844 def visit_Call(self, node): 872 def visit_Call(self, node):
1139 for elem in reversed(self.__nodeStack[:-1]): 1167 for elem in reversed(self.__nodeStack[:-1]):
1140 if isinstance(elem, ast.ExceptHandler) and elem.name == name: 1168 if isinstance(elem, ast.ExceptHandler) and elem.name == name:
1141 self.violations.append((node, "M505")) 1169 self.violations.append((node, "M505"))
1142 break 1170 break
1143 1171
1172 def visit_Assign(self, node):
1173 """
1174 Public method to handle assignments.
1175
1176 @param node reference to the node to be processed
1177 @type ast.Assign
1178 """
1179 if isinstance(self.__nodeStack[-2], ast.ClassDef):
1180 # By using 'hasattr' below we're ignoring starred arguments, slices
1181 # and tuples for simplicity.
1182 assignTargets = {t.id for t in node.targets if hasattr(t, 'id')}
1183 if '__metaclass__' in assignTargets and sys.version_info >= (3, 0):
1184 self.violations.append((node, "M514"))
1185
1186 elif len(node.targets) == 1:
1187 target = node.targets[0]
1188 if isinstance(target, ast.Attribute) and \
1189 isinstance(target.value, ast.Name):
1190 if (target.value.id, target.attr) == ('os', 'environ'):
1191 self.violations.append((node, "M506"))
1192
1193 self.generic_visit(node)
1194
1195 def visit_For(self, node):
1196 """
1197 Public method to handle 'for' statements.
1198
1199 @param node reference to the node to be processed
1200 @type ast.For
1201 """
1202 self.__checkForM507(node)
1203
1204 self.generic_visit(node)
1205
1144 def __checkForM502(self, node): 1206 def __checkForM502(self, node):
1145 """ 1207 """
1146 Private method to check the use of *strip(). 1208 Private method to check the use of *strip().
1147 1209
1148 @param node reference to the node to be processed 1210 @param node reference to the node to be processed
1160 1222
1161 if len(s) == len(set(s)): 1223 if len(s) == len(set(s)):
1162 return # no characters appear more than once 1224 return # no characters appear more than once
1163 1225
1164 self.violations.append((node, "M502")) 1226 self.violations.append((node, "M502"))
1227
1228 def __checkForM507(self, node):
1229 """
1230 Private method to check for unused loop variables.
1231
1232 @param node reference to the node to be processed
1233 @type ast.For
1234 """
1235 targets = NameFinder()
1236 targets.visit(node.target)
1237 ctrlNames = set(filter(lambda s: not s.startswith('_'),
1238 targets.getNames()))
1239 body = NameFinder()
1240 for expr in node.body:
1241 body.visit(expr)
1242 usedNames = set(body.getNames())
1243 for name in sorted(ctrlNames - usedNames):
1244 n = targets.getNames()[name][0]
1245 self.violations.append((n, "M507", name))
1246
1247
1248 class NameFinder(ast.NodeVisitor):
1249 """
1250 Class to extract a name out of a tree of nodes.
1251 """
1252 def __init__(self):
1253 """
1254 Constructor
1255 """
1256 super(NameFinder, self).__init__()
1257
1258 self.__names = {}
1259
1260 def visit_Name(self, node):
1261 """
1262 Public method to handle 'Name' nodes.
1263
1264 @param node reference to the node to be processed
1265 @type ast.Name
1266 """
1267 self.__names.setdefault(node.id, []).append(node)
1268
1269 def visit(self, node):
1270 """
1271 Public method to traverse a given AST node.
1272
1273 @param node AST node to be traversed
1274 @type ast.Node
1275 """
1276 if isinstance(node, list):
1277 for elem in node:
1278 super(NameFinder, self).visit(elem)
1279 else:
1280 super(NameFinder, self).visit(node)
1281
1282 def getNames(self):
1283 """
1284 Public method to return the extracted names and Name nodes.
1285
1286 @return dictionary containing the names as keys and the list of nodes
1287 @rtype dict
1288 """
1289 return self.__names
1165 1290
1166 # 1291 #
1167 # eflag: noqa = M702 1292 # eflag: noqa = M702

eric ide

mercurial