#!/usr/bin/env python3 from pathlib import Path from pprint import pprint from itertools import chain from subprocess import check_call, run, PIPE import sys from typing import List, Optional, Iterable def log(*args): print(*args, file=sys.stderr) DIR = Path(__file__).absolute().parent # hmm. I guess I need to check all subpackages separately # otherwise pylint doesn't work and mypy doesn't discover everything # TODO could reuse in readme?? # returns None if not a package def package_name(p: Path) -> str: def mname(p: Path): nosuf = p.with_suffix('') return str(nosuf).replace('/', '.') has_init = (p.parent / '__init__.py').exists() if has_init: return mname(p.parent) else: return mname(p) def packages() -> Iterable[str]: yield from sorted(set( package_name(p.relative_to(DIR)) for p in (DIR / 'my').rglob('*.py') )) def pylint(): # TODO ugh. pylint still doesn't like checking my.config or my.books # only top level .py files seem ok?? pass def mypy(package: str): return run([ 'mypy', '--color-output', # TODO eh? doesn't work.. '--namespace-packages', '-p', package, ], stdout=PIPE, stderr=PIPE) def mypy_all() -> Iterable[Exception]: from concurrent.futures import ThreadPoolExecutor pkgs = list(packages()) log(f"Checking {pkgs}") with ThreadPoolExecutor() as pool: for p, res in zip(pkgs, pool.map(mypy, pkgs)): ret = res.returncode if ret > 0: log(f'FAILED: {p}') else: log(f'OK: {p}') print(res.stdout.decode('utf8')) print(res.stderr.decode('utf8'), file=sys.stderr) try: res.check_returncode() except Exception as e: yield e def main(): errors = list(mypy_all()) if len(errors) > 0: sys.exit(1) if __name__ == '__main__': main()