Last active
May 12, 2022 02:54
-
-
Save weixinfree/ac3cf44b3b96fb95fa76c330fe3dc983 to your computer and use it in GitHub Desktop.
Revisions
-
weixinfree revised this gist
Nov 1, 2021 . 1 changed file with 23 additions and 21 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -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|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"] 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)) 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 _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 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() } 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: f.write(code) 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__": fire.Fire(main) -
weixinfree created this gist
Feb 6, 2021 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,95 @@ #! /usr/bin/env python3 """ Prerequirements: 1. brew install graphviz 2. pip3 install fire Usage: deps [path to code] """ import fire from pathlib import Path import re import os from pprint import pprint from typing import Dict, Iterable, List from simpletemplate import Template from subprocess import check_call from concurrent.futures import ThreadPoolExecutor 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" ENGINE = [ "dot", "neato", "twopi", "circo", "osage", "fdp", "sfdp" ] TEMPLATE = '''\ digraph Deps { node [color=lightblue2, style=filled]; %{for node in deps.keys():}% {{node}}; %{end}% %{for node, values in deps.items():}% %{for v in values:}% {{node}} -> {{v}}; %{end}% %{end}% }\ ''' def _parse_file(file: Path): content = file.read_text() 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"): 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)) t2 = time() print(f">>> 1. scan files finishd, cost: {t2 - t1:.2f}s") with ThreadPoolExecutor() as pool: _deps = dict(pool.map(_parse_file, list(files))) # _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()} 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: f.write(code) 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__': fire.Fire(main)