3 from os
import makedirs
4 from os.path
import isdir
5 from argparse
import ArgumentParser
6 from typing
import Mapping, Union, TextIO
8 from DQDefects
import DefectsDB
9 from DQDefects.virtual_logic
import DefectLogic
11 DEPENDSON_DIR =
"dependson"
32 return any(c.primary
for c
in self.
children)
39 return (f
'<Node {self.name} parents="{[n.name for n in self.parents]}" '
40 f
'children="{[n.name for n in self.children]}">')
42 def dot(self, current_node=False, tooltip: str =
"", viewing_dependents: bool =
False) -> str:
43 color =
"grey" if self.
primary else "white"
45 color =
"darkslategray2" if viewing_dependents
else "gold"
47 tooltip = (
"[Virtual]" if self.
virtual else "[Primary]") +
" " + tooltip
53 if viewing_dependents:
54 url = f
"../{self.name}.svg"
55 label +=
r"\n[Deep dependants]"
57 url = f
"{DEPENDSON_DIR}/{self.name}.svg"
58 label +=
r"\n[Dependencies]"
60 url =
"%s.svg" % self.
name
62 return f
'{self.name} [fillcolor={color}, style=filled, URL="{url}", tooltip="{tooltip}", label="{label}"];'
64 def build_tree(all_logic: Mapping[str, DefectLogic]) -> dict[str, Node]:
66 all_nodes: dict[str, Node] = {}
68 def make_primary(current_logic: str) -> Node:
69 if current_logic
in all_nodes:
70 return all_nodes[current_logic]
71 all_nodes[current_logic] = node =
Node(current_logic)
74 def explore_virtual(current_logic: str) -> Node:
75 if current_logic
in all_nodes:
76 return all_nodes[current_logic]
78 this_logic = all_logic[current_logic]
79 all_nodes[current_logic] = node =
Node(current_logic)
81 for name
in this_logic.clauses:
83 child = explore_virtual(name)
85 child = make_primary(name)
87 child.parents.add(node)
88 node.children.add(child)
92 for name
in all_logic:
97 def walk(node: Node, visited: set[Node], visit_primary: bool, fd: TextIO):
100 for subnode
in sorted(node.children, key=Node.get_name):
101 if subnode.virtual
or (subnode.primary
and visit_primary):
102 print(f
"{node.name} -> {subnode.name}", file=fd)
103 walk(subnode, visited, visit_primary, fd)
106 descs: Mapping[Union[str, int], str], parents: bool):
107 for node
in sorted(nodes, key=Node.get_name):
108 at_current_node = node.name == current_node.name
109 description = descs.get(node.name, node.name)
111 description = description.replace(
'\n',
' ')
112 print(node.dot(at_current_node, description, parents), file=fd)
116 with open(
"%s/%s.dot" % (output_dir, node.name),
"w")
as fd:
117 print(f
"strict digraph {node.name} {{", file=fd)
118 print(
"rankdir=LR;\n", file=fd)
122 for parent
in sorted(node.parents, key=Node.get_name):
123 print(f
"{parent.name} -> {node.name}", file=fd)
126 walk(node, visited, node.has_primary_children, fd)
134 visited =
set([node])
136 with open(f
"{output_dir}/{DEPENDSON_DIR}/{node.name}.dot",
"w")
as fd:
137 def walk_parents(node):
139 for parent
in node.parents:
140 print(f
"{parent.name} -> {node.name}", file=fd)
143 print(f
"strict digraph {node.name} {{", file=fd)
144 print(
"rankdir=LR;\n", file=fd)
152 def render_all_flags(output_dir: str, all_nodes: dict[str, Node], descs: Mapping[Union[str, int], str]):
154 path =
"%s/%s" % (output_dir, DEPENDSON_DIR)
158 for _, node
in sorted(all_nodes.items()):
164 parser = ArgumentParser(description=
"Dump defect viewer information")
166 parser.add_argument(
"-t",
"--tag", default=
"HEAD", help=
"Defect tag")
167 parser.add_argument(
"-o",
"--output", default=
".", help=
"Directory to dump files")
169 args = parser.parse_args()
172 db = DefectsDB(tag=args.tag)
174 descs = db.all_defect_descriptions
177 all_nodes =
build_tree(db.virtual_defect_logics)
180 output_dir =
"%s/%s" % (args.output, args.tag)
183 if __name__ ==
"__main__":