def nx_contracted_nodes(G, u, v, self_loops=True, inplace=False):
    """
    copy of networkx function with inplace modification
    TODO: commit to networkx
    """
    import itertools as it
    if G.is_directed():
        in_edges = ((w, u, d) for w, x, d in G.in_edges(v, data=True)
                    if self_loops or w != u)
        out_edges = ((u, w, d) for x, w, d in G.out_edges(v, data=True)
                     if self_loops or w != u)
        new_edges = it.chain(in_edges, out_edges)
    else:
        new_edges = ((u, w, d) for x, w, d in G.edges(v, data=True)
                     if self_loops or w != u)
    if inplace:
        H = G
        new_edges = list(new_edges)
    else:
        H = G.copy()
    node_dict = nx_node_dict(H)
    v_data = node_dict[v]
    H.remove_node(v)
    H.add_edges_from(new_edges)
    if 'contraction' in node_dict[u]:
        node_dict[u]['contraction'][v] = v_data
    else:
        node_dict[u]['contraction'] = {v: v_data}
    return H
copy of networkx function with inplace modification
    TODO: commit to networkx