HPI/lint
Dima Gerasimov cc127f1876 kython.klogging
- move to core
- add a proper description why it's useful
- make default level INFO
- use HPI_LOGS variable for easier log level control (abdc6df1ea)
2020-10-29 03:13:18 +01:00

105 lines
2.6 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
import os
from typing import List, Optional, Iterable
def log(*args):
print(*args, file=sys.stderr)
CI = 'CI' in os.environ
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 subpackages(package: str) -> Iterable[str]:
ppath = package.replace('.', '/')
yield from sorted({
package_name(p.relative_to(DIR)) for p in (DIR / ppath).rglob('*.py')
})
# TODO meh.. think how to check _everything_ on CI
def core_modules() -> Iterable[str]:
return [
*subpackages('my.core'),
'my.config',
'my.cfg',
'tests/misc.py',
'tests/get_files.py',
# 'tests/config.py', TODO hmm. unclear how to type check this module
]
def all_modules() -> Iterable[str]:
yield from subpackages('my')
yield from sorted(
str(f.relative_to(DIR)) for f in (DIR / 'tests').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(thing: str):
is_package = Path(thing).suffix != '.py'
cmd = [
'mypy',
'--color-output', # TODO eh? doesn't work..
*(['-p'] if is_package else []), thing,
]
print(' '.join(cmd), file=sys.stderr)
return run(cmd, stdout=PIPE, stderr=PIPE)
def mypy_all() -> Iterable[Exception]:
from concurrent.futures import ThreadPoolExecutor
pkgs = list(core_modules() if CI else all_modules())
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()