Source code for flake8_helper

#!/usr/bin/env python3
#
#  __init__.py
"""
A helper library for Flake8 plugins.
"""
#
#  Copyright © 2021 Dominic Davis-Foster <dominic@davis-foster.co.uk>
#
#  Permission is hereby granted, free of charge, to any person obtaining a copy
#  of this software and associated documentation files (the "Software"), to deal
#  in the Software without restriction, including without limitation the rights
#  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#  copies of the Software, and to permit persons to whom the Software is
#  furnished to do so, subject to the following conditions:
#
#  The above copyright notice and this permission notice shall be included in all
#  copies or substantial portions of the Software.
#
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
#  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
#  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
#  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
#  OR OTHER DEALINGS IN THE SOFTWARE.
#

# stdlib
import ast
from abc import ABC, abstractmethod
from typing import Generic, Iterator, List, Tuple, Type, TypeVar

__all__ = ["_V", "Visitor", "_P", "Plugin"]

__author__: str = "Dominic Davis-Foster"
__copyright__: str = "2021 Dominic Davis-Foster"
__license__: str = "MIT License"
__version__: str = "0.2.2"
__email__: str = "dominic@davis-foster.co.uk"

_P = TypeVar("_P", bound="Plugin")
_V = TypeVar("_V", bound="Visitor")


[docs]class Visitor(ast.NodeVisitor): """ AST node visitor. """ def __init__(self) -> None: #: The list of Flake8 errors identified by the visitor. self.errors: List[Tuple[int, int, str]] = []
[docs] def report_error(self, node: ast.AST, error: str) -> None: """ Report an error for the given node. :param node: :param error: """ self.errors.append(( node.lineno, node.col_offset, error, ))
[docs]class Plugin(ABC, Generic[_V]): """ Abstract base class for Flake8 plugins. :param tree: The abstract syntax tree (AST) to check. **Minimum example:** .. code=block:: python class EncodingsPlugin(Plugin): ''' A Flake8 plugin to identify incorrect use of encodings. :param tree: The abstract syntax tree (AST) to check. ''' name: str = __name__ version: str = __version__ #: The plugin version """ def __init__(self, tree: ast.AST): #: The abstract syntax tree (AST) being checked. self._tree = tree @property @abstractmethod def name(self) -> str: """ The plugin name. """ raise NotImplementedError @property @abstractmethod def version(self) -> str: """ The plugin version. """ raise NotImplementedError @property @abstractmethod def visitor_class(self) -> Type[_V]: """ The visitor class to use to traverse the AST. """ raise NotImplementedError
[docs] def run(self: _P) -> Iterator[Tuple[int, int, str, Type[_P]]]: """ Traverse the Abstract Syntax Tree and identify errors. Yields a tuple of (line number, column offset, error message, type(self)) """ visitor: _V = self.visitor_class() visitor.visit(self._tree) for line, col, msg in visitor.errors: yield line, col, msg, type(self)