200 lines
3.6 KiB
Python
200 lines
3.6 KiB
Python
|
import os as _os
|
||
|
|
||
|
|
||
|
def convey(x, fs):
|
||
|
y = x
|
||
|
for f in fs:
|
||
|
y = f(y)
|
||
|
return y
|
||
|
|
||
|
|
||
|
def string_coin(template, arguments, options = None):
|
||
|
options = (
|
||
|
{
|
||
|
"open": "{{",
|
||
|
"close": "}}",
|
||
|
}
|
||
|
|
|
||
|
(options or {})
|
||
|
)
|
||
|
result = template
|
||
|
for (key, value, ) in arguments.items():
|
||
|
if (value is None):
|
||
|
pass
|
||
|
else:
|
||
|
result = result.replace(
|
||
|
(
|
||
|
"%s%s%s"
|
||
|
% (
|
||
|
options["open"],
|
||
|
key,
|
||
|
options["close"],
|
||
|
)
|
||
|
),
|
||
|
value
|
||
|
)
|
||
|
return result
|
||
|
|
||
|
|
||
|
def file_read(path):
|
||
|
handle = open(path, "r")
|
||
|
content = handle.read()
|
||
|
handle.close()
|
||
|
return content
|
||
|
|
||
|
|
||
|
def file_write(path, content):
|
||
|
_os.makedirs(_os.path.dirname(path), exist_ok = True)
|
||
|
handle = open(path, "w" if _os.path.exists(path) else "a")
|
||
|
handle.write(content)
|
||
|
handle.close()
|
||
|
return None
|
||
|
|
||
|
|
||
|
def dot_entry(head, attributes, options = None):
|
||
|
options = (
|
||
|
{
|
||
|
"indentation": 0,
|
||
|
}
|
||
|
|
|
||
|
(options or {})
|
||
|
)
|
||
|
return string_coin(
|
||
|
"{{indentation}}{{head}} [{{attributes}}];\n",
|
||
|
{
|
||
|
"indentation": ("\t" * options["indentation"]),
|
||
|
"head": head,
|
||
|
"attributes": convey(
|
||
|
attributes,
|
||
|
[
|
||
|
lambda x: x.items(),
|
||
|
lambda x: map(
|
||
|
lambda pair: string_coin(
|
||
|
"{{key}}=\"{{value}}\"",
|
||
|
{
|
||
|
"key": pair[0],
|
||
|
"value": pair[1]
|
||
|
}
|
||
|
),
|
||
|
x
|
||
|
),
|
||
|
", ".join,
|
||
|
]
|
||
|
),
|
||
|
}
|
||
|
)
|
||
|
|
||
|
|
||
|
def dot_node(node, options = None):
|
||
|
options = (
|
||
|
{
|
||
|
"indentation": 0,
|
||
|
}
|
||
|
|
|
||
|
(options or {})
|
||
|
)
|
||
|
return dot_entry(
|
||
|
string_coin("{{name}}", {"name": node["name"]}),
|
||
|
node["attributes"],
|
||
|
options
|
||
|
)
|
||
|
|
||
|
|
||
|
def dot_edge(edge, options = None):
|
||
|
options = (
|
||
|
{
|
||
|
"indentation": 0,
|
||
|
}
|
||
|
|
|
||
|
(options or {})
|
||
|
)
|
||
|
return dot_entry(
|
||
|
string_coin("{{name_from}} -> {{name_to}}", {"name_from": edge["name_from"], "name_to": edge["name_to"]}),
|
||
|
edge["attributes"],
|
||
|
options
|
||
|
)
|
||
|
|
||
|
|
||
|
def dot_subgraph(subgraph, options = None):
|
||
|
options = (
|
||
|
{
|
||
|
"indentation": 0,
|
||
|
}
|
||
|
|
|
||
|
(options or {})
|
||
|
)
|
||
|
return string_coin(
|
||
|
(
|
||
|
"{{indentation}}subgraph cluster_{{name}}\n"
|
||
|
+
|
||
|
"{{indentation}}{\n"
|
||
|
+
|
||
|
"{{attributes}}\n"
|
||
|
+
|
||
|
"{{nodes}}\n"
|
||
|
+
|
||
|
"{{edges}}\n"
|
||
|
+
|
||
|
"{{indentation}}}\n"
|
||
|
),
|
||
|
{
|
||
|
"indentation": ("\t" * options["indentation"]),
|
||
|
"name": subgraph["name"],
|
||
|
"attributes": convey(
|
||
|
subgraph["attributes"],
|
||
|
[
|
||
|
lambda x: x.items(),
|
||
|
lambda x: map(
|
||
|
lambda pair: string_coin(
|
||
|
"{{indentation}}{{key}}=\"{{value}}\";\n",
|
||
|
{
|
||
|
"indentation": ("\t" * (options["indentation"] + 1)),
|
||
|
"key": pair[0],
|
||
|
"value": pair[1]
|
||
|
}
|
||
|
),
|
||
|
x
|
||
|
),
|
||
|
"".join,
|
||
|
]
|
||
|
),
|
||
|
"nodes": "".join(map(lambda node: dot_node(node, {"indentation": (options["indentation"] + 1)}), subgraph["nodes"])),
|
||
|
"edges": "".join(map(lambda edge: dot_edge(edge, {"indentation": (options["indentation"] + 1)}), subgraph["edges"])),
|
||
|
}
|
||
|
)
|
||
|
|
||
|
|
||
|
def dot_graph(graph):
|
||
|
return string_coin(
|
||
|
(
|
||
|
"digraph {{name}}\n"
|
||
|
+
|
||
|
"{\n"
|
||
|
+
|
||
|
"{{settings_graph}}\n"
|
||
|
+
|
||
|
"{{settings_node}}\n"
|
||
|
+
|
||
|
"{{settings_edge}}\n"
|
||
|
+
|
||
|
"{{subgraphs}}\n"
|
||
|
+
|
||
|
"{{nodes}}\n"
|
||
|
+
|
||
|
"{{edges}}\n"
|
||
|
+
|
||
|
"}\n"
|
||
|
),
|
||
|
{
|
||
|
"name": graph["name"],
|
||
|
"settings_graph": dot_entry("graph", graph["settings"]["graph"], {"indentation": 1}),
|
||
|
"settings_node": dot_entry("node", graph["settings"]["node"], {"indentation": 1}),
|
||
|
"settings_edge": dot_entry("edge", graph["settings"]["edge"], {"indentation": 1}),
|
||
|
"nodes": "".join(map(lambda node: dot_node(node, {"indentation": 1}), graph["nodes"])),
|
||
|
"edges": "".join(map(lambda edge: dot_edge(edge, {"indentation": 1}), graph["edges"])),
|
||
|
"subgraphs": "".join(map(lambda subgraph: dot_subgraph(subgraph, {"indentation": 1}), graph["subgraphs"])),
|
||
|
}
|
||
|
)
|
||
|
|
||
|
|