Outsource set_dot_basics() and apply_dot_tweaks()
This commit is contained in:
parent
2f03dcd1a3
commit
587b359fa0
@ -33,10 +33,12 @@ from wireviz.wv_bom import (
|
|||||||
)
|
)
|
||||||
from wireviz.wv_colors import get_color_hex, translate_color
|
from wireviz.wv_colors import get_color_hex, translate_color
|
||||||
from wireviz.wv_gv_html import (
|
from wireviz.wv_gv_html import (
|
||||||
|
apply_dot_tweaks,
|
||||||
gv_connector_loops,
|
gv_connector_loops,
|
||||||
gv_node_component,
|
gv_node_component,
|
||||||
html_line_breaks,
|
html_line_breaks,
|
||||||
remove_links,
|
remove_links,
|
||||||
|
set_dot_basics,
|
||||||
)
|
)
|
||||||
from wireviz.wv_helper import (
|
from wireviz.wv_helper import (
|
||||||
flatten2d,
|
flatten2d,
|
||||||
@ -145,27 +147,7 @@ class Harness:
|
|||||||
|
|
||||||
def create_graph(self) -> Graph:
|
def create_graph(self) -> Graph:
|
||||||
dot = Graph()
|
dot = Graph()
|
||||||
dot.body.append(f"// Graph generated by {APP_NAME} {__version__}\n")
|
set_dot_basics(dot, self.options)
|
||||||
dot.body.append(f"// {APP_URL}\n")
|
|
||||||
dot.attr(
|
|
||||||
"graph",
|
|
||||||
rankdir="LR",
|
|
||||||
ranksep="2",
|
|
||||||
bgcolor=wv_colors.translate_color(self.options.bgcolor, "HEX"),
|
|
||||||
nodesep="0.33",
|
|
||||||
fontname=self.options.fontname,
|
|
||||||
)
|
|
||||||
dot.attr(
|
|
||||||
"node",
|
|
||||||
shape="none",
|
|
||||||
width="0",
|
|
||||||
height="0",
|
|
||||||
margin="0", # Actual size of the node is entirely determined by the label.
|
|
||||||
style="filled",
|
|
||||||
fillcolor=wv_colors.translate_color(self.options.bgcolor_node, "HEX"),
|
|
||||||
fontname=self.options.fontname,
|
|
||||||
)
|
|
||||||
dot.attr("edge", style="bold", fontname=self.options.fontname)
|
|
||||||
|
|
||||||
for connector in self.connectors.values():
|
for connector in self.connectors.values():
|
||||||
# generate connector node
|
# generate connector node
|
||||||
@ -212,7 +194,6 @@ class Harness:
|
|||||||
|
|
||||||
html = []
|
html = []
|
||||||
|
|
||||||
|
|
||||||
wirehtml = []
|
wirehtml = []
|
||||||
# conductor table
|
# conductor table
|
||||||
wirehtml.append('<table border="0" cellspacing="0" cellborder="0">')
|
wirehtml.append('<table border="0" cellspacing="0" cellborder="0">')
|
||||||
@ -405,70 +386,7 @@ class Harness:
|
|||||||
fillcolor=translate_color(bgcolor, "HEX"),
|
fillcolor=translate_color(bgcolor, "HEX"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def typecheck(name: str, value: Any, expect: type) -> None:
|
apply_dot_tweaks(dot, self.tweak)
|
||||||
if not isinstance(value, expect):
|
|
||||||
raise Exception(
|
|
||||||
f"Unexpected value type of {name}: Expected {expect}, got {type(value)}\n{value}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO?: Differ between override attributes and HTML?
|
|
||||||
if self.tweak.override is not None:
|
|
||||||
typecheck("tweak.override", self.tweak.override, dict)
|
|
||||||
for k, d in self.tweak.override.items():
|
|
||||||
typecheck(f"tweak.override.{k} key", k, str)
|
|
||||||
typecheck(f"tweak.override.{k} value", d, dict)
|
|
||||||
for a, v in d.items():
|
|
||||||
typecheck(f"tweak.override.{k}.{a} key", a, str)
|
|
||||||
typecheck(f"tweak.override.{k}.{a} value", v, (str, type(None)))
|
|
||||||
|
|
||||||
# Override generated attributes of selected entries matching tweak.override.
|
|
||||||
for i, entry in enumerate(dot.body):
|
|
||||||
if isinstance(entry, str):
|
|
||||||
# Find a possibly quoted keyword after leading TAB(s) and followed by [ ].
|
|
||||||
match = re.match(
|
|
||||||
r'^\t*(")?((?(1)[^"]|[^ "])+)(?(1)") \[.*\]$', entry, re.S
|
|
||||||
)
|
|
||||||
keyword = match and match[2]
|
|
||||||
if keyword in self.tweak.override.keys():
|
|
||||||
for attr, value in self.tweak.override[keyword].items():
|
|
||||||
if value is None:
|
|
||||||
entry, n_subs = re.subn(
|
|
||||||
f'( +)?{attr}=("[^"]*"|[^] ]*)(?(1)| *)', "", entry
|
|
||||||
)
|
|
||||||
if n_subs < 1:
|
|
||||||
print(
|
|
||||||
f"Harness.create_graph() warning: {attr} not found in {keyword}!"
|
|
||||||
)
|
|
||||||
elif n_subs > 1:
|
|
||||||
print(
|
|
||||||
f"Harness.create_graph() warning: {attr} removed {n_subs} times in {keyword}!"
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if len(value) == 0 or " " in value:
|
|
||||||
value = value.replace('"', r"\"")
|
|
||||||
value = f'"{value}"'
|
|
||||||
entry, n_subs = re.subn(
|
|
||||||
f'{attr}=("[^"]*"|[^] ]*)', f"{attr}={value}", entry
|
|
||||||
)
|
|
||||||
if n_subs < 1:
|
|
||||||
# If attr not found, then append it
|
|
||||||
entry = re.sub(r"\]$", f" {attr}={value}]", entry)
|
|
||||||
elif n_subs > 1:
|
|
||||||
print(
|
|
||||||
f"Harness.create_graph() warning: {attr} overridden {n_subs} times in {keyword}!"
|
|
||||||
)
|
|
||||||
|
|
||||||
dot.body[i] = entry
|
|
||||||
|
|
||||||
if self.tweak.append is not None:
|
|
||||||
if isinstance(self.tweak.append, list):
|
|
||||||
for i, element in enumerate(self.tweak.append, 1):
|
|
||||||
typecheck(f"tweak.append[{i}]", element, str)
|
|
||||||
dot.body.extend(self.tweak.append)
|
|
||||||
else:
|
|
||||||
typecheck("tweak.append", self.tweak.append, str)
|
|
||||||
dot.body.append(self.tweak.append)
|
|
||||||
|
|
||||||
for mate in self.mates:
|
for mate in self.mates:
|
||||||
if mate.shape[0] == "<" and mate.shape[-1] == ">":
|
if mate.shape[0] == "<" and mate.shape[-1] == ">":
|
||||||
|
|||||||
@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
from itertools import zip_longest
|
from itertools import zip_longest
|
||||||
from typing import List, Optional, Union
|
from typing import Any, List, Optional, Union
|
||||||
|
|
||||||
|
from wireviz import APP_NAME, APP_URL, __version__
|
||||||
from wireviz.DataClasses import Cable, Color, Component, Connector, Options
|
from wireviz.DataClasses import Cable, Color, Component, Connector, Options
|
||||||
from wireviz.wv_colors import get_color_hex, translate_color
|
from wireviz.wv_colors import get_color_hex, translate_color
|
||||||
from wireviz.wv_helper import pn_info_string, remove_links
|
from wireviz.wv_helper import pn_info_string, remove_links
|
||||||
@ -356,3 +357,95 @@ def html_size_attr_dict(image):
|
|||||||
|
|
||||||
def html_line_breaks(inp):
|
def html_line_breaks(inp):
|
||||||
return remove_links(inp).replace("\n", "<br />") if isinstance(inp, str) else inp
|
return remove_links(inp).replace("\n", "<br />") if isinstance(inp, str) else inp
|
||||||
|
|
||||||
|
|
||||||
|
def set_dot_basics(dot, options):
|
||||||
|
dot.body.append(f"// Graph generated by {APP_NAME} {__version__}\n")
|
||||||
|
dot.body.append(f"// {APP_URL}\n")
|
||||||
|
dot.attr(
|
||||||
|
"graph",
|
||||||
|
rankdir="LR",
|
||||||
|
ranksep="2",
|
||||||
|
bgcolor=translate_color(options.bgcolor, "HEX"),
|
||||||
|
nodesep="0.33",
|
||||||
|
fontname=options.fontname,
|
||||||
|
)
|
||||||
|
dot.attr(
|
||||||
|
"node",
|
||||||
|
shape="none",
|
||||||
|
width="0",
|
||||||
|
height="0",
|
||||||
|
margin="0", # Actual size of the node is entirely determined by the label.
|
||||||
|
style="filled",
|
||||||
|
fillcolor=translate_color(options.bgcolor_node, "HEX"),
|
||||||
|
fontname=options.fontname,
|
||||||
|
)
|
||||||
|
dot.attr("edge", style="bold", fontname=options.fontname)
|
||||||
|
|
||||||
|
|
||||||
|
def apply_dot_tweaks(dot, tweak):
|
||||||
|
def typecheck(name: str, value: Any, expect: type) -> None:
|
||||||
|
if not isinstance(value, expect):
|
||||||
|
raise Exception(
|
||||||
|
f"Unexpected value type of {name}: Expected {expect}, got {type(value)}\n{value}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO?: Differ between override attributes and HTML?
|
||||||
|
if tweak.override is not None:
|
||||||
|
typecheck("tweak.override", tweak.override, dict)
|
||||||
|
for k, d in tweak.override.items():
|
||||||
|
typecheck(f"tweak.override.{k} key", k, str)
|
||||||
|
typecheck(f"tweak.override.{k} value", d, dict)
|
||||||
|
for a, v in d.items():
|
||||||
|
typecheck(f"tweak.override.{k}.{a} key", a, str)
|
||||||
|
typecheck(f"tweak.override.{k}.{a} value", v, (str, type(None)))
|
||||||
|
|
||||||
|
# Override generated attributes of selected entries matching tweak.override.
|
||||||
|
for i, entry in enumerate(dot.body):
|
||||||
|
if not isinstance(entry, str):
|
||||||
|
continue
|
||||||
|
# Find a possibly quoted keyword after leading TAB(s) and followed by [ ].
|
||||||
|
match = re.match(r'^\t*(")?((?(1)[^"]|[^ "])+)(?(1)") \[.*\]$', entry, re.S)
|
||||||
|
keyword = match and match[2]
|
||||||
|
if not keyword in tweak.override.keys():
|
||||||
|
continue
|
||||||
|
|
||||||
|
for attr, value in tweak.override[keyword].items():
|
||||||
|
if value is None:
|
||||||
|
entry, n_subs = re.subn(
|
||||||
|
f'( +)?{attr}=("[^"]*"|[^] ]*)(?(1)| *)', "", entry
|
||||||
|
)
|
||||||
|
if n_subs < 1:
|
||||||
|
print(
|
||||||
|
f"Harness.create_graph() warning: {attr} not found in {keyword}!"
|
||||||
|
)
|
||||||
|
elif n_subs > 1:
|
||||||
|
print(
|
||||||
|
f"Harness.create_graph() warning: {attr} removed {n_subs} times in {keyword}!"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if len(value) == 0 or " " in value:
|
||||||
|
value = value.replace('"', r"\"")
|
||||||
|
value = f'"{value}"'
|
||||||
|
entry, n_subs = re.subn(
|
||||||
|
f'{attr}=("[^"]*"|[^] ]*)', f"{attr}={value}", entry
|
||||||
|
)
|
||||||
|
if n_subs < 1:
|
||||||
|
# If attr not found, then append it
|
||||||
|
entry = re.sub(r"\]$", f" {attr}={value}]", entry)
|
||||||
|
elif n_subs > 1:
|
||||||
|
print(
|
||||||
|
f"Harness.create_graph() warning: {attr} overridden {n_subs} times in {keyword}!"
|
||||||
|
)
|
||||||
|
|
||||||
|
dot.body[i] = entry
|
||||||
|
|
||||||
|
if tweak.append is not None:
|
||||||
|
if isinstance(tweak.append, list):
|
||||||
|
for i, element in enumerate(tweak.append, 1):
|
||||||
|
typecheck(f"tweak.append[{i}]", element, str)
|
||||||
|
dot.body.extend(tweak.append)
|
||||||
|
else:
|
||||||
|
typecheck("tweak.append", tweak.append, str)
|
||||||
|
dot.body.append(tweak.append)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user