#!/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) -> Optional[str]: def mname(p: Path): nosuf = p.with_suffix('') return str(nosuf).replace('/', '.') if p.suffix == '.py': return mname(p) if p.is_dir() and (p / '__init__.py').exists(): return mname(p) return None def packages() -> Iterable[str]: for p in sorted(p.relative_to(DIR) for p in (DIR / 'my').iterdir()): res = package_name(p) if res is not None: yield res 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()