Example #1
0
def test_render_explicit_ipython_format_inside_ipython():
    graph = nx.Graph()
    graph.add_edge("A", "B")
    for format in ["svg", "png", "raw"]:
        output = nxv.render(graph, format=format)
        with assert_ipython_display_call(output, f"ipython/{format}"):
            nxv.render(graph, format=f"ipython/{format}")
Example #2
0
def test_render_invalid():
    graph = nx.Graph()
    graph.add_node(0)
    style = nxv.Style(
        node={"label": H.table(["x"], attributes={"notanattribute": "y"})})
    with pytest.raises(nxv.GraphVizError):
        nxv.render(graph, style, format="svg")
Example #3
0
def test_html_like_labels():
    graph = nx.OrderedDiGraph()
    graph.add_node(
        0,
        label=H.table([
            H.table_row([H.table_cell("A", attributes={"COLSPAN": 2})]),
            H.table_row([H.table_cell("C"),
                         H.table_cell("D")]),
        ]),
    )
    graph.add_node(1, label=H.bold('3 < 7 "hello" & "world" 5 > 2'))
    graph.add_node(2, label=H.join(["hello", H.italic("world")]))
    graph.add_edge(0, 1)
    style = nxv.Style(node=lambda u, d: d)
    actual = nxv.render(graph, style, format="raw")
    expected = textwrap.dedent("""
        digraph "G" {
            graph [];
            node0000 [label=<<TABLE><TR><TD COLSPAN="2">A</TD></TR><TR><TD>C</TD><TD>D</TD></TR></TABLE>>];
            node0001 [label=<<B>3 &lt; 7 &quot;hello&quot; &amp; &quot;world&quot; 5 &gt; 2</B>>];
            node0002 [label=<hello<I>world</I>>];
            node0000 -> node0001 [];
        }
        """).strip()
    assert actual == expected
Example #4
0
def test_render():
    graph = nx.DiGraph()
    nx.add_path(graph, [0, 1, 2, 3])
    graph.add_edges_from([("even", 0), ("even", 2), ("odd", 1), ("odd", 3)])

    def int_color(n):
        return "gray" if n % 2 == 0 else "darkred"

    style = nxv.Style(
        graph={
            "label": "Beware the odd numbers!",
            "labelloc": "t"
        },
        node=nxv.switch(
            lambda u, d: type(u),
            {
                str: {
                    "shape": "diamond"
                },
                int: lambda u, d: {
                    "shape": "circle",
                    "style": "filled",
                    "color": int_color(u),
                    "fontcolor": "white",
                },
            },
        ),
        edge=nxv.switch(
            lambda u, v, d: (type(u), type(v)),
            {
                (str, int): lambda u, v, d: {
                    "color": int_color(v)
                },
                (int, int): {
                    "dir": "none",
                    "style": "dashed"
                },
            },
        ),
    )

    nxv.render(graph, style, format="svg")
Example #5
0
def test_render_multi():
    graph = nx.MultiDiGraph()
    graph.add_edge(0, 1, key="LessThan")
    graph.add_edge(0, 2, key="LessThan")
    graph.add_edge(1, 2, key="LessThan")
    graph.add_edge(0, 1, key="Successor")
    graph.add_edge(1, 2, key="Successor")

    style = nxv.Style(edge=nxv.switch(
        lambda u, v, k, d: k,
        {
            "LessThan": lambda u, v, k, d: {
                "color": "red",
                "label": f"{u} < {v}",
            },
            "Successor": lambda u, v, k, d: {
                "color": "blue",
                "label": f"{u} + 1 = {v}",
            },
        },
    ))

    nxv.render(graph, style, format="svg")
Example #6
0
File: docs.py Project: twosigma/nxv
def build_logo():
    shutil.rmtree("docs/_static/logo", ignore_errors=True)
    os.makedirs("docs/_static/logo", exist_ok=True)
    graph = nx.Graph()
    nx.add_path(graph, [0, 1, 2, 3, 4, 5, 0])
    nx.add_star(graph, [6, 0, 1, 2, 3, 4, 5])
    style = nxv.Style(
        graph={
            "pad": 1 / 8,
            "bgcolor": "#00000000",
            "size": "1,1",
            "ratio": 1,
        },
        node=lambda u, d: {
            "shape": "circle",
            "label": None,
            "width": 3 / 4,
            "style": "filled",
            "fillcolor": "#009AA6" if u % 2 else "#E37222",
            "penwidth": 5,
        },
        edge={"penwidth": 5},
    )
    path = "docs/_static/logo/logo.svg"
    LOGGER.info(f"Rendering {path}")
    with open(path, "wb") as f:
        f.write(nxv.render(graph, style, algorithm="neato", format="svg"))
    for size in [16, 32, 40, 48, 64, 128, 256]:
        style_with_dpi = nxv.compose([style, nxv.Style(graph={"dpi": size})])
        path = f"docs/_static/logo/logo-{size}.png"
        LOGGER.info(f"Rendering {path}")
        with open(path, "wb") as f:
            f.write(
                nxv.render(graph,
                           style_with_dpi,
                           algorithm="neato",
                           format="png"))
Example #7
0
def test_multiline_labels():
    graph = nx.OrderedDiGraph()
    graph.add_node(0, label="A\nB")
    graph.add_node(1, label="C\nD")
    graph.add_edge(0, 1)
    style = nxv.Style(node=lambda u, d: d)
    actual = nxv.render(graph, style, format="raw")
    expected = textwrap.dedent("""
        digraph "G" {
            graph [];
            node0000 [label="A
        B"];
            node0001 [label="C
        D"];
            node0000 -> node0001 [];
        }
        """).strip()
    assert actual == expected
Example #8
0
def test_subgraph_indentation():
    graph = nx.OrderedDiGraph()
    graph.add_node("A")
    graph.add_node("B")
    graph.add_edge("A", "B")
    actual = nxv.render(graph, subgraph_func=lambda u, d: u, format="raw")
    expected = textwrap.dedent("""
        digraph "G" {
            graph [];
            subgraph "A" {
                graph [];
                node0000 [label="A"];
            }
            subgraph "B" {
                graph [];
                node0001 [label="B"];
            }
            node0000 -> node0001 [];
        }
        """).strip()
    assert actual == expected
Example #9
0
def render(plan: typing.Union[Plan, Graph,
                              typing.Tuple[Plan, typing.Optional[Node]]],
           *,
           registry: Registry = None,
           predicate: typing.Callable[[Node, dict], bool] = None,
           level: typing.Optional[int] = None,
           format: typing.Optional[str] = None) -> typing.Optional[bytes]:
    """
    Use :mod:`nxv` to render a plan's symbolic call graph.

    :param plan: A plan's symbolic call graph.
    :param registry: A registry to include in the visualization.
    :param predicate: An optional node predicate ``f(u, d)`` that determines whether a node ``u`` with
                      attribute dict ``d`` will be included in the render.
    :param level: Optional maximum number of scope levels to view. Nodes are grouped by scope[:level].
    :param format: The nxv/GraphViz output format to produce.
    :return: The rendered graph.
    """
    import nxv

    if (isinstance(plan, tuple) and len(plan) == 2
            and isinstance(plan[0], Plan)
            and (isinstance(plan[1], Node) or plan[1] is None)):
        plan = plan[0]
    validation.assert_is_instance(plan, "plan", (Plan, Graph))
    graph = (plan.graph if isinstance(plan, Plan) else plan).copy()
    if predicate:
        graph.remove_nodes_from(
            [u for u, d in graph.nodes(data=True) if not predicate(u, d)])

    if level is not None:
        scope_groups = OrderedDict()
        for u in graph.nodes():
            scope = get_scope(graph, u)
            if scope:
                scope_groups.setdefault(scope[:level], []).append(u)
        for scope, group in scope_groups.items():
            group = set(group)
            predecessors = set()
            successors = set()
            for w in group:
                predecessors.update(graph.predecessors(w))
                successors.update(
                    (v, e) for _, v, e in graph.out_edges(w, keys=True))
            scope_node = Scope()
            graph.add_node(scope_node, scope=scope, count=len(group))
            graph.remove_nodes_from(group)
            graph.add_edges_from((predecessor, scope_node, Dependency())
                                 for predecessor in predecessors
                                 if predecessor not in group)
            graph.add_edges_from((scope_node, successor, dependency)
                                 for successor, dependency in successors
                                 if successor not in group)

    style = default_style(registry)
    return nxv.render(
        graph,
        style,
        algorithm="dot",
        format=format,
    )
Example #10
0
File: docs.py Project: twosigma/nxv
def build_example(example):
    path = f"docs/_static/example/{example.__name__}.svg"
    LOGGER.info(f"Rendering {path}")
    with open(path, "wb") as f:
        f.write(nxv.render(**example(), format="svg"))
Example #11
0
def test_render_strange_characters():
    graph = nx.Graph()
    nx.add_path(graph, range(1000))
    style = nxv.Style(node=lambda u, d: {"label": f"{u}:{chr(u)}"})
    nxv.render(graph, style, format="svg")
Example #12
0
def test_render_default_format_inside_ipython():
    graph = nx.Graph()
    graph.add_edge("A", "B")
    output = nxv.render(graph, format="svg")
    with assert_ipython_display_call(output, "ipython/svg"):
        nxv.render(graph)
Example #13
0
def test_render_default_format_outside_ipython():
    graph = nx.Graph()
    with pytest.raises(ValueError):
        nxv.render(graph)
Example #14
0
def test_render_color():
    graph = nx.Graph()
    graph.add_node(0)
    style = nxv.Style(node={"label": None, "color": (1, 1, 1)})
    nxv.render(graph, style, format="svg")