def topological_sort(G):
    """Return a generator of nodes in topologically sorted order.

    A topological sort is a nonunique permutation of the nodes such that an
    edge from u to v implies that u appears before v in the topological sort
    order.

    Parameters
    ----------
    G : NetworkX digraph
        A directed graph

    Returns
    -------
    topologically_sorted_nodes : iterable
        An iterable of node names in topological sorted order.

    Raises
    ------
    NetworkXError
        Topological sort is defined for directed graphs only. If the graph G
        is undirected, a :exc:`NetworkXError` is raised.

    NetworkXUnfeasible
        If G is not a directed acyclic graph (DAG) no topological sort exists
        and a NetworkXUnfeasible exception is raised.  This can also be
        raised if G is changed while the returned iterator is being processed.

    RuntimeError
        If G is changed while the returned iterator is being processed.

    Examples
    --------
    To get the reverse order of the topological sort::

        >>> DG = nx.DiGraph([(1, 2), (2, 3)])
        >>> list(reversed(list(nx.topological_sort(DG))))
        [3, 2, 1]

    Notes
    -----
    This algorithm is based on a description and proof in
    Introduction to algorithms - a creative approach [1]_ .

    See also
    --------
    is_directed_acyclic_graph, lexicographical_topological_sort

    References
    ----------
    .. [1] Manber, U. (1989). Introduction to algorithms - a creative approach. Addison-Wesley.
        http://www.amazon.com/Introduction-Algorithms-A-Creative-Approach/dp/0201120372
    """
    if not G.is_directed():
        raise nx.NetworkXError(
            "Topological sort not defined on undirected graphs.")

    indegree_map = {v: d for v, d in G.in_degree() if d > 0}
    # These nodes have zero indegree and ready to be returned.
    zero_indegree = [v for v, d in G.in_degree() if d == 0]

    while zero_indegree:
        node = zero_indegree.pop()
        if node not in G:
            raise RuntimeError("Graph changed during iteration")
        for _, child in G.edges(node):
            try:
                indegree_map[child] -= 1
            except __HOLE__:
                raise RuntimeError("Graph changed during iteration")
            if indegree_map[child] == 0:
                zero_indegree.append(child)
                del indegree_map[child]

        yield node

    if indegree_map:
        raise nx.NetworkXUnfeasible("Graph contains a cycle or graph changed "
                                    "during iteration")
dataset/ETHPy150Open networkx/networkx/networkx/algorithms/dag.py/topological_sort