from graphs import MutableGraph, Directed, Undirected

class SimpleGraph(MutableGraph):
    """Simple, inefficient, example implementation of the Graph ABC.

    Nodes are represented as a set, and edges as a dict.
    """

    class NodesView(MutableGraph.NodesView):

        def __init__(self, g):
            self.data = set()
            self.graph = g

        def __len__(self):
            return len(self.data)

        def __iter__(self):
            return iter(self.data)

        def __contains__(self, node):
            return node in self.data

        def add(self, node):
            self.data.add(node)
                
        def discard(self, node):
            # We need to make sure that all edges containing the node
            # are discarded as well.

            edges = self.graph.edges
            for edge in list(edges):
                if node in edge:
                    del edges[edge]
            self.data.discard(node)

        @classmethod
        def _from_iterable(cls, it):
            # Needed by the Set ABC
            return set(it)

        # Fixes a bug in old Python 3.0 releases
        def __iand__(self, c):
            for node in self - c:
                self.discard(node)
            return self

    class EdgesView(MutableGraph.EdgesView):

        def __init__(self, g):
            self.graph = g
            self.data = {}

        def __len__(self):
            return len(self.data)

        def __iter__(self):
            return iter(self.data)

        def __contains__(self, edge):
            return self._normalize(edge) in self.data

        def __getitem__(self, edge):
            return self.data[self._normalize(edge)]

        def __setitem__(self, edge, label):
            # We need to make sure all nodes get added to nodes.

            for node in edge:
                self.graph.nodes.add(node)
            self.data[self._normalize(edge)] = label

        def __delitem__(self, edge):
            del self.data[self._normalize(edge)]

class SimpleDirected(SimpleGraph, Directed):

    class EdgesView(SimpleGraph.EdgesView, Directed.EdgesView):
        _normalize = tuple

class SimpleUndirected(SimpleGraph, Undirected):

    class EdgesView(SimpleGraph.EdgesView, Undirected.EdgesView):
        _normalize = frozenset

if __name__ == '__main__':
    ug = SimpleUndirected()
    dg = SimpleDirected()
    assert type(dg.edges) == SimpleDirected.EdgesView
    ug.edges[1, 2] = 1
    ug.edges.add(2, 3)
    assert ug.edges[3, 2] == 1
    ug.edges.discard(3,2)
    assert 2, 3 not in ug
    dg.edges[1, 2] = 1
    assert (2, 1) not in dg.edges
    assert (2, 1) in ug.edges
    emptygraph = SimpleUndirected()
    assert emptygraph != ug
    assert emptygraph.nodes <= ug.nodes
    ug.nodes &= {1, 5}
    assert set(ug.nodes) == {1}
    ug.nodes.clear()
    assert emptygraph.nodes <= ug.nodes
    assert emptygraph == ug
