def TopologicalSort(d):
  """Returns a topologically-sorted list of nodes.

  Args:
    d: a dictionary representing a directed acyclic graph in which each
       key represents a node and its value is a list of nodes it is connected
       to.

  Returns:
    A topologically-sorted list of all nodes.

  Raises:
    Exception: if a cycle is found.
  """
  visited = []
  sorted_nodes = []
  visiting = []  # For detecting cycles.

  def _Search(key):
    if key not in visited:
      if key in visiting:
        raise Exception('TopologicalSort found a cycle at key "' + key + '"')
      visiting.append(key)
      for edge in d.get(key, []):
        _Search(edge)
      visited.append(key)
      sorted_nodes.append(key)
      visiting.remove(key)

  for key in d.keys():
    _Search(key)

  # The DFS puts the leaves in the list first, so reverse it.
  sorted_nodes.reverse()
  return sorted_nodes