def test_switch(): func = switch( lambda x: x[0], { "A": lambda x: x.lower(), "B": lambda x: x.upper(), }, default=lambda x: x[::-1], ) assert _apply(func, "Apple") == "apple" assert _apply(func, "Banana") == "BANANA" assert _apply(func, "Cherry") == "yrrehC"
def test_chain(): func = chain([{"x": 7}, lambda name: {"name": name}, {"x": 8}]) assert _apply(func, "john") == {"x": 8, "name": "john"}
def test_apply_func(): assert _apply(lambda x, y: x + y, 2, 5) == 7
def test_apply_func_by_name(): assert _apply(lambda x, y: x + y, x=2, y=5) == 7
def test_apply_lit_ignores_arguments(): assert _apply(7, "garbage1", garbage2="garbage3") == 7
def test_apply_lit(): assert _apply(7) == 7
def _to_gv(graph, style: Style, subgraph_func=None): """ Serializes a `NetworkX`_ graph as a `GraphViz`_ string. :param graph: A `NetworkX`_ ``Graph``, ``DiGraph``, ``MultiGraph``, or ``MultiDiGraph``. :param style: A :class:`~nxv.Style` object. :param subgraph_func: An optional function ``f(u, d)`` that returns a subgraph key, where ``u`` is a `NetworkX`_ node and ``d`` is its attribute dict. :return: The raw `GraphViz`_ string format to pass as input to one of the GraphViz layout algorithms. """ if subgraph_func is None: subgraph_func = _default_subgraph_func graph_attrs = _apply(style.graph, graph, graph.graph) graph_type = graph_attrs.get( "type", "digraph" if nx.is_directed(graph) else "graph") assert graph_type in {"graph", "digraph"} edge_str = {"graph": "--", "digraph": "->"}[graph_type] ids = {u: f"node{i:04}" for i, u in enumerate(graph.nodes())} no_subgraph_nodes = [] subgraph_nodes = {} for u, d in graph.nodes(data=True): subgraph = _apply(subgraph_func, u, d) if subgraph is None: no_subgraph_nodes.append((u, d)) else: subgraph_nodes.setdefault(subgraph, []).append((u, d)) def node_declaration(u, d): node_attrs = _apply(style.node, u, d) return f"{ids[u]} {_attributes_modifier(node_attrs)};" def edge_declaration(*edge): u, v = edge[:2] edge_attrs = _apply(style.edge, *edge) return f"{ids[u]} {edge_str} {ids[v]} {_attributes_modifier(edge_attrs)};" def subgraph_declaration(subgraph, nodes, attrs): return _block( _graph_identifier("subgraph", attrs.get("name", str(subgraph))), [_graph_attrs_declaration(attrs)] + [node_declaration(u, d) for u, d in nodes], ) edges_kwargs = ({ "keys": True, "data": True } if is_multi_graph(graph) else { "data": True }) lines = _block( _graph_identifier(graph_type, graph_attrs.get("name", "G")), ([_graph_attrs_declaration(graph_attrs)] + [node_declaration(u, d) for u, d in no_subgraph_nodes] + [ line for subgraph, nodes in subgraph_nodes.items() for line in subgraph_declaration(subgraph, nodes, _apply(style.subgraph, subgraph)) ] + [edge_declaration(*edge) for edge in graph.edges(**edges_kwargs)]), ) return "\n".join(lines)
def edge_declaration(*edge): u, v = edge[:2] edge_attrs = _apply(style.edge, *edge) return f"{ids[u]} {edge_str} {ids[v]} {_attributes_modifier(edge_attrs)};"
def node_declaration(u, d): node_attrs = _apply(style.node, u, d) return f"{ids[u]} {_attributes_modifier(node_attrs)};"