docs: def make_traverser(cls, source_data, target_data, relation_operation,
                         accessor=None, manage_back_references=True):
          """
          Factory method to create a tree traverser depending on the input
          source and target data combination.
  
          :param source_data: Source data.
          :param target_target: Target data.
          :param str relation_operation: Relation operation. On of the constants
            defined in :class:`everest.constants.RELATION_OPERATIONS`.
          :param accessor: Accessor for looking up target nodes for update
            operations.
          :param bool manage_back_references: If set, backreferences will
            automatically be updated in the target data.
          """
          reg = get_current_registry()
          prx_fac = reg.getUtility(IDataTraversalProxyFactory)
          if relation_operation == RELATION_OPERATIONS.ADD \
             or relation_operation == RELATION_OPERATIONS.UPDATE:
              if relation_operation == RELATION_OPERATIONS.ADD \
                 and not target_data is None:
                  raise ValueError('Must not provide target data with '
                                   'relation operation ADD.')
              source_proxy = prx_fac.make_proxy(source_data,
                                                None,
                                                RELATIONSHIP_DIRECTIONS.NONE,
                                                relation_operation)
              source_is_sequence = \
                  source_proxy.proxy_for == RESOURCE_KINDS.COLLECTION
              if not source_is_sequence:
                  source_id = source_proxy.get_id()
          else:
              source_proxy = None
              source_is_sequence = False
          if relation_operation == RELATION_OPERATIONS.REMOVE \
             or relation_operation == RELATION_OPERATIONS.UPDATE:
              rel_dir = RELATIONSHIP_DIRECTIONS.BIDIRECTIONAL
              if not manage_back_references:
                  rel_dir &= ~RELATIONSHIP_DIRECTIONS.REVERSE
              if relation_operation == RELATION_OPERATIONS.REMOVE:
                  if not source_data is None:
                      raise ValueError('Must not provide source data with '
                                       'relation operation REMOVE.')
                  target_proxy = prx_fac.make_proxy(target_data,
                                                    accessor,
                                                    rel_dir,
                                                    relation_operation)
              else: # UPDATE
                  if accessor is None:
                      raise ValueError('Need to provide an accessor when '
                                       'performing UPDATE operations.')
                  if not target_data is None:
                      target_root = target_data
                  elif not source_is_sequence:
                      # Look up the (single) target to update.
                      target_root = accessor.get_by_id(source_id)
                      if target_root is None:
                          raise ValueError('Entity with ID %s to update not '
                                           'found.' % source_id)
                  else:
                      # Look up collection of targets to update.
                      target_root = []
                      for src_prx in source_proxy:
                          tgt_ent_id = src_prx.get_id()
                          if tgt_ent_id is None:
                              continue
                          tgt_ent = accessor.get_by_id(tgt_ent_id)
                          if tgt_ent is None:
                              continue
                          target_root.append(tgt_ent)
                  target_proxy = prx_fac.make_proxy(target_root,
                                                    accessor,
                                                    rel_dir,
                                                    relation_operation)
              target_is_sequence = \
                      target_proxy.proxy_for == RESOURCE_KINDS.COLLECTION
          else:
              target_proxy = None
              target_is_sequence = False
          if not source_proxy is None and not target_proxy is None:
              # Check for source/target consistency.
              if not ((source_is_sequence and target_is_sequence) or
                      (not source_is_sequence and not target_is_sequence)):
                  raise ValueError('When both source and target root nodes are '
                                   'given, they can either both be sequences '
                                   'or both not be sequences.')
          return cls(source_proxy, target_proxy)