docs: def _merge(left, right, path=None, conflict=_Conflict.error):
      """
      Merges values in place from *right* into *left*.
  
      :param left: mapping to merge into
      :param right: mapping to merge from
      :param path: `list` of keys processed before (used for error reporting
          only, should only need to be provided by recursive calls)
      :param conflict: action to be taken on merge conflict, raising an error
          or overwriting an existing value
      :return: *left*, for convenience
      """
      path = path or []
      conflict = _Conflict(conflict)
  
      for key in right:
          if key in left:
              if isinstance(left[key], Mapping) and isinstance(right[key], Mapping):
                  # recurse, merge left and right dict values, update path for current 'step'
                  _merge(left[key], right[key], path + [key], conflict=conflict)
              elif left[key] != right[key]:
                  if conflict is _Conflict.error:
                      # not both dicts we could merge, but also not the same, this doesn't work
                      conflict_path = '.'.join(path + [key])
                      raise MergeConflictError('merge conflict at {}'.format(conflict_path), key=conflict_path)
                  else:
                      # overwrite left value with right value
                      left[key] = right[key]
              # else: left[key] is already equal to right[key], no action needed
          else:
              # key not yet in left or not considering conflicts, simple addition of right's mapping to left
              left[key] = right[key]
  
      return left