|
|
@@ -4,6 +4,7 @@ |
|
|
Prerequirements: |
|
|
1. brew install graphviz |
|
|
2. pip3 install fire |
|
|
3. pip3 install simpletemplate |
|
|
|
|
|
Usage: |
|
|
deps [path to code] |
|
|
@@ -21,21 +22,13 @@ |
|
|
from time import time |
|
|
|
|
|
|
|
|
DEFAULT_EXLUDE = r"accessids|logtag|widget|bar|callback|item|listener|callback|response|layout|view|model|utils|util|helper|logger|pagelist|constant|api|config|type|wrapper|source" |
|
|
DEFAULT_EXLUDE = r"(accessids|logtag|widget|listener|response|layout|view|model|utils|util|helper|logger|pagelist|constant|constants|api|config|type|wrapper|source|item|reason|dialog|object|info|name|status|data|apiservice|drawable|callback|viewV\d+|delegate)$" |
|
|
|
|
|
|
|
|
ENGINE = [ |
|
|
"dot", |
|
|
"neato", |
|
|
"twopi", |
|
|
"circo", |
|
|
"osage", |
|
|
"fdp", |
|
|
"sfdp" |
|
|
] |
|
|
ENGINE = ["dot", "neato", "twopi", "circo", "osage", "fdp", "sfdp"] |
|
|
|
|
|
|
|
|
TEMPLATE = '''\ |
|
|
TEMPLATE = """\ |
|
|
digraph Deps { |
|
|
node [color=lightblue2, style=filled]; |
|
|
%{for node in deps.keys():}% |
|
|
@@ -48,26 +41,33 @@ |
|
|
%{end}% |
|
|
%{end}% |
|
|
}\ |
|
|
''' |
|
|
""" |
|
|
|
|
|
|
|
|
def _parse_file(file: Path): |
|
|
content = file.read_text() |
|
|
return file.stem, set(re.findall(r'\b[A-Z$][\w.]+\b', content)) |
|
|
return file.stem, set(re.findall(r"\b[A-Z$][\w]+\b", content)) |
|
|
|
|
|
|
|
|
def _files(root: Path) -> Iterable[Path]: |
|
|
for d, _, files in os.walk(root): |
|
|
yield from (Path(os.path.join(d, f)) for f in files) |
|
|
|
|
|
|
|
|
def main(path: str, exlude: str = DEFAULT_EXLUDE, engine: str = "dot"): |
|
|
def _should_exlude(file: Path, exclude: str): |
|
|
r = re.search(exclude, file.stem, re.I) |
|
|
if r: |
|
|
print(f"exlude: {file.stem} {r}") |
|
|
return r |
|
|
|
|
|
|
|
|
def main(path: str, exclude: str = DEFAULT_EXLUDE, engine: str = "dot"): |
|
|
dot = Path(path).stem |
|
|
|
|
|
t1 = time() |
|
|
files = _files(Path(path)) |
|
|
if exlude: |
|
|
files = (f for f in files if not re.search(exlude, str(f), re.I)) |
|
|
if exclude: |
|
|
files = (f for f in files if not _should_exlude(f, exclude=exclude)) |
|
|
|
|
|
t2 = time() |
|
|
print(f">>> 1. scan files finishd, cost: {t2 - t1:.2f}s") |
|
|
@@ -76,20 +76,22 @@ def main(path: str, exlude: str = DEFAULT_EXLUDE, engine: str = "dot"): |
|
|
|
|
|
# _deps = dict(_parse_file(f) for f in files) |
|
|
valid_keys = set(_deps.keys()) |
|
|
deps = {k: [v for v in values if v in valid_keys and v != k] |
|
|
for k, values in _deps.items()} |
|
|
deps = { |
|
|
k: [v for v in values if v in valid_keys and v != k] |
|
|
for k, values in _deps.items() |
|
|
} |
|
|
|
|
|
t3 = time() |
|
|
print(f">>> 2. parse files finishd, cost: {t3 - t2:.2f}s") |
|
|
code = Template(TEMPLATE).render({"deps": deps}) |
|
|
with open(f'{dot}.dot', 'w') as f: |
|
|
with open(f"{dot}.dot", "w") as f: |
|
|
f.write(code) |
|
|
|
|
|
check_call(f'{engine} -Tpng {dot}.dot -o {dot}.png && open {dot}.png', shell=True) |
|
|
check_call(f"{engine} -Tpng {dot}.dot -o {dot}.png && open {dot}.png", shell=True) |
|
|
|
|
|
t4 = time() |
|
|
print(f">>> 3. render finishd, cost: {t4 - t3:.2f}s, total: {t4 - t1:.2f}s") |
|
|
|
|
|
|
|
|
if __name__ == '__main__': |
|
|
if __name__ == "__main__": |
|
|
fire.Fire(main) |