-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdev
More file actions
executable file
·110 lines (80 loc) · 2.53 KB
/
Copy pathdev
File metadata and controls
executable file
·110 lines (80 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/env python
"""Dev task launcher for BBLM."""
import argparse
import subprocess
import sys
from typing import Any, Callable, Optional, TypeVar
# Helpers
def run(*command: Any) -> None:
"""Run a command, terminating on failure."""
cmd = [str(arg) for arg in command if arg is not None]
print("$ " + " ".join(cmd), file=sys.stderr)
exit_code = subprocess.call(cmd)
if exit_code:
sys.exit(exit_code)
T = TypeVar("T")
def cli(*args: Any, **kwargs: Any) -> Callable[[T], T]:
"""Declare a CLI command / arguments for that command."""
def wrap(func: T) -> T:
if not hasattr(func, "cli_args"):
setattr(func, "cli_args", [])
if args or kwargs:
getattr(func, "cli_args").append((args, kwargs))
return func
return wrap
ROOTS = ["dev", "bblm", "tests"]
# Builders
@cli("-k", "--filter")
@cli("-s", "--nocapture", dest="capture", action="store_false")
def tests(
filter: Optional[str], capture: bool # pylint:disable=redefined-builtin
) -> None:
"""run Python tests"""
run(
"python",
"-m",
"pytest",
"tests",
*(["-k", filter] if filter else ["--cov=bblm"]),
None if capture else "--capture=no",
)
@cli()
def lint() -> None:
"""run static analysis"""
run("python", "-m", "flake8", *ROOTS)
run("python", "-m", "mypy", *ROOTS)
run("python", "-m", "pylint", *(r for r in ROOTS if r != "tests"))
run(
"python",
"-m",
"pylint",
"tests",
"--disable=missing-module-docstring",
)
@cli("--check", action="store_true")
def format(check: bool) -> None: # pylint:disable=redefined-builtin
"""run autoformatters"""
run("black", "--check" if check else None, *ROOTS)
run("isort", "--check" if check else None, *ROOTS)
@cli()
def ci() -> None:
"""run continuous integration checks"""
tests(filter=None, capture=True)
lint()
format(check=True)
# Script
def _main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.set_defaults(action=ci)
subs = parser.add_subparsers()
for key, value in globals().items():
if hasattr(value, "cli_args"):
sub = subs.add_parser(key.replace("_", "-"), help=value.__doc__)
for args, kwargs in value.cli_args:
sub.add_argument(*args, **kwargs)
sub.set_defaults(action=value)
cli_args = vars(parser.parse_args())
action = cli_args.pop("action")
action(**cli_args)
if __name__ == "__main__":
_main()