Code Style Checker

Sat, 10 Apr 2021 15:11:43 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 10 Apr 2021 15:11:43 +0200
changeset 8211
8322a6f219ff
parent 8210
b5903eaa7a7b
child 8212
91015c7ace79

Code Style Checker
- don't treat 'if __name__ == "__main__":' as an issue
- added a check for if-blocks which only check if a key is in a dictionary
- added a check for bare boolean function arguments
- added a check for bare numeric function arguments

eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py file | annotate | diff | comparison | revisions
eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyNodeVisitor.py file | annotate | diff | comparison | revisions
eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/translations.py file | annotate | diff | comparison | revisions
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py	Sat Apr 10 13:02:08 2021 +0200
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyChecker.py	Sat Apr 10 15:11:43 2021 +0200
@@ -21,7 +21,7 @@
         # Python-specifics
         "Y101", "Y102", "Y103", "Y104", "Y105", "Y106", "Y107", "Y108",
         "Y109", "Y110", "Y111", "Y112", "Y113", "Y114", "Y115", "Y116",
-        "Y117", "Y118", "Y119", "Y120", "Y121",
+        "Y117", "Y118", "Y119", "Y120", "Y121", "Y122",
        
         # Python-specifics not part of flake8-simplify
        "Y181", "Y182",
@@ -33,6 +33,9 @@
         
         # Opinionated
         "Y301",
+        
+        # General Code Style
+        "Y401", "Y402",
     ]
     
     def __init__(self, source, filename, tree, selected, ignored, expected,
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyNodeVisitor.py	Sat Apr 10 13:02:08 2021 +0200
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyNodeVisitor.py	Sat Apr 10 15:11:43 2021 +0200
@@ -120,6 +120,7 @@
         self.__check108(node)
         self.__check114(node)
         self.__check116(node)
+        self.__check122(node)
         
         self.generic_visit(node)
     
@@ -171,6 +172,8 @@
         """
         self.__check115(node)
         self.__check182(node)
+        self.__check401(node)
+        self.__check402(node)
         
         self.generic_visit(node)
     
@@ -208,7 +211,7 @@
         self.__classDefinitionStack.append(node.name)
         
         self.__check119(node)
-        self.__check120(node)
+        self.__check120_121(node)
         
         self.generic_visit(node)
         
@@ -433,6 +436,17 @@
         @param node reference to the AST node to be checked
         @type ast.If
         """
+        # Don't treat 'if __name__ == "__main__":' as an issue.
+        if (
+            isinstance(node.test, ast.Compare) and
+            isinstance(node.test.left, ast.Name) and
+            node.test.left.id == "__name__" and
+            isinstance(node.test.ops[0], ast.Eq) and
+            isinstance(node.test.comparators[0], ast.Constant) and
+            node.test.comparators[0].value == "__main__"
+        ):
+            return
+        
         # ## Pattern 1
         # if a: <---
         #     if b: <---
@@ -444,7 +458,7 @@
             node.body[0].orelse == []
         )
         # ## Pattern 2
-        # if a: < irrelvant for here
+        # if a: < irrelevant for here
         #     pass
         # elif b:  <--- this is treated like a nested block
         #     if c: <---
@@ -712,7 +726,7 @@
                              check, target, iterable)
             elif node.body[0].body[0].value.value is False:
                 check = "not " + check
-                if check.startswith("not not"):
+                if check.startswith("not not "):
                     check = check[len("not not "):]
                 self.__error(node.lineno - 1, node.col_offset, "Y111",
                              check, target, iterable)
@@ -1059,7 +1073,7 @@
                 self.__error(node.lineno - 1, node.col_offset, "Y119",
                              node.name)
     
-    def __check120(self, node):
+    def __check120_121(self, node):
         """
         Private method to check for classes that inherit from object.
         
@@ -1084,6 +1098,34 @@
             self.__error(node.lineno - 1, node.col_offset, "Y121",
                          node.name, ", ".join(b.id for b in node.bases[:-1]))
     
+    def __check122(self, node):
+        """
+        Private method to check for all if-blocks which only check if a key
+        is in a dictionary.
+        
+        @param node reference to the AST node to be checked
+        @type ast.If
+        """
+        if (
+            isinstance(node.test, ast.Compare) and
+            len(node.test.ops) == 1 and
+            isinstance(node.test.ops[0], ast.In) and
+            len(node.body) == 1 and
+            len(node.orelse) == 0
+        ) and (
+            # We might still be left with a check if a value is in a list or
+            # in the body the developer might remove the element from the list.
+            # We need to have a look at the body.
+            isinstance(node.body[0], ast.Assign) and
+            isinstance(node.body[0].value, ast.Subscript) and
+            len(node.body[0].targets) == 1 and
+            isinstance(node.body[0].targets[0], ast.Name)
+        ):
+            key = unparse(node.test.left)
+            dictname = unparse(node.test.comparators[0])
+            self.__error(node.lineno - 1, node.col_offset, "Y122",
+                         dictname, key)
+    
     def __check181(self, node):
         """
         Private method to check for assignments that could be converted into
@@ -1494,6 +1536,54 @@
             right = unparse(node.comparators[0])
             self.__error(node.lineno - 1, node.col_offset, "Y301",
                          left, right)
+    
+    def __check401(self, node):
+        """
+        Private method to check for bare boolean function arguments.
+        
+        @param node reference to the AST node to be checked
+        @type ast.Call
+        """
+        # foo(a, b, True)
+        hasBareBool = any(
+            isinstance(callArg, ast.Constant) and
+            (callArg.value is True or callArg.value is False)
+            for callArg in node.args
+        )
+
+        isException = (
+            isinstance(node.func, ast.Attribute) and
+            node.func.attr in ["get"]
+        )
+        
+        if hasBareBool and not isException:
+            self.__error(node.lineno - 1, node.col_offset, "Y401")
+    
+    def __check402(self, node):
+        """
+        Private method to check for bare numeric function arguments.
+        
+        @param node reference to the AST node to be checked
+        @type ast.Call
+        """
+        # foo(a, b, 123123)
+        hasBareNumeric = any(
+            isinstance(callArg, ast.Constant) and
+            type(callArg.value) in (float, int)
+            for callArg in node.args
+        )
+
+        isException = (
+            isinstance(node.func, ast.Name) and
+            node.func.id == "range"
+        )
+        isException = isException or (
+            isinstance(node.func, ast.Attribute) and
+            node.func.attr in ["get", "insert",]
+        )
+        
+        if hasBareNumeric and not isException:
+            self.__error(node.lineno - 1, node.col_offset, "Y402")
 
 #
 # eflag: noqa = M891
--- a/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/translations.py	Sat Apr 10 13:02:08 2021 +0200
+++ b/eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/translations.py	Sat Apr 10 15:11:43 2021 +0200
@@ -44,10 +44,10 @@
         '''Use "{0} in {1}" instead of "{2}"'''),
     "Y110": QCoreApplication.translate(
         "SimplifyChecker",
-        '''Use "return any({0} for {1} in {2})"'''),
+        '''Use "any({0} for {1} in {2})"'''),
     "Y111": QCoreApplication.translate(
         "SimplifyChecker",
-        '''Use "return all({0} for {1} in {2})"'''),
+        '''Use "all({0} for {1} in {2})"'''),
     "Y112": QCoreApplication.translate(
         "SimplifyChecker",
         '''Use "{0}" instead of "{1}"'''),
@@ -79,6 +79,9 @@
     "Y121": QCoreApplication.translate(
         "SimplifyChecker",
         '''Use "class {0}({1}):" instead of "class {0}({1}, object):"'''),
+    "Y122": QCoreApplication.translate(
+        "SimplifyChecker",
+        '''Use "{0}.get({1})" instead of "if {1} in {0}: {0}[{1}]"'''),
     
     # Python-specifics not part of flake8-simplify
     "Y181": QCoreApplication.translate(
@@ -137,9 +140,18 @@
         "SimplifyChecker",
         '''Use "False" instead of "... and False"'''),
     
+    # Opinionated
     "Y301": QCoreApplication.translate(
         "SimplifyChecker",
         '''Use "{1} == {0}" instead of "{0} == {1}" (Yoda-condition)'''),
+    
+    # General Code Style
+    "Y401": QCoreApplication.translate(
+        "SimplifyChecker",
+        '''Use keyword-argument instead of magic boolean'''),
+    "Y402": QCoreApplication.translate(
+        "SimplifyChecker",
+        '''Use keyword-argument instead of magic number'''),
 }
 
 _simplifyMessagesSampleArgs = {
@@ -161,6 +173,7 @@
     "Y119": ["Foo"],
     "Y120": ["Foo"],
     "Y121": ["FooBar", "Foo"],
+    "Y122": ["bar_dict", "'foo'"],
     
     # Python-specifics not part of flake8-simplify
     "Y181": ["foo += 42", "foo = foo + 42"],
@@ -183,5 +196,8 @@
     "Y221": ["foo"],
     "Y222": ["foo"],
     
+    # Opinionated
     "Y301": ["42", "foo"],
+    
+    # General Code Style
 }

eric ide

mercurial