code: def merge_doctrees(
      old: Node, new: Node, condition: Any
  ) -> Iterator[Node]:
      """Merge the `old` doctree with the `new` one while looking at nodes
      matching the `condition`.
  
      Each node which replaces another one or has been added to the `new` doctree
      will be yielded.
  
      :param condition:
          A callable which returns either ``True`` or ``False`` for a given node.
      """
      old_iter = old.findall(condition)
      new_iter = new.findall(condition)
      old_nodes = []
      new_nodes = []
      ratios = {}
      seen = set()
      # compare the nodes each doctree in order
      for old_node, new_node in zip_longest(old_iter, new_iter):
          if old_node is None:
              new_nodes.append(new_node)
              continue
          if not getattr(old_node, "uid", None):
              # maybe config.gettext_uuid has been changed.
              old_node.uid = uuid4().hex
          if new_node is None:
              old_nodes.append(old_node)
              continue
          ratio = get_ratio(old_node.rawsource, new_node.rawsource)
          if ratio == 0:
              new_node.uid = old_node.uid
              seen.add(new_node)
          else:
              ratios[old_node, new_node] = ratio
              old_nodes.append(old_node)
              new_nodes.append(new_node)
      # calculate the ratios for each unequal pair of nodes, should we stumble
      # on a pair which is equal we set the uid and add it to the seen ones
      for old_node, new_node in product(old_nodes, new_nodes):
          if new_node in seen or (old_node, new_node) in ratios:
              continue
          ratio = get_ratio(old_node.rawsource, new_node.rawsource)
          if ratio == 0:
              new_node.uid = old_node.uid
              seen.add(new_node)
          else:
              ratios[old_node, new_node] = ratio
      # choose the old node with the best ratio for each new node and set the uid
      # as long as the ratio is under a certain value, in which case we consider
      # them not changed but different
      ratios = sorted(ratios.items(), key=itemgetter(1))  # type: ignore[assignment]
      for (old_node, new_node), ratio in ratios:
          if new_node in seen:
              continue
          else:
              seen.add(new_node)
          if ratio < VERSIONING_RATIO:
              new_node.uid = old_node.uid
          else:
              new_node.uid = uuid4().hex
              yield new_node
      # create new uuids for any new node we left out earlier, this happens
      # if one or more nodes are simply added.
      for new_node in set(new_nodes) - seen:
          new_node.uid = uuid4().hex
          yield new_node
  
file_path: sphinx/sphinx/versioning.py
imports: from __future__ import annotations
  import pickle
  from itertools import product, zip_longest
  from operator import itemgetter
  from os import path
  from typing import TYPE_CHECKING, Any
  from uuid import uuid4
  from sphinx.transforms import SphinxTransform
label_desc: Use image node_id 2 for calling a global function with example usage: merge_doctrees(old, new, condition) without return types