src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/MiscellaneousChecker.py

branch
eric7
changeset 10356
09c698245a5c
parent 10186
91c3ba0767ad
child 10359
de0420dac60e
diff -r f3187412ecf4 -r 09c698245a5c src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/MiscellaneousChecker.py
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/MiscellaneousChecker.py	Wed Nov 29 14:31:31 2023 +0100
+++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Miscellaneous/MiscellaneousChecker.py	Wed Nov 29 14:31:50 2023 +0100
@@ -143,6 +143,7 @@
         "M532",
         "M533",
         "M534",
+        "M535",
         ## Bugbear++
         "M581",
         "M582",
@@ -339,6 +340,7 @@
                     "M532",
                     "M533",
                     "M534",
+                    "M535",
                     "M581",
                     "M582",
                 ),
@@ -1617,7 +1619,7 @@
 #######################################################################
 ## BugBearVisitor
 ##
-## adapted from: flake8-bugbear v23.7.10
+## adapted from: flake8-bugbear v23.11.26
 ##
 ## Original: Copyright (c) 2016 Ɓukasz Langa
 #######################################################################
@@ -1897,6 +1899,36 @@
         for node in nodes:
             yield from ast.walk(node)
 
+    def __getNamesFromTuple(self, node):
+        """
+        Private method to get the names from an ast.Tuple node.
+
+        @param node ast node to be processed
+        @type ast.Tuple
+        @yield names
+        @ytype str
+        """
+        for dim in node.elts:
+            if isinstance(dim, ast.Name):
+                yield dim.id
+            elif isinstance(dim, ast.Tuple):
+                yield from self.__getNamesFromTuple(dim)
+
+    def __getDictCompLoopVarNames(self, node):
+        """
+        Private method to get the names of comprehension loop variables.
+
+        @param node ast node to be processed
+        @type ast.DictComp
+        @yield loop variable names
+        @ytype str
+        """
+        for gen in node.generators:
+            if isinstance(gen.target, ast.Name):
+                yield gen.target.id
+            elif isinstance(gen.target, ast.Tuple):
+                yield from self.__getNamesFromTuple(gen.target)
+
     def visit(self, node):
         """
         Public method to traverse a given AST node.
@@ -2024,7 +2056,7 @@
                 ):
                     self.violations.append((node, "M510"))
 
-            self.__checkForM526(node)
+        self.__checkForM526(node)
 
         self.__checkForM528(node)
         self.__checkForM534(node)
@@ -2129,6 +2161,7 @@
         @type ast.DictComp
         """
         self.__checkForM523(node)
+        self.__checkForM535(node)
 
         self.generic_visit(node)
 
@@ -2265,6 +2298,15 @@
 
         self.generic_visit(node)
 
+    def visit_ImportFrom(self, node):
+        """
+        Public method to check from imports.
+
+        @param node reference to the node to be processed
+        @type ast.Import
+        """
+        self.visit_Import(node)
+
     def visit_Set(self, node):
         """
         Public method to check a set.
@@ -2286,6 +2328,9 @@
         if isinstance(node, ast.Import):
             for name in node.names:
                 self.__M505Imports.add(name.asname or name.name)
+        elif isinstance(node, ast.ImportFrom):
+            for name in node.names:
+                self.__M505Imports.add(f"{node.module}.{name.name or name.asname}")
         elif isinstance(node, ast.Call):
             if node.func.attr not in ("lstrip", "rstrip", "strip"):
                 return  # method name doesn't match
@@ -2386,13 +2431,25 @@
         itemContext = item.context_expr
         if (
             hasattr(itemContext, "func")
-            and isinstance(itemContext.func, ast.Attribute)
             and (
-                itemContext.func.attr == "assertRaises"
+                (
+                    isinstance(itemContext.func, ast.Attribute)
+                    and (
+                        itemContext.func.attr == "assertRaises"
+                        or (
+                            itemContext.func.attr == "raises"
+                            and isinstance(itemContext.func.value, ast.Name)
+                            and itemContext.func.value.id == "pytest"
+                            and "match"
+                            not in [kwd.arg for kwd in itemContext.keywords]
+                        )
+                    )
+                )
                 or (
-                    itemContext.func.attr == "raises"
-                    and isinstance(itemContext.func.value, ast.Name)
-                    and itemContext.func.value.id == "pytest"
+                    isinstance(itemContext.func, ast.Name)
+                    and itemContext.func.id == "raises"
+                    and isinstance(itemContext.func.ctx, ast.Load)
+                    and "pytest.raises" in self.__M505Imports
                     and "match" not in [kwd.arg for kwd in itemContext.keywords]
                 )
             )
@@ -2846,6 +2903,27 @@
         elif node.func.attr == "split":
             check(2, "maxsplit")
 
+    def __checkForM535(self, node: ast.DictComp):
+        """
+        Private method to check that a static key isn't used in a dict comprehension.
+
+        Record a warning if a likely unchanging key is used - either a constant,
+        or a variable that isn't coming from the generator expression.
+
+        @param node reference to the node to be processed
+        @type ast.DictComp
+        """
+        """Check that a static key isn't used in a dict comprehension.
+
+        Emit a warning if a likely unchanging key is used - either a constant,
+        or a variable that isn't coming from the generator expression.
+        """
+        if isinstance(node.key, ast.Constant):
+            self.violations.append((node, "M535", node.key.value))
+        elif isinstance(node.key, ast.Name):
+            if node.key.id not in self.__getDictCompLoopVarNames(node):
+                self.violations.append((node, "M535", node.key.id))
+
 
 class NameFinder(ast.NodeVisitor):
     """

eric ide

mercurial