src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Imports/ImportsChecker.py

branch
eric7
changeset 11150
73d80859079c
parent 11147
dee6e106b4d3
diff -r fc45672fae42 -r 73d80859079c src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Imports/ImportsChecker.py
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Imports/ImportsChecker.py	Thu Feb 27 09:22:15 2025 +0100
+++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Imports/ImportsChecker.py	Thu Feb 27 14:42:39 2025 +0100
@@ -11,8 +11,10 @@
 import copy
 import re
 
+from CodeStyleTopicChecker import CodeStyleTopicChecker
 
-class ImportsChecker:
+
+class ImportsChecker(CodeStyleTopicChecker):
     """
     Class implementing a checker for import statements.
     """
@@ -28,6 +30,7 @@
         "I-903",
         "I-904",
     ]
+    Category = "I"
 
     def __init__(self, source, filename, tree, select, ignore, expected, repeat, args):
         """
@@ -50,96 +53,23 @@
         @param args dictionary of arguments for the various checks
         @type dict
         """
-        self.__select = tuple(select)
-        self.__ignore = tuple(ignore)
-        self.__expected = expected[:]
-        self.__repeat = repeat
-        self.__filename = filename
-        self.__source = source[:]
-        self.__tree = copy.deepcopy(tree)
-        self.__args = args
-
-        # statistics counters
-        self.counters = {}
-
-        # collection of detected errors
-        self.errors = []
+        super().__init__(
+            ImportsChecker.Category,
+            source,
+            filename,
+            tree,
+            select,
+            ignore,
+            expected,
+            repeat,
+            args,
+        )
 
         checkersWithCodes = [
             (self.__checkLocalImports, ("I-101", "I-102", "I-103")),
             (self.__tidyImports, ("I-901", "I-902", "I-903", "I-904")),
         ]
-
-        self.__checkers = []
-        for checker, codes in checkersWithCodes:
-            if any(not (code and self.__ignoreCode(code)) for code in codes):
-                self.__checkers.append(checker)
-
-    def __ignoreCode(self, code):
-        """
-        Private method to check if the message code should be ignored.
-
-        @param code message code to check for
-        @type str
-        @return flag indicating to ignore the given code
-        @rtype bool
-        """
-        return code in self.__ignore or (
-            code.startswith(self.__ignore) and not code.startswith(self.__select)
-        )
-
-    def __error(self, lineNumber, offset, code, *args):
-        """
-        Private method to record an issue.
-
-        @param lineNumber line number of the issue
-        @type int
-        @param offset position within line of the issue
-        @type int
-        @param code message code
-        @type str
-        @param args arguments for the message
-        @type list
-        """
-        if self.__ignoreCode(code):
-            return
-
-        if code in self.counters:
-            self.counters[code] += 1
-        else:
-            self.counters[code] = 1
-
-        # Don't care about expected codes
-        if code in self.__expected:
-            return
-
-        if code and (self.counters[code] == 1 or self.__repeat):
-            # record the issue with one based line number
-            self.errors.append(
-                {
-                    "file": self.__filename,
-                    "line": lineNumber + 1,
-                    "offset": offset,
-                    "code": code,
-                    "args": args,
-                }
-            )
-
-    def run(self):
-        """
-        Public method to check the given source against miscellaneous
-        conditions.
-        """
-        if not self.__filename:
-            # don't do anything, if essential data is missing
-            return
-
-        if not self.__checkers:
-            # don't do anything, if no codes were selected
-            return
-
-        for check in self.__checkers:
-            check()
+        self._initializeCheckers(checkersWithCodes)
 
     #######################################################################
     ## Local imports
@@ -153,13 +83,10 @@
         """
         from .LocalImportVisitor import LocalImportVisitor
 
-        visitor = LocalImportVisitor(self.__args, self)
-        visitor.visit(copy.deepcopy(self.__tree))
+        visitor = LocalImportVisitor(self.args, self)
+        visitor.visit(copy.deepcopy(self.tree))
         for violation in visitor.violations:
-            if not self.__ignoreCode(violation[1]):
-                node = violation[0]
-                reason = violation[1]
-                self.__error(node.lineno - 1, node.col_offset, reason)
+            self.addErrorFromNode(violation[0], violation[1])
 
     #######################################################################
     ## Tidy imports
@@ -171,11 +98,11 @@
         """
         Private method to check various other import related topics.
         """
-        self.__banRelativeImports = self.__args.get("BanRelativeImports", "")
+        self.__banRelativeImports = self.args.get("BanRelativeImports", "")
         self.__bannedModules = []
         self.__bannedStructuredPatterns = []
         self.__bannedUnstructuredPatterns = []
-        for module in self.__args.get("BannedModules", []):
+        for module in self.args.get("BannedModules", []):
             module = module.strip()
             if "*" in module[:-1] or module == "*":
                 # unstructured
@@ -197,16 +124,16 @@
         self.__bannedStructuredPatterns.sort(key=lambda x: len(x[0]), reverse=True)
 
         ruleMethods = []
-        if not self.__ignoreCode("I-901"):
+        if not self._ignoreCode("I-901"):
             ruleMethods.append(self.__checkUnnecessaryAlias)
-        if not self.__ignoreCode("I-902") and bool(self.__bannedModules):
+        if not self._ignoreCode("I-902") and bool(self.__bannedModules):
             ruleMethods.append(self.__checkBannedImport)
         if (
-            not self.__ignoreCode("I-903") and self.__banRelativeImports == "parents"
-        ) or (not self.__ignoreCode("I-904") and self.__banRelativeImports == "true"):
+            not self._ignoreCode("I-903") and self.__banRelativeImports == "parents"
+        ) or (not self._ignoreCode("I-904") and self.__banRelativeImports == "true"):
             ruleMethods.append(self.__checkBannedRelativeImports)
 
-        for node in ast.walk(self.__tree):
+        for node in ast.walk(self.tree):
             for method in ruleMethods:
                 method(node)
 
@@ -251,14 +178,14 @@
                     else:
                         rewritten = f"import {importedName}"
 
-                    self.__error(node.lineno - 1, node.col_offset, "I-901", rewritten)
+                    self.addErrorFromNode(node, "I-901", rewritten)
 
         elif isinstance(node, ast.ImportFrom):
             for alias in node.names:
                 if alias.name == alias.asname:
                     rewritten = f"from {node.module} import {alias.name}"
 
-                    self.__error(node.lineno - 1, node.col_offset, "I-901", rewritten)
+                    self.addErrorFromNode(node, "I-901", rewritten)
 
     def __isModuleBanned(self, moduleName):
         """
@@ -326,7 +253,7 @@
                     continue
                 else:
                     warned.add(moduleName)
-                self.__error(node.lineno - 1, node.col_offset, "I-902", moduleName)
+                self.addErrorFromNode(node, "I-902", moduleName)
 
     def __checkBannedRelativeImports(self, node):
         """
@@ -347,4 +274,4 @@
             msgCode = "I-904"
 
         if isinstance(node, ast.ImportFrom) and node.level > minNodeLevel:
-            self.__error(node.lineno - 1, node.col_offset, msgCode)
+            self.addErrorFromNode(node, msgCode)

eric ide

mercurial