add linting script for mypy
This commit is contained in:
parent
e5b3a1e91e
commit
01b52fcca2
2 changed files with 93 additions and 0 deletions
83
lint
Executable file
83
lint
Executable file
|
@ -0,0 +1,83 @@
|
|||
#!/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()
|
10
mypy.ini
Normal file
10
mypy.ini
Normal file
|
@ -0,0 +1,10 @@
|
|||
[mypy]
|
||||
mypy_path=~/.config/my
|
||||
pretty = True
|
||||
show_error_context = True
|
||||
show_error_codes = True
|
||||
check_untyped_defs = True
|
||||
|
||||
# it's not controled by me, so for now just ignore..
|
||||
[mypy-my.config.repos.pdfannots.pdfannots]
|
||||
ignore_errors = True
|
Loading…
Add table
Reference in a new issue