From ac1bd55d07fd1bad2f4a92dc0809607c407d9140 Mon Sep 17 00:00:00 2001 From: "Maciej A. Czyzewski" Date: Wed, 9 Jun 2021 15:29:18 +0200 Subject: [PATCH] feature: new params for graphviz + solves #70 - solve abs path bug #70 - new params for graphviz (ranksep; layout) - tested layout `dot`; `fdp` (square graph) - updated `.gitignore` (files gen. after `visualize_pyan_architecture.sh`) --- .gitignore | 5 ++++ README.md | 6 ++-- pyan/main.py | 55 +++++++++++++++++++++++++++++++--- visualize_pyan_architecture.sh | 5 ++++ 4 files changed, 64 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 990fdc0c..93313aaf 100644 --- a/.gitignore +++ b/.gitignore @@ -162,3 +162,8 @@ htmlcov .idea/ .history/ .vscode/ + +# our vis. of architecture +architecture.dot +architecture.html +architecture.svg diff --git a/README.md b/README.md index d1f19dcf..9e6919a3 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ See `pyan3 --help`. Example: -`pyan *.py --uses --no-defines --colored --grouped --annotated --dot >myuses.dot` +`pyan3 *.py --uses --no-defines --colored --grouped --annotated --dot >myuses.dot` Then render using your favorite GraphViz filter, mainly `dot` or `fdp`: @@ -56,11 +56,11 @@ Then render using your favorite GraphViz filter, mainly `dot` or `fdp`: Or use directly -`pyan *.py --uses --no-defines --colored --grouped --annotated --svg >myuses.svg` +`pyan3 *.py --uses --no-defines --colored --grouped --annotated --svg >myuses.svg` You can also export as an interactive HTML -`pyan *.py --uses --no-defines --colored --grouped --annotated --html > myuses.html` +`pyan3 *.py --uses --no-defines --colored --grouped --annotated --html > myuses.html` Alternatively, you can call `pyan` from a script diff --git a/pyan/main.py b/pyan/main.py index 5d079714..b1a16f63 100644 --- a/pyan/main.py +++ b/pyan/main.py @@ -141,6 +141,31 @@ def main(cli_args=None): ), ) + parser.add_argument( + "--dot-ranksep", + default="0.5", + dest="ranksep", + help=( + "specifies the dot graph 'ranksep' property for " + "controlling desired rank separation, in inches. " + "Allowed values: [0.02 .. 1000.0]. " + "[dot only]" + ), + ) + + parser.add_argument( + "--graphviz-layout", + default="dot", + dest="layout", + help=( + "specifies the graphviz 'layout' property for " + "the name of the layout algorithm to use. " + "Allowed values: ['dot', 'neato', 'fdp', 'sfdp', 'twopi', 'circo']. " + "Recommended values: ['dot', 'fdp']. " + "[graphviz only]" + ), + ) + parser.add_argument( "-a", "--annotated", @@ -159,7 +184,12 @@ def main(cli_args=None): known_args, unknown_args = parser.parse_known_args(cli_args) - filenames = [fn2 for fn in unknown_args for fn2 in glob(fn, recursive=True)] + + filenames = [] + for fn in unknown_args: + for fn2 in glob(fn, recursive=True): + abs_fn2 = os.path.abspath(fn2) + filenames.append(abs_fn2) # determine root if known_args.root is not None: @@ -203,6 +233,11 @@ def main(cli_args=None): handler = logging.FileHandler(known_args.logname) logger.addHandler(handler) + logger.debug(f"[files] {unknown_args}") + + if root: + root = os.path.abspath(root) + v = CallGraphVisitor(filenames, logger=logger, root=root) if known_args.function or known_args.namespace: @@ -222,13 +257,25 @@ def main(cli_args=None): writer = None if known_args.dot: - writer = DotWriter(graph, options=["rankdir=" + known_args.rankdir], output=known_args.filename, logger=logger) + writer = DotWriter(graph, options=[ + "rankdir=" + known_args.rankdir, + "ranksep=" + known_args.ranksep, + "layout=" + known_args.layout, + ], output=known_args.filename, logger=logger) if known_args.html: - writer = HTMLWriter(graph, options=["rankdir=" + known_args.rankdir], output=known_args.filename, logger=logger) + writer = HTMLWriter(graph, options=[ + "rankdir=" + known_args.rankdir, + "ranksep=" + known_args.ranksep, + "layout=" + known_args.layout, + ], output=known_args.filename, logger=logger) if known_args.svg: - writer = SVGWriter(graph, options=["rankdir=" + known_args.rankdir], output=known_args.filename, logger=logger) + writer = SVGWriter(graph, options=[ + "rankdir=" + known_args.rankdir, + "ranksep=" + known_args.ranksep, + "layout=" + known_args.layout, + ], output=known_args.filename, logger=logger) if known_args.tgf: writer = TgfWriter(graph, output=known_args.filename, logger=logger) diff --git a/visualize_pyan_architecture.sh b/visualize_pyan_architecture.sh index 22c63342..81b6ca24 100755 --- a/visualize_pyan_architecture.sh +++ b/visualize_pyan_architecture.sh @@ -2,3 +2,8 @@ echo -ne "Pyan architecture: generating architecture.{dot,svg}\n" python3 -m pyan pyan/*.py --no-defines --uses --colored --annotate --dot -V >architecture.dot 2>architecture.log dot -Tsvg architecture.dot >architecture.svg +echo -ne "Pyan architecture: generating architecture.{html,graphviz=fdp}\n" +python3 -m pyan pyan/*.py --no-defines --uses \ + --grouped --nested-groups \ + --graphviz-layout fdp \ + --colored --html > architecture.html