From cfd0ddb302bb8fa54e0ee18bf44d52635d093a0a Mon Sep 17 00:00:00 2001 From: Jin Lee Date: Fri, 15 Nov 2019 09:42:31 -0800 Subject: [PATCH] new feature: added dict_to_dot_str dict_tool (converts a dict into graphviz dot format) --- caper/dict_tool.py | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/caper/dict_tool.py b/caper/dict_tool.py index 3e366ae8..46f989ad 100644 --- a/caper/dict_tool.py +++ b/caper/dict_tool.py @@ -30,6 +30,7 @@ def merge_dict(a, b): a[key] = b[key] else: a[key] = b[key] + return a def flatten_dict(d, parent_key=()): @@ -187,6 +188,86 @@ def split_dict(d, rules=None): return result +def dict_to_dot_str(d, parent_key='digraph D', indent=''): + """Dict will be converted into DOT like the followings: + 1) Value string will not be double-quotted in DOT. + - make sure to escape double-quotes in a string with special characters + (e.g. whitespace, # and ;) + 2) If "value" is None then "key" will be just added to DOT without "=" + + dict: + { "key1": "val1", "key2": "val2", "key3": { "key3_1": "val3_1", }... } + + dot: + digraph D { + key1 = val1; + key2 = val2; + key3 { + key3_1 = val3_1; + ... + } + ... + } + + Example in a Croo output def JSON file: + (note that strings for "label" are double-quote-escaped). + + dict: + { + "rankdir": "TD", + "start": "[shape=Mdiamond]", + "end": "[shape=Msquare]", + "subgraph cluster_rep1": { + "style": "filled", + "color": "mistyrose", + "label": "\"Replicate 1\"" + }, + "subgraph cluster_rep2": { + "style": "filled", + "color": "azure", + "label": "\"Replicate 2\"" + }, + "a0 -> b0": null, + "c0 -> d0": null + } + + Such dict will be converted into a dot: + + dot: + digraph D { + rankDir = TD; + start = [shape=Mdiamond]; + end = [shape=Msquare]; + subgraph cluster_rep1 { + style = filled; + color = mistyrose; + label = "Replicate 1" + }; + subgraph cluster_rep2 { + style = filled; + color = azure; + label = "Replicate 2" + }; + a0 -> b0; + c0 -> d0; + } + """ + result = '' + if d is None: + return '{}{};\n'.format(indent, parent_key) + elif isinstance(d, str): + return '{}{} = {};\n'.format(indent, parent_key, d) + elif isinstance(d, dict): + result += indent + parent_key + ' {\n' + for k, v in d.items(): + result += dict_to_dot_str(v, parent_key=k, indent=indent + '\t') + result += indent + '}\n' + else: + raise ValueError('Unsupported data type: {} ' + '(only str and dict/JSON are allowed).'.format(type(d))) + return result + + def test(): import json from collections import OrderedDict