eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsFutureVisitor.py

branch
eric7
changeset 8773
3dd81b827455
child 8783
04fe1beecd9c
diff -r 70f9dfe7116a -r 3dd81b827455 eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsFutureVisitor.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsFutureVisitor.py	Thu Nov 18 19:37:14 2021 +0100
@@ -0,0 +1,136 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a node visitor for function type annotations.
+"""
+
+#
+# The visitor and associated classes are adapted from flake8-future-annotations
+# v0.0.4
+#
+
+import ast
+
+
+class AnnotationsFutureVisitor(ast.NodeVisitor):
+    """
+    Class implementing a node visitor to check __future__ imports.
+    """
+    SimplifyableTypes = (
+        "DefaultDict",
+        "Deque",
+        "Dict",
+        "FrozenSet",
+        "List",
+        "Optional",
+        "Set",
+        "Tuple",
+        "Union",
+        "Type",
+    )
+    
+    def __init__(self):
+        """
+        Constructor
+        """
+        super().__init__()
+        
+        self.__typingAliases = []
+        self.__importsFutureAnnotations = False
+        
+        # e.g. from typing import List, typing.List, t.List
+        self.__typingImports = []
+    
+    def visit_Import(self, node):
+        """
+        Public method to check imports for typing related stuff.
+        
+        This looks like:
+        import typing
+        or
+        import typing as t
+        
+        typing or t will be added to the list of typing aliases.
+        
+        @param node reference to the AST Import node
+        @type ast.Import
+        """
+        for alias in node.names:
+            if alias.name == "typing":
+                self.__typingAliases.append("typing")
+            if alias.asname is not None:
+                self.__typingAliases.append(alias.asname)
+        
+        self.generic_visit(node)
+    
+    def visit_ImportFrom(self, node):
+        """
+        Public method to detect the 'from __future__ import annotations'
+        import if present.
+
+        If 'from typing import ...' is used, add simplifiable names that were
+        imported.
+        
+        @param node reference to the AST ImportFrom node
+        @type ast.ImportFrom
+        """
+        if node.module == "__future__":
+            for alias in node.names:
+                if alias.name == "annotations":
+                    self.__importsFutureAnnotations = True
+
+        if node.module == "typing":
+            for alias in node.names:
+                if alias.name in AnnotationsFutureVisitor.SimplifyableTypes:
+                    self.__typingImports.append(alias.name)
+
+        self.generic_visit(node)
+    
+    def visit_Attribute(self, node):
+        """
+        Public method to record simplifiable names.
+        
+        If 'import typing' or 'import typing as t' is used, add simplifiable
+        names that were used later on in the code.
+        
+        @param node reference to the AST Attribute node
+        @type ast.Attribute
+        """
+        if (
+            node.attr in AnnotationsFutureVisitor.SimplifyableTypes
+            and isinstance(node.value, ast.Name)
+            and node.value.id in self.__typingAliases
+        ):
+            self.__typingImports.append(f"{node.value.id}.{node.attr}")
+        
+        self.generic_visit(node)
+    
+    def importsFutureAnnotations(self):
+        """
+        Public method to check, if the analyzed code uses future annotation.
+        
+        @return flag indicatung the use of future annotation
+        @rtype bool
+        """
+        return self.__importsFutureAnnotations
+    
+    def hasTypingImports(self):
+        """
+        Public method to check, if the analyzed code includes typing imports.
+        
+        @return flag indicating the use of typing imports
+        @rtype bool
+        """
+        return bool(self.__typingImports)
+    
+    def getTypingImports(self):
+        """
+        Public method to get the list of typing imports.
+        
+        @return list of typing imports
+        @rtype list of str
+        """
+        return self.__typingImports[:]

eric ide

mercurial