2929# stdlib
3030import ast
3131from abc import ABC , abstractmethod
32- from typing import Iterator , List , Tuple , Type , TypeVar
32+ from typing import Generic , Iterator , List , Tuple , Type , TypeVar
3333
3434__all__ = ["Visitor" , "_P" , "Plugin" ]
3535
4040__email__ : str = "dominic@davis-foster.co.uk"
4141
4242_P = TypeVar ("_P" , bound = "Plugin" )
43+ _V = TypeVar ("_V" , bound = "Visitor" )
4344
4445
4546class Visitor (ast .NodeVisitor ):
@@ -66,7 +67,7 @@ def report_error(self, node: ast.AST, error: str):
6667 ))
6768
6869
69- class Plugin (ABC ):
70+ class Plugin (ABC , Generic [ _V ] ):
7071 """
7172 Abstract base class for Flake8 plugins.
7273
@@ -110,14 +111,23 @@ def version(self) -> str:
110111
111112 raise NotImplementedError
112113
114+ @property
115+ @abstractmethod
116+ def visitor_class (self ) -> Type [_V ]:
117+ """
118+ The visitor class to use to traverse the AST.
119+ """
120+
121+ raise NotImplementedError
122+
113123 def run (self : _P ) -> Iterator [Tuple [int , int , str , Type [_P ]]]:
114124 """
115125 Traverse the Abstract Syntax Tree and identify errors.
116126
117127 Yields a tuple of (line number, column offset, error message, type(self))
118128 """
119129
120- visitor = Visitor ()
130+ visitor : _V = self . visitor_class ()
121131 visitor .visit (self ._tree )
122132
123133 for line , col , msg in visitor .errors :
0 commit comments