/usr/lib/python2.7/dist-packages/ipapython/graph.py is in python-ipalib 4.3.1-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80  | #
# Copyright (C) 2015  FreeIPA Contributors see COPYING for license
#
class Graph():
    """
    Simple oriented graph structure
    G = (V, E) where G is graph, V set of vertices and E list of edges.
    E = (tail, head) where tail and head are vertices
    """
    def __init__(self):
        self.vertices = set()
        self.edges = []
        self._adj = dict()
    def add_vertex(self, vertex):
        self.vertices.add(vertex)
        self._adj[vertex] = []
    def add_edge(self, tail, head):
        if tail not in self.vertices:
            raise ValueError("tail is not a vertex")
        if head not in self.vertices:
            raise ValueError("head is not a vertex")
        self.edges.append((tail, head))
        self._adj[tail].append(head)
    def remove_edge(self, tail, head):
        try:
            self.edges.remove((tail, head))
        except KeyError:
            raise ValueError(
                "graph does not contain edge: (%s, %s)" % (tail, head))
        self._adj[tail].remove(head)
    def remove_vertex(self, vertex):
        try:
            self.vertices.remove(vertex)
        except KeyError:
            raise ValueError("graph does not contain vertex: %s" % vertex)
        # delete _adjacencies
        del self._adj[vertex]
        for key, _adj in self._adj.items():
            _adj[:] = [v for v in _adj if v != vertex]
        # delete edges
        edges = [e for e in self.edges if e[0] != vertex and e[1] != vertex]
        self.edges[:] = edges
    def get_tails(self, head):
        """
        Get list of vertices where a vertex is on the right side of an edge
        """
        return [e[0] for e in self.edges if e[1] == head]
    def get_heads(self, tail):
        """
        Get list of vertices where a vertex is on the left side of an edge
        """
        return [e[1] for e in self.edges if e[0] == tail]
    def bfs(self, start=None):
        """
        Breadth-first search traversal of the graph from `start` vertex.
        Return a set of all visited vertices
        """
        if not start:
            start = list(self.vertices)[0]
        visited = set()
        queue = [start]
        while queue:
            vertex = queue.pop(0)
            if vertex not in visited:
                visited.add(vertex)
                queue.extend(set(self._adj.get(vertex, [])) - visited)
        return visited
 |