HPI/lint
2020-04-12 13:15:33 +01:00

83 lines
2 KiB
Python
Executable file

#!/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()