code: def _toposort(dsk, keys=None, returncycle=False, dependencies=None):
      # Stack-based depth-first search traversal.  This is based on Tarjan's
      # method for topological sorting (see wikipedia for pseudocode)
      if keys is None:
          keys = dsk
      elif not isinstance(keys, list):
          keys = [keys]
      if not returncycle:
          ordered = []
  
      # Nodes whose descendents have been completely explored.
      # These nodes are guaranteed to not be part of a cycle.
      completed = set()
  
      # All nodes that have been visited in the current traversal.  Because
      # we are doing depth-first search, going "deeper" should never result
      # in visiting a node that has already been seen.  The `seen` and
      # `completed` sets are mutually exclusive; it is okay to visit a node
      # that has already been added to `completed`.
      seen = set()
  
      if dependencies is None:
          dependencies = {k: get_dependencies(dsk, k) for k in dsk}
  
      for key in keys:
          if key in completed:
              continue
          nodes = [key]
          while nodes:
              # Keep current node on the stack until all descendants are visited
              cur = nodes[-1]
              if cur in completed:
                  # Already fully traversed descendants of cur
                  nodes.pop()
                  continue
              seen.add(cur)
  
              # Add direct descendants of cur to nodes stack
              next_nodes = []
              for nxt in dependencies[cur]:
                  if nxt not in completed:
                      if nxt in seen:
                          # Cycle detected!
                          # Let's report only the nodes that directly participate in the cycle.
                          # We use `priorities` below to greedily construct a short cycle.
                          # Shorter cycles may exist.
                          priorities = {}
                          prev = nodes[-1]
                          # Give priority to nodes that were seen earlier.
                          while nodes[-1] != nxt:
                              priorities[nodes.pop()] = -len(priorities)
                          priorities[nxt] = -len(priorities)
                          # We're going to get the cycle by walking backwards along dependents,
                          # so calculate dependents only for the nodes in play.
                          inplay = set(priorities)
                          dependents = reverse_dict(
                              {
                                  k: inplay.intersection(
                                      dependencies[k]
                                  )
                                  for k in inplay
                              }
                          )
                          # Begin with the node that was seen twice and the node `prev` from
                          # which we detected the cycle.
                          cycle = [nodes.pop()]
                          cycle.append(prev)
                          while prev != cycle[0]:
                              # Greedily take a step that takes us closest to completing the cycle.
                              # This may not give us the shortest cycle, but we get *a* short cycle.
                              deps = dependents[cycle[-1]]
                              prev = min(
                                  deps, key=priorities.__getitem__
                              )
                              cycle.append(prev)
                          cycle.reverse()
  
                          if returncycle:
                              return cycle
                          else:
                              cycle = "->".join(str(x) for x in cycle)
                              raise RuntimeError(
                                  "Cycle detected in Dask: %s" % cycle
                              )
                      next_nodes.append(nxt)
  
              if next_nodes:
                  nodes.extend(next_nodes)
              else:
                  # cur has no more descendants to explore, so we're done with it
                  if not returncycle:
                      ordered.append(cur)
                  completed.add(cur)
                  seen.remove(cur)
                  nodes.pop()
      if returncycle:
          return []
      return ordered
  
imports: from __future__ import annotations
  from collections import defaultdict
  from collections.abc import Collection, Iterable, Mapping
  from typing import Any, Literal, TypeVar, cast, overload
  from dask.typing import Graph, Key, NoDefault, no_default
label_desc: Use image node_id 18 for calling a global function with example usage: _toposort(dsk, keys, returncycle, dependencies) and returns: ordered, list, cycle