docs: def filter_stack(graph, head, filters):
      """
      Perform a walk in a depth-first order starting
      at *head*.
  
      Returns (visited, removes, orphans).
  
      * visited: the set of visited nodes
      * removes: the list of nodes where the node
        data does not all *filters*
      * orphans: tuples of (last_good, node),
        where node is not in removes, is directly 
        reachable from a node in *removes* and 
        *last_good* is the closest upstream node that is not
        in *removes*.
      """
  
      visited, removes, orphans = set([head]), set(), set()
      stack = deque([(head, head)])
      get_data = graph.node_data
      get_edges = graph.out_edges
      get_tail = graph.tail
  
      while stack:
          last_good, node = stack.pop()
          data = get_data(node)
          if data is not None:
              for filtfunc in filters:
                  if not filtfunc(data):
                      removes.add(node)
                      break
              else:
                  last_good = node
          for edge in get_edges(node):
              tail = get_tail(edge)
              if last_good is not node:
                  orphans.add((last_good, tail))
              if tail not in visited:
                  visited.add(tail)
                  stack.append((last_good, tail))
  
      orphans = [(last_good, tail) for (last_good, tail) in orphans if tail not in removes]
      #orphans.sort()
  
      return visited, removes, orphans