forked from huangsam/ultimate-python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
runner.py
69 lines (50 loc) · 1.71 KB
/
runner.py
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
import io
import sys
from contextlib import contextmanager
from importlib import import_module
from inspect import isfunction, signature
from os import devnull
from pkgutil import walk_packages
from ultimatepython import __name__ as root_name
from ultimatepython import __path__ as root_path
# Module-level constants
_STYLE_SUCCESS = "\033[92m"
_STYLE_BOLD = "\033[1m"
_STYLE_END = "\033[0m"
_RUNNER_PROGRESS = "->"
_MODULE_MAIN = "main"
@contextmanager
def no_stdout():
"""Silence standard output with /dev/null."""
save_stdout = sys.stdout
with io.open(devnull, "w") as dev_null:
sys.stdout = dev_null
yield
sys.stdout = save_stdout
def success_text(text):
"""Get success text."""
return f"{_STYLE_SUCCESS}{bold_text(text)}{_STYLE_END}"
def bold_text(text):
"""Get bold text."""
return f"{_STYLE_BOLD}{text}{_STYLE_END}"
def main():
print(bold_text(f"Start {root_name} runner"))
for item in walk_packages(root_path, f"{root_name}."):
mod = import_module(item.name)
# Skip modules without a main object
if not hasattr(mod, _MODULE_MAIN):
continue
# By this point, there is a main object in the module
main_func = getattr(mod, _MODULE_MAIN)
# The main object is a function
assert isfunction(main_func)
# The main function has zero parameters
assert len(signature(main_func).parameters) == 0
# The main function should not throw any errors
print(f"{_RUNNER_PROGRESS} Run {mod.__name__}:{_MODULE_MAIN}", end="")
with no_stdout():
main_func()
print(" [PASS]")
print(success_text(f"Finish {root_name} runner"))
if __name__ == "__main__":
main()