docs: def toposort(data):
      """
      Dependencies are expressed as a dictionary whose keys are items
      and whose values are a set of dependent items. Output is a list of
      sets in topological order. The first set consists of items with no
      dependences, each subsequent set consists of items that depend upon
      items in the preceeding sets.
      :param data:
      :type data:
      :return:
      :rtype:
      """
  
      # Special case empty input.
      if len(data) == 0:
          return
  
      # Copy the input so as to leave it unmodified.
      data = data.copy()
  
      # Ignore self dependencies.
      for k, v in data.items():
          v.discard(k)
      # Find all items that don't depend on anything.
      extra_items_in_deps = reduce(set.union, data.values()) - set(data.keys())
      # Add empty dependences where needed.
      data.update(dict((item, set()) for item in extra_items_in_deps))
      while True:
          ordered = set(item for item, dep in data.items() if len(dep) == 0)
          if not ordered:
              break
          yield ordered
          data = dict((item, (dep - ordered))
                  for item, dep in data.items()
                  if item not in ordered)
      if len(data) != 0:
          raise CyclicDependency(data)