src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsDeprecationsVisitor.py

branch
eric7
changeset 10087
65b7354b0d4c
child 10439
21c28b0f9e41
equal deleted inserted replaced
10086:c8854a6300d1 10087:65b7354b0d4c
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a node visitor for checking the use of deprecated 'typing' symbols.
8 """
9
10 #
11 # The visitors are adapted and extended variants of the ones found in
12 # flake8-pep585 v0.1.7
13 #
14
15 import ast
16
17
18 class AnnotationsDeprecationsVisitor(ast.NodeVisitor):
19 """
20 Class implementing a node visitor for checking the use of deprecated 'typing'
21 symbols.
22 """
23
24 NameReplacements = {
25 "Tuple": "tuple",
26 "List": "list",
27 "Dict": "dict",
28 "Set": "set",
29 "FrozenSet": "frozenset",
30 "Type": "type",
31 "Deque": "collections.deque",
32 "DefaultDict": "collections.defaultdict",
33 "OrderedDict": "collections.OrderedDict",
34 "Counter": "collections.Counter",
35 "ChainMap": "collections.ChainMap",
36 "Awaitable": "collections.abc.Awaitable",
37 "Coroutine": "collections.abc.Coroutine",
38 "AsyncIterable": "collections.abc.AsyncIterable",
39 "AsyncIterator": "collections.abc.AsyncIterator",
40 "AsyncGenerator": "collections.abc.AsyncGenerator",
41 "Iterable": "collections.abc.Iterable",
42 "Iterator": "collections.abc.Iterator",
43 "Generator": "collections.abc.Generator",
44 "Reversible": "collections.abc.Reversible",
45 "Container": "collections.abc.Container",
46 "Collection": "collections.abc.Collection",
47 "Callable": "collections.abc.Callable",
48 "AbstractSet": "collections.abc.Set",
49 "MutableSet": "collections.abc.MutableSet",
50 "Mapping": "collections.abc.Mapping",
51 "MutableMapping": "collections.abc.MutableMapping",
52 "Sequence": "collections.abc.Sequence",
53 "MutableSequence": "collections.abc.MutableSequence",
54 "ByteString": "collections.abc.ByteString",
55 "MappingView": "collections.abc.MappingView",
56 "KeysView": "collections.abc.KeysView",
57 "ItemsView": "collections.abc.ItemsView",
58 "ValuesView": "collections.abc.ValuesView",
59 "ContextManager": "contextlib.AbstractContextManager",
60 "AsyncContextManager": "contextlib.AbstractAsyncContextManager",
61 "Pattern": "re.Pattern",
62 "Match": "re.Match",
63 }
64
65 def __init__(self, exemptedList):
66 """
67 Constructor
68
69 @param exemptedList list of typing symbols exempted from checking
70 @type list of str
71 """
72 self.__exemptedList = exemptedList[:]
73 self.__typingAliases = set()
74
75 self.__issues = []
76
77 def getIssues(self):
78 """
79 Public method to get the list of detected issues.
80
81 @return list of detected issues consisting of a tuple of a reference to the node
82 and a tuple containing the used name and the suggested replacement
83 @rtype list of tuples of (ast.AST, (str, str))
84 """
85 return self.__issues
86
87 def __checkDeprecation(self, node, name):
88 """
89 Private method to check, if the given name is deprecated.
90
91 @param node reference to the node
92 @type ast.ImportFrom, ast.Attribute
93 @param name name to be checked
94 @type str
95 """
96 if name not in self.__exemptedList:
97 replacement = self.NameReplacements.get(name)
98 if replacement is not None:
99 self.__issues.append((node, (name, replacement)))
100
101 def visit_ImportFrom(self, node):
102 """
103 Public method to handle an ast.ImportFrom node.
104
105 @param node reference to the node to be handled
106 @type ast.ImportFrom
107 """
108 if node.module == "typing":
109 for alias in node.names:
110 self.__checkDeprecation(node, alias.name)
111
112 def visit_Import(self, node):
113 """
114 Public method to handle an ast.Import node.
115
116 @param node reference to the node to be handled
117 @type ast.Import
118 """
119 for alias in node.names:
120 if alias.name == "typing":
121 self.__typingAliases.add(alias.asname or "typing")
122
123 def visit_Attribute(self, node):
124 """
125 Public method to handle an ast.Attribute node.
126
127 @param node reference to the node to be handled
128 @type ast.Attribute
129 """
130 if (
131 isinstance(node.value, ast.Name)
132 and node.value.id in self.__typingAliases
133 and node.attr not in self.__exemptedList
134 ):
135 self.__checkDeprecation(node, node.attr)
136
137 def visit_AnnAssign(self, node):
138 """
139 Public method to handle an ast.AnnAssign node.
140
141 @param node reference to the node to be handled
142 @type ast.AnnAssign
143 """
144 if isinstance(node.annotation, ast.Name):
145 self.__checkDeprecation(node, node.annotation.id)
146 elif isinstance(node.annotation, ast.Subscript) and isinstance(
147 node.annotation.value, ast.Name
148 ):
149 self.__checkDeprecation(node, node.annotation.value.id)
150
151 def visit_FunctionDef(self, node):
152 """
153 Public method to handle an ast.FunctionDef or ast.AsyncFunctionDef node.
154
155 @param node reference to the node to be handled
156 @type ast.FunctionDef or ast.AsyncFunctionDef
157 """
158 for arg in node.args.args + node.args.posonlyargs + node.args.kwonlyargs:
159 if isinstance(arg.annotation, ast.Name):
160 self.__checkDeprecation(arg, arg.annotation.id)
161 elif isinstance(arg.annotation, ast.Subscript) and isinstance(
162 arg.annotation.value, ast.Name
163 ):
164 self.__checkDeprecation(arg, arg.annotation.value.id)
165
166 visit_AsyncFunctionDef = visit_FunctionDef
167
168
169 class AnnotationsFutureImportVisitor(ast.NodeVisitor):
170 """
171 Class implementing a node visitor to dtermine, if the annotations __future__
172 import is present.
173
174 This class is used to determine usage of annotations for Python 3.8.
175 """
176
177 def __init__(self):
178 """
179 Constructor
180 """
181 self.__futureImport = False
182
183 def futureImportPresent(self):
184 """
185 Public method to check, if a 'from __future__ import annotations' statement
186 exists.
187
188 @return flag indicating the existence of the import statement
189 @rtype bool
190 """
191 return self.__futureImport
192
193 def visit_ImportFrom(self, node):
194 """
195 Public method to handle an ast.ImportFrom node.
196
197 @param node reference to the node to be handled
198 @type ast.ImportFrom
199 """
200 if node.module == "__future__" and "annotations" in {
201 alias.name for alias in node.names
202 }:
203 self.__futureImport = True

eric ide

mercurial