Make setting HTML tag attributes easier through kwargs

This commit is contained in:
Daniel Rojas 2021-10-19 15:44:52 +02:00 committed by KV
parent 587b359fa0
commit 31c5e1aad9
2 changed files with 67 additions and 101 deletions

View File

@ -79,17 +79,16 @@ def gv_node_component(
tbl = nested_table(lines)
if component.bgcolor:
tbl.attribs["bgcolor"] = translate_color(component.bgcolor, "HEX")
else:
if isinstance(component, Connector) and harness_options.bgcolor_connector:
tbl.attribs["bgcolor"] = translate_color(
harness_options.bgcolor_connector, "HEX"
)
elif isinstance(component, Cable) and harness_options.bgcolor_cable:
tbl.attribs["bgcolor"] = translate_color(
harness_options.bgcolor_cable, "HEX"
)
tbl.update_attribs(bgcolor=translate_color(component.bgcolor, "HEX"))
if isinstance(component, Connector) and harness_options.bgcolor_connector:
tbl.update_attribs(
bgcolor=translate_color(harness_options.bgcolor_connector, "HEX")
)
elif isinstance(component, Cable) and harness_options.bgcolor_cable:
tbl.update_attribs(
bgcolor=translate_color(harness_options.bgcolor_cable, "HEX")
)
return tbl
@ -129,22 +128,13 @@ def nested_table(lines: List[Td]) -> Table:
inner_table = cells[0].contents
else:
# nest cell content inside a table
inner_table_attribs = {
"border": 0,
"cellspacing": 0,
"cellpadding": 3,
"cellborder": 1,
}
inner_table = Table(Tr(cells), attribs=inner_table_attribs)
inner_table = Table(
Tr(cells), border=0, cellspacing=0, cellpadding=3, cellborder=1
)
rows.append(Tr(Td(inner_table)))
if len(rows) == 0: # create dummy row to avoid GraphViz errors due to empty <table>
rows = Tr(Td(""))
outer_table_attribs = {
"border": 0,
"cellspacing": 0,
"cellpadding": 0,
}
tbl = Table(rows, attribs=outer_table_attribs)
tbl = Table(rows, border=0, cellspacing=0, cellpadding=0)
return tbl
@ -163,20 +153,13 @@ def gv_pin_table(component) -> Table:
gv_pin_row(pinindex, pinname, pinlabel, pincolor, component)
)
table_attribs = {
"border": 0,
"cellspacing": 0,
"cellpadding": 3,
"cellborder": 1,
}
return Table(pin_rows, attribs=table_attribs)
return Table(pin_rows, border=0, cellspacing=0, cellpadding=3, cellborder=1)
def gv_pin_row(pin_index, pin_name, pin_label, pin_color, connector) -> Tr:
cell_pin_left = Td(pin_name, attribs={"port": f"p{pin_index+1}l"})
cell_pin_label = Td(pin_label, empty_is_none=True)
cell_pin_right = Td(pin_name, attribs={"port": f"p{pin_index+1}r"})
cell_pin_left = Td(pin_name, port=f"p{pin_index+1}l")
cell_pin_label = Td(pin_label, delete_if_empty=True)
cell_pin_right = Td(pin_name, port=f"p{pin_index+1}r")
cells = [
cell_pin_left if connector.ports_left else None,
@ -234,12 +217,7 @@ def gv_conductor_table(cable, harness_options) -> Table:
rows.append(Tr(Td("&nbsp;")))
table_attribs = {
"border": 0,
"cellspacing": 0,
"cellborder": 0,
}
tbl = Table(rows, attribs=table_attribs)
tbl = Table(rows, border=0, cellspacing=0, cellborder=0)
return tbl
@ -255,9 +233,8 @@ def gv_wire_cell(index, color, pad) -> Td:
"border": 0,
"bgcolor": bgcolor if bgcolor != "" else "BK",
}
wire_inner_rows.append(Tr(Td("", attribs=wire_inner_cell_attribs)))
wire_inner_table_attribs = {"cellspacing": 0, "cellborder": 0, "border": 0}
wire_inner_table = Table(wire_inner_rows, wire_inner_table_attribs)
wire_inner_rows.append(Tr(Td("", **wire_inner_cell_attribs)))
wire_inner_table = Table(wire_inner_rows, cellspacing=0, cellborder=0, border=0)
wire_outer_cell_attribs = {
"colspan": 3,
"border": 0,
@ -265,17 +242,13 @@ def gv_wire_cell(index, color, pad) -> Td:
"port": f"w{index}",
"height": 2 * len(bgcolors),
}
wire_outer_cell = Td(wire_inner_table, attribs=wire_outer_cell_attribs)
wire_outer_cell = Td(wire_inner_table, **wire_outer_cell_attribs)
return wire_outer_cell
def colored_cell(contents, bgcolor) -> Td:
if bgcolor:
attribs = {"bgcolor": translate_color(bgcolor, "HEX")}
else:
attribs = {}
return Td(contents, attribs=attribs)
return Td(contents, bgcolor=translate_color(bgcolor, "HEX"))
def part_number_str_list(component: Component) -> List[str]:
@ -292,11 +265,7 @@ def part_number_str_list(component: Component) -> List[str]:
def colorbar_cell(color) -> Td:
if color:
colorbar_attribs = {
"bgcolor": translate_color(color, "HEX"),
"width": 4,
}
return Td("", attribs=colorbar_attribs)
return Td("", bgcolor=translate_color(color, "HEX"), width=4)
else:
return None
@ -305,35 +274,26 @@ def image_and_caption_cells(component: Component) -> (Td, Td):
if not component.image:
return (None, None)
image_tag = Img(
attribs={"scale": component.image.scale, "src": component.image.src}
)
image_tag = Img(scale=component.image.scale, src=component.image.src)
image_cell_inner = Td(image_tag, flat=True)
if component.image.fixedsize:
# further nest the image in a table with width/height/fixedsize parameters, and place that table in a cell
inner_cell_attribs = html_size_attr_dict(component.image)
image_cell_inner.attribs = Attribs(inner_cell_attribs)
image_cell_inner.update_attribs(**html_size_attr_dict(component.image))
image_cell = Td(
Table(
Tr(image_cell_inner),
attribs={"border": 0, "cellspacing": 0, "cellborder": 0, "id": "!"},
)
Table(Tr(image_cell_inner), border=0, cellspacing=0, cellborder=0, id="!")
)
else:
image_cell = image_cell_inner
outer_cell_attribs = {}
outer_cell_attribs["balign"] = "left"
if component.image.bgcolor:
outer_cell_attribs["bgcolor"] = translate_color(component.image.bgcolor, "HEX")
if component.image.caption:
outer_cell_attribs["sides"] = "TLR"
image_cell.attribs = Attribs(outer_cell_attribs)
image_cell.update_attribs(
balign="left",
bgcolor=translate_color(component.image.bgcolor, "HEX"),
sides="TLR" if component.image.caption else None,
)
if component.image.caption:
caption_cell = Td(
f"{html_line_breaks(component.image.caption)}",
attribs={"balign": "left", "sides": "BLR", "id": "td_caption"},
f"{html_line_breaks(component.image.caption)}", balign="left", sides="BLR"
)
else:
caption_cell = None

View File

@ -16,29 +16,27 @@ class Attribs(Dict):
for k, v in self.items():
if v is not None:
html.append(f' {k}="{v}"')
else:
html.append(f" {k}")
# else:
# html.append(f" {k}")
return "".join(html)
@dataclass
class Tag:
contents: str = None
contents = None
attribs: Attribs = field(default_factory=Attribs)
flat: bool = False
empty_is_none: bool = False
flat: bool = None
delete_if_empty: bool = False
def __post_init__(self):
if self.attribs is None:
self.attribs = Attribs({})
elif isinstance(self.attribs, Dict):
self.attribs = Attribs(self.attribs)
elif not isinstance(self.attribs, Attribs):
raise Exception(
"Tag.attribs must be of type None, Dict, or Attribs, "
f"but type {type(self.attribs).__name__} was given instead:\n"
f"{self.attribs}"
)
def __init__(self, contents, flat=None, delete_if_empty=False, **kwargs):
self.contents = contents
self.flat = flat
self.delete_if_empty = delete_if_empty
self.attribs = Attribs({**kwargs})
def update_attribs(self, **kwargs):
for k, v in kwargs.items():
self.attribs[k] = v
@property
def tagname(self):
@ -46,36 +44,41 @@ class Tag:
@property
def auto_flat(self):
if self.flat: # force flat
return True
if self.flat is not None: # user specified
return self.flat
if not _is_iterable_not_str(self.contents): # catch str, int, float, ...
if not isinstance(self.contents, Tag): # avoid recursion
return not "\n" in str(self.contents) # flatten if single line
def indent_lines(self, lines):
if self.auto_flat:
@property
def is_empty(self):
return self.get_contents(force_flat=True) == ""
def indent_lines(self, lines, force_flat=False):
if self.auto_flat or force_flat:
return lines
else:
indenter = " " * indent_count
return "\n".join(f"{indenter}{line}" for line in lines.split("\n"))
def get_contents(self):
separator = "" if self.auto_flat else "\n"
def get_contents(self, force_flat=False):
separator = "" if self.auto_flat or force_flat else "\n"
if _is_iterable_not_str(self.contents):
return separator.join(
[self.indent_lines(str(c)) for c in self.contents if c is not None]
[
self.indent_lines(str(c), force_flat)
for c in self.contents
if c is not None
]
)
elif self.contents is None:
return ""
else: # str, int, float, etc.
return self.indent_lines(str(self.contents))
return self.indent_lines(str(self.contents), force_flat)
def __repr__(self):
# if self.flat:
# import pudb; pudb.set_trace()
separator = "" if self.auto_flat else "\n"
if self.contents is None and self.empty_is_none:
if self.delete_if_empty and self.is_empty:
return ""
else:
html = [
@ -89,6 +92,9 @@ class Tag:
@dataclass
class TagSingleton(Tag):
def __init__(self, **kwargs):
self.attribs = Attribs({**kwargs})
def __repr__(self):
return f"<{self.tagname}{str(self.attribs)} />"