29 "Set", |
30 "Set", |
30 "Tuple", |
31 "Tuple", |
31 "Union", |
32 "Union", |
32 "Type", |
33 "Type", |
33 ) |
34 ) |
34 |
35 |
35 def __init__(self): |
36 def __init__(self): |
36 """ |
37 """ |
37 Constructor |
38 Constructor |
38 """ |
39 """ |
39 super().__init__() |
40 super().__init__() |
40 |
41 |
41 self.__typingAliases = [] |
42 self.__typingAliases = [] |
42 self.__importsFutureAnnotations = False |
43 self.__importsFutureAnnotations = False |
43 |
44 |
44 # e.g. from typing import List, typing.List, t.List |
45 # e.g. from typing import List, typing.List, t.List |
45 self.__typingImports = [] |
46 self.__typingImports = [] |
46 |
47 |
47 def visit_Import(self, node): |
48 def visit_Import(self, node): |
48 """ |
49 """ |
49 Public method to check imports for typing related stuff. |
50 Public method to check imports for typing related stuff. |
50 |
51 |
51 This looks like: |
52 This looks like: |
52 import typing |
53 import typing |
53 or |
54 or |
54 import typing as t |
55 import typing as t |
55 |
56 |
56 typing or t will be added to the list of typing aliases. |
57 typing or t will be added to the list of typing aliases. |
57 |
58 |
58 @param node reference to the AST Import node |
59 @param node reference to the AST Import node |
59 @type ast.Import |
60 @type ast.Import |
60 """ |
61 """ |
61 for alias in node.names: |
62 for alias in node.names: |
62 if alias.name == "typing": |
63 if alias.name == "typing": |
63 self.__typingAliases.append("typing") |
64 self.__typingAliases.append("typing") |
64 if alias.asname is not None: |
65 if alias.asname is not None: |
65 self.__typingAliases.append(alias.asname) |
66 self.__typingAliases.append(alias.asname) |
66 |
67 |
67 self.generic_visit(node) |
68 self.generic_visit(node) |
68 |
69 |
69 def visit_ImportFrom(self, node): |
70 def visit_ImportFrom(self, node): |
70 """ |
71 """ |
71 Public method to detect the 'from __future__ import annotations' |
72 Public method to detect the 'from __future__ import annotations' |
72 import if present. |
73 import if present. |
73 |
74 |
74 If 'from typing import ...' is used, add simplifiable names that were |
75 If 'from typing import ...' is used, add simplifiable names that were |
75 imported. |
76 imported. |
76 |
77 |
77 @param node reference to the AST ImportFrom node |
78 @param node reference to the AST ImportFrom node |
78 @type ast.ImportFrom |
79 @type ast.ImportFrom |
79 """ |
80 """ |
80 if node.module == "__future__": |
81 if node.module == "__future__": |
81 for alias in node.names: |
82 for alias in node.names: |
86 for alias in node.names: |
87 for alias in node.names: |
87 if alias.name in AnnotationsFutureVisitor.SimplifyableTypes: |
88 if alias.name in AnnotationsFutureVisitor.SimplifyableTypes: |
88 self.__typingImports.append(alias.name) |
89 self.__typingImports.append(alias.name) |
89 |
90 |
90 self.generic_visit(node) |
91 self.generic_visit(node) |
91 |
92 |
92 def visit_Attribute(self, node): |
93 def visit_Attribute(self, node): |
93 """ |
94 """ |
94 Public method to record simplifiable names. |
95 Public method to record simplifiable names. |
95 |
96 |
96 If 'import typing' or 'import typing as t' is used, add simplifiable |
97 If 'import typing' or 'import typing as t' is used, add simplifiable |
97 names that were used later on in the code. |
98 names that were used later on in the code. |
98 |
99 |
99 @param node reference to the AST Attribute node |
100 @param node reference to the AST Attribute node |
100 @type ast.Attribute |
101 @type ast.Attribute |
101 """ |
102 """ |
102 if ( |
103 if ( |
103 node.attr in AnnotationsFutureVisitor.SimplifyableTypes and |
104 node.attr in AnnotationsFutureVisitor.SimplifyableTypes |
104 isinstance(node.value, ast.Name) and |
105 and isinstance(node.value, ast.Name) |
105 node.value.id in self.__typingAliases |
106 and node.value.id in self.__typingAliases |
106 ): |
107 ): |
107 self.__typingImports.append(f"{node.value.id}.{node.attr}") |
108 self.__typingImports.append(f"{node.value.id}.{node.attr}") |
108 |
109 |
109 self.generic_visit(node) |
110 self.generic_visit(node) |
110 |
111 |
111 def importsFutureAnnotations(self): |
112 def importsFutureAnnotations(self): |
112 """ |
113 """ |
113 Public method to check, if the analyzed code uses future annotation. |
114 Public method to check, if the analyzed code uses future annotation. |
114 |
115 |
115 @return flag indicatung the use of future annotation |
116 @return flag indicatung the use of future annotation |
116 @rtype bool |
117 @rtype bool |
117 """ |
118 """ |
118 return self.__importsFutureAnnotations |
119 return self.__importsFutureAnnotations |
119 |
120 |
120 def hasTypingImports(self): |
121 def hasTypingImports(self): |
121 """ |
122 """ |
122 Public method to check, if the analyzed code includes typing imports. |
123 Public method to check, if the analyzed code includes typing imports. |
123 |
124 |
124 @return flag indicating the use of typing imports |
125 @return flag indicating the use of typing imports |
125 @rtype bool |
126 @rtype bool |
126 """ |
127 """ |
127 return bool(self.__typingImports) |
128 return bool(self.__typingImports) |
128 |
129 |
129 def getTypingImports(self): |
130 def getTypingImports(self): |
130 """ |
131 """ |
131 Public method to get the list of typing imports. |
132 Public method to get the list of typing imports. |
132 |
133 |
133 @return list of typing imports |
134 @return list of typing imports |
134 @rtype list of str |
135 @rtype list of str |
135 """ |
136 """ |
136 return self.__typingImports[:] |
137 return self.__typingImports[:] |