4
4
from abc import abstractmethod
5
5
from typing import Callable , List , Tuple , Optional , NamedTuple , TypeVar
6
6
7
- from mypy .nodes import Expression , StrExpr , IntExpr , UnaryExpr , Context , DictExpr
7
+ from mypy .nodes import Expression , StrExpr , IntExpr , UnaryExpr , Context , DictExpr , ClassDef
8
8
from mypy .types import (
9
9
Type , Instance , CallableType , TypedDictType , UnionType , NoneTyp , FunctionLike , TypeVarType ,
10
10
AnyType , TypeList , UnboundType , TypeOfAny
13
13
from mypy .options import Options
14
14
15
15
16
- class AnalyzerPluginInterface :
16
+ class TypeAnalyzerPluginInterface :
17
17
"""Interface for accessing semantic analyzer functionality in plugins."""
18
18
19
19
@abstractmethod
@@ -40,7 +40,7 @@ def analyze_callable_args(self, arglist: TypeList) -> Optional[Tuple[List[Type],
40
40
'AnalyzeTypeContext' , [
41
41
('type' , UnboundType ), # Type to analyze
42
42
('context' , Context ),
43
- ('api' , AnalyzerPluginInterface )])
43
+ ('api' , TypeAnalyzerPluginInterface )])
44
44
45
45
46
46
class CheckerPluginInterface :
@@ -53,6 +53,23 @@ def named_generic_type(self, name: str, args: List[Type]) -> Instance:
53
53
raise NotImplementedError
54
54
55
55
56
+ class SemanticAnalyzerPluginInterface :
57
+ """Interface for accessing semantic analyzer functionality in plugins."""
58
+
59
+ @abstractmethod
60
+ def named_type (self , qualified_name : str , args : Optional [List [Type ]] = None ) -> Instance :
61
+ raise NotImplementedError
62
+
63
+ @abstractmethod
64
+ def parse_bool (self , expr : Expression ) -> Optional [bool ]:
65
+ raise NotImplementedError
66
+
67
+ @abstractmethod
68
+ def fail (self , msg : str , ctx : Context , serious : bool = False , * ,
69
+ blocker : bool = False ) -> None :
70
+ raise NotImplementedError
71
+
72
+
56
73
# A context for a function hook that infers the return type of a function with
57
74
# a special signature.
58
75
#
@@ -98,6 +115,14 @@ def named_generic_type(self, name: str, args: List[Type]) -> Instance:
98
115
('context' , Context ),
99
116
('api' , CheckerPluginInterface )])
100
117
118
+ # A context for a class hook that modifies the class definition.
119
+ ClassDefContext = NamedTuple (
120
+ 'ClassDecoratorContext' , [
121
+ ('cls' , ClassDef ), # The class definition
122
+ ('reason' , Expression ), # The expression being applied (decorator, metaclass, base class)
123
+ ('api' , SemanticAnalyzerPluginInterface )
124
+ ])
125
+
101
126
102
127
class Plugin :
103
128
"""Base class of all type checker plugins.
@@ -136,7 +161,17 @@ def get_attribute_hook(self, fullname: str
136
161
) -> Optional [Callable [[AttributeContext ], Type ]]:
137
162
return None
138
163
139
- # TODO: metaclass / class decorator hook
164
+ def get_class_decorator_hook (self , fullname : str
165
+ ) -> Optional [Callable [[ClassDefContext ], None ]]:
166
+ return None
167
+
168
+ def get_metaclass_hook (self , fullname : str
169
+ ) -> Optional [Callable [[ClassDefContext ], None ]]:
170
+ return None
171
+
172
+ def get_base_class_hook (self , fullname : str
173
+ ) -> Optional [Callable [[ClassDefContext ], None ]]:
174
+ return None
140
175
141
176
142
177
T = TypeVar ('T' )
@@ -182,6 +217,18 @@ def get_attribute_hook(self, fullname: str
182
217
) -> Optional [Callable [[AttributeContext ], Type ]]:
183
218
return self ._find_hook (lambda plugin : plugin .get_attribute_hook (fullname ))
184
219
220
+ def get_class_decorator_hook (self , fullname : str
221
+ ) -> Optional [Callable [[ClassDefContext ], None ]]:
222
+ return self ._find_hook (lambda plugin : plugin .get_class_decorator_hook (fullname ))
223
+
224
+ def get_metaclass_hook (self , fullname : str
225
+ ) -> Optional [Callable [[ClassDefContext ], None ]]:
226
+ return self ._find_hook (lambda plugin : plugin .get_metaclass_hook (fullname ))
227
+
228
+ def get_base_class_hook (self , fullname : str
229
+ ) -> Optional [Callable [[ClassDefContext ], None ]]:
230
+ return self ._find_hook (lambda plugin : plugin .get_base_class_hook (fullname ))
231
+
185
232
def _find_hook (self , lookup : Callable [[Plugin ], T ]) -> Optional [T ]:
186
233
for plugin in self ._plugins :
187
234
hook = lookup (plugin )
0 commit comments