#!/usr/bin/env python """ all your lint are belong to us """ import os import subprocess import sys # pylint: disable=missing-class-docstring,too-few-public-methods class Color: HEAD = "\033[95m" BLUE = "\033[94m" GREEN = "\033[92m" WARN = "\033[93m" FAIL = "\033[91m" BOLD = "\033[1m" UNDER = "\033[4m" END = "\033[0m" def run(cmd, file): "Exec a linter for a file." global ERRORS # pylint: disable=global-statement args = { "ormolu": ["--mode", "check"], "hlint": [], "black": ["--quiet", "--check"], "pylint": ["--disable=invalid-name"], } # pylint: disable=subprocess-run-check ret = subprocess.run([cmd, *args[cmd], file], stdout=subprocess.PIPE) if ret.returncode != 0: ERRORS += 1 # pylint: disable=undefined-variable msg = ret.stdout.decode("utf-8").strip() print(Color.WARN + f"lint error: {cmd}: {file}" + Color.END) if msg: for line in msg.split("\n"): print(" " + line) def changed_files(): "Return a list of changed files according to git." merge_base = ( subprocess.check_output(["git", "merge-base", "HEAD", "origin/master"]) .decode("utf-8") .strip() ) return ( subprocess.check_output(["git", "diff", "--name-only", merge_base]) .decode("utf-8") .strip() .split() ) def group_files(files, extensions): """Given a list of files and list of extensions, return a dict of: {ext: [files]} """ root = os.getenv("BIZ_ROOT") ret = {k: [] for k in extensions} for ext in extensions: for file in files: if file.endswith(ext): ret[ext].append(os.path.join(root, file)) return ret def guard_todos(files): "Fail if TODO found in text" global ERRORS # pylint: disable=global-statement for fname in files: with open(fname) as text: if "TODO" in text.read(): ERRORS += 1 print("found todo:", fname) if __name__ == "__main__": ERRORS = 0 if "-h" in sys.argv: print(f"usage: {os.path.basename(__file__)} ") print("if no files given, lint changed files in this branch") sys.exit(0) elif len(sys.argv) == 1: FILES = group_files(changed_files(), [".hs", ".py"]) else: FILES = group_files(sys.argv[1:], [".hs", ".py"]) for hs in FILES[".hs"]: if not os.path.exists(hs): print("lint: does not exist:", hs) continue print(f"lint: {hs}") run("ormolu", hs) run("hlint", hs) for py in FILES[".py"]: if not os.path.exists(py): print("lint: does not exist:", py) continue print(f"lint: {py}") # Broken in our nixpkgs # run("black", py) run("pylint", py) if ERRORS: print("lint: errors:", ERRORS) sys.exit(ERRORS)