eric6/Plugins/CheckerPlugins/CodeStyleChecker/MiscellaneousChecker.py

changeset 7021
2894aa889a4e
parent 6942
2602857055c5
child 7040
f89952e5fc11
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/MiscellaneousChecker.py	Wed May 22 18:44:36 2019 +0200
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/MiscellaneousChecker.py	Wed May 22 18:54:05 2019 +0200
@@ -46,8 +46,10 @@
         
         "M201",
         
-        "M501", "M502", "M503", "M504", "M505", "M506", "M507",
-        "M511", "M512", "M513", "M514",
+        "M501", "M502", "M503", "M504", "M505", "M506", "M507", "M508",
+        "M509",
+        "M511", "M512", "M513",
+        "M521", "M522", "M523", "M524",
         
         "M601",
         "M611", "M612", "M613",
@@ -133,8 +135,9 @@
                                         "M621", "M622", "M623", "M624", "M625",
                                         "M631", "M632")),
             (self.__checkBugBear, ("M501", "M502", "M503", "M504", "M505",
-                                   "M506", "M507",
-                                   "M511", "M512", "M513", "M514")),
+                                   "M506", "M507", "M508", "M509",
+                                   "M511", "M512", "M513",
+                                   "M521", "M522", "M523", "M524")),
             (self.__checkLogging, ("M651", "M652", "M653", "M654", "M655")),
             (self.__checkFuture, ("M701", "M702")),
             (self.__checkGettext, ("M711",)),
@@ -653,6 +656,10 @@
             "list",
             "set",
         )
+        immutableCalls = (
+            "tuple",
+            "frozenset",
+        )
         functionDefs = [ast.FunctionDef]
         try:
             functionDefs.append(ast.AsyncFunctionDef)
@@ -662,7 +669,7 @@
         for node in ast.walk(self.__tree):
             if any(isinstance(node, functionDef)
                    for functionDef in functionDefs):
-                for default in node.args.defaults:
+                for default in node.args.defaults + node.args.kw_defaults:
                     if any(isinstance(default, mutableType)
                            for mutableType in mutableTypes):
                         typeName = type(default).__name__
@@ -672,7 +679,7 @@
                                 self.__error(default.lineno - 1,
                                              default.col_offset,
                                              "M823", callPath + "()")
-                            else:
+                            elif callPath not in immutableCalls:
                                 self.__error(default.lineno - 1,
                                              default.col_offset,
                                              "M822", typeName)
@@ -731,7 +738,7 @@
     
     def __checkBugBear(self):
         """
-        Private method to bugbear checks.
+        Private method for bugbear checks.
         """
         visitor = BugBearVisitor()
         visitor.visit(self.__tree)
@@ -1079,7 +1086,7 @@
     Class implementing a node visitor to check for various topics.
     """
     #
-    # This class was implemented along the BugBear flake8 extension (v 18.2.0).
+    # This class was implemented along the BugBear flake8 extension (v 19.3.0).
     # Original: Copyright (c) 2016 Ɓukasz Langa
     #
     
@@ -1135,9 +1142,9 @@
         if sys.version_info >= (3, 0):
             validPaths = ("six", "future.utils", "builtins")
             methodsDict = {
-                "M511": ("iterkeys", "itervalues", "iteritems", "iterlists"),
-                "M512": ("viewkeys", "viewvalues", "viewitems", "viewlists"),
-                "M513": ("next",),
+                "M521": ("iterkeys", "itervalues", "iteritems", "iterlists"),
+                "M522": ("viewkeys", "viewvalues", "viewitems", "viewlists"),
+                "M523": ("next",),
             }
         else:
             validPaths = ()
@@ -1154,11 +1161,36 @@
                 self.__checkForM502(node)
         else:
             try:
+                # bad super() call
+                if isinstance(node.func, ast.Name) and node.func.id == "super":
+                    args = node.args
+                    if (
+                        len(args) == 2 and
+                        isinstance(args[0], ast.Attribute) and
+                        isinstance(args[0].value, ast.Name) and
+                        args[0].value.id == 'self' and
+                        args[0].attr == '__class__'
+                    ):
+                        self.violations.append((node, "M509"))
+                
+                # bad getattr and setattr
                 if (
                     node.func.id in ("getattr", "hasattr") and
                     node.args[1].s == "__call__"
                 ):
-                    self.violations.append((node, "M503"))
+                    self.violations.append((node, "M511"))
+                if (
+                    node.func.id == "getattr" and
+                    len(node.args) == 2 and
+                    isinstance(node.args[1], ast.Str)
+                ):
+                    self.violations.append((node, "M512"))
+                elif (
+                    node.func.id == "setattr" and
+                    len(node.args) == 3 and
+                    isinstance(node.args[1], ast.Str)
+                ):
+                    self.violations.append((node, "M513"))
             except (AttributeError, IndexError):
                 pass
 
@@ -1196,7 +1228,7 @@
             # and tuples for simplicity.
             assignTargets = {t.id for t in node.targets if hasattr(t, 'id')}
             if '__metaclass__' in assignTargets and sys.version_info >= (3, 0):
-                self.violations.append((node, "M514"))
+                self.violations.append((node, "M524"))
         
         elif len(node.targets) == 1:
             target = node.targets[0]
@@ -1218,6 +1250,33 @@
         
         self.generic_visit(node)
     
+    def visit_Assert(self, node):
+        """
+        Public method to handle 'assert' statements.
+        
+        @param node reference to the node to be processed
+        @type ast.Assert
+        """
+        if isinstance(node.test, ast.NameConstant) and \
+           node.test.value is False:
+            self.violations.append((node, "M503"))
+        
+        self.generic_visit(node)
+    
+    def visit_JoinedStr(self, node):
+        """
+        Public method to handle f-string arguments.
+        
+        @param node reference to the node to be processed
+        @type ast.JoinedStr
+        """
+        if sys.version_info >= (3, 6):
+            for value in node.values:
+                if isinstance(value, ast.FormattedValue):
+                    return
+            
+            self.violations.append((node, "M508"))
+    
     def __checkForM502(self, node):
         """
         Private method to check the use of *strip().

eric ide

mercurial