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

branch
eric7
changeset 8773
3dd81b827455
child 8783
04fe1beecd9c
equal deleted inserted replaced
8772:70f9dfe7116a 8773:3dd81b827455
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a node visitor for function type annotations.
8 """
9
10 #
11 # The visitor and associated classes are adapted from flake8-future-annotations
12 # v0.0.4
13 #
14
15 import ast
16
17
18 class AnnotationsFutureVisitor(ast.NodeVisitor):
19 """
20 Class implementing a node visitor to check __future__ imports.
21 """
22 SimplifyableTypes = (
23 "DefaultDict",
24 "Deque",
25 "Dict",
26 "FrozenSet",
27 "List",
28 "Optional",
29 "Set",
30 "Tuple",
31 "Union",
32 "Type",
33 )
34
35 def __init__(self):
36 """
37 Constructor
38 """
39 super().__init__()
40
41 self.__typingAliases = []
42 self.__importsFutureAnnotations = False
43
44 # e.g. from typing import List, typing.List, t.List
45 self.__typingImports = []
46
47 def visit_Import(self, node):
48 """
49 Public method to check imports for typing related stuff.
50
51 This looks like:
52 import typing
53 or
54 import typing as t
55
56 typing or t will be added to the list of typing aliases.
57
58 @param node reference to the AST Import node
59 @type ast.Import
60 """
61 for alias in node.names:
62 if alias.name == "typing":
63 self.__typingAliases.append("typing")
64 if alias.asname is not None:
65 self.__typingAliases.append(alias.asname)
66
67 self.generic_visit(node)
68
69 def visit_ImportFrom(self, node):
70 """
71 Public method to detect the 'from __future__ import annotations'
72 import if present.
73
74 If 'from typing import ...' is used, add simplifiable names that were
75 imported.
76
77 @param node reference to the AST ImportFrom node
78 @type ast.ImportFrom
79 """
80 if node.module == "__future__":
81 for alias in node.names:
82 if alias.name == "annotations":
83 self.__importsFutureAnnotations = True
84
85 if node.module == "typing":
86 for alias in node.names:
87 if alias.name in AnnotationsFutureVisitor.SimplifyableTypes:
88 self.__typingImports.append(alias.name)
89
90 self.generic_visit(node)
91
92 def visit_Attribute(self, node):
93 """
94 Public method to record simplifiable names.
95
96 If 'import typing' or 'import typing as t' is used, add simplifiable
97 names that were used later on in the code.
98
99 @param node reference to the AST Attribute node
100 @type ast.Attribute
101 """
102 if (
103 node.attr in AnnotationsFutureVisitor.SimplifyableTypes
104 and isinstance(node.value, ast.Name)
105 and node.value.id in self.__typingAliases
106 ):
107 self.__typingImports.append(f"{node.value.id}.{node.attr}")
108
109 self.generic_visit(node)
110
111 def importsFutureAnnotations(self):
112 """
113 Public method to check, if the analyzed code uses future annotation.
114
115 @return flag indicatung the use of future annotation
116 @rtype bool
117 """
118 return self.__importsFutureAnnotations
119
120 def hasTypingImports(self):
121 """
122 Public method to check, if the analyzed code includes typing imports.
123
124 @return flag indicating the use of typing imports
125 @rtype bool
126 """
127 return bool(self.__typingImports)
128
129 def getTypingImports(self):
130 """
131 Public method to get the list of typing imports.
132
133 @return list of typing imports
134 @rtype list of str
135 """
136 return self.__typingImports[:]

eric ide

mercurial