Source code for svst.api

import ast
import os
import io
import tokenize

from typing import Iterator, List, Tuple, Optional

from mypy import api as mypy_api

from svst import utils, output, parsing, constants


[docs]def get_lines_to_ignore(code: str) -> List[int]: """Read lines to ignore in a string of source code. Args: code: String of source code. Returns: List of lines to ignore. """ type_ignore_string: str = "type: ignore" tokens = tokenize.tokenize(io.BytesIO(code.encode("utf-8")).readline) lines_to_ignore: List[int] = [] for token in tokens: if token.type == tokenize.COMMENT: if token.string.strip().endswith( type_ignore_string ) or token.string.endswith(f"{type_ignore_string}[{constants.ERROR_NAME}]"): lines_to_ignore.append(token.start[0]) return lines_to_ignore
[docs]def parse_code( code: str, file_name: Optional[str] = None, ) -> Iterator[output.OutputTypedDict]: """Parse code directly and return a list of output dictionaries. Args: code: String of python code. file_name: Path of the file being analysed. Returns: A list of OutputTypedDict that contain the info of the svst error. """ tree = ast.parse(code, file_name) lines_to_ignore = get_lines_to_ignore(code) checker = parsing.VariableAnnotationChecker(file_name) checker.visit(tree) for error_message in checker.error_messages: if error_message["line_number"] not in lines_to_ignore: yield error_message
[docs]def mypy_run( path: str, ) -> List[str]: """Use mypy api to analyse a path. Args: path: File or directory path string. Yields: `mypy` error string. """ results: Tuple[str, str, int] = mypy_api.run([path]) for error_message in results[0].split("\n")[ :-2 ]: # 2 lines removed at the end to clean the output yield error_message
[docs]def run( path_list: List[str], mypy: bool = False, ) -> List[str]: """Run path list. Args: path_list: List of path strings. mypy: Run mypy for the same `path_list`. Yields: str: {file_name}:{line_number}: error: Variable "{variable_name}" is missing a standalone variable type annotation in the scope "{variable_scope}" [no-untyped-var] """ path: str for path in path_list: root: str dirs: List[str] files: List[str] for root, dirs, files in os.walk(path): file: str for file in files: if utils.is_ignored_file(root, file): continue file_path: str = os.path.join(root, file) file_buffer: io.TextIOWrapper with open(file_path, "r") as file_buffer: svst_errors = parse_code(file_buffer.read(), file_path) for svst_error in svst_errors: yield output.output_string_constructor(svst_error) if mypy: for line in mypy_run(path): yield line