docs: def od_replace_key(od, key, new_key, *args, **kw):
      '''
      Replace key(s) in OrderedDict ``od`` by new key(s) in-place (i.e.,
      preserving the order(s) of the key(s))
  
      Optional new value(s) for new key(s) can be provided as a positional
      argument (otherwise the old value(s) will be used):
  
          od_replace_key(od, key, new_key, new_value)
  
      To replace multiple keys, pass argument ``key`` as a list instance,
      or explicitly pass a keyword argument ``multi=True``:
  
          od_replace_key(od, keys, new_keys, [new_values,] multi=True)
  
      '''
      multi = kw.get('multi', False) or isinstance(key, list)
  
      if multi:
          if len(key) != len(new_key):
              raise ValueError('Length of keys (%s) does not match '
                               'length of new keys (%s)' % (len(key), len(new_key)))
          if args:
              new_value = args[0]
              if len(new_key) != len(new_value):
                  raise ValueError('Length of new keys (%s) does not match '
                                   'length of new values (%s)' %
                                   (len(new_key), len(new_value)))
              for k_old, k_new, v_new in zip(key, new_key, new_value):
                  od_replace_key(od, k_old, k_new, v_new)
          else:
              for k_old, k_new in zip(key, new_key):
                  od_replace_key(od, k_old, k_new)
          return
  
      # single key
  
      if args:
          value = args[0]
  
      if new_key == key:
          if args:
              OrderedDict.__setitem__(od, key, value)
          return
  
      # new_key != key
      if new_key in od: # new_key overwrites another existing key
          OrderedDict.__delitem__(od, new_key)
  
      if PY2:
          # modify internal variables
          _map = od._OrderedDict__map
          link = _map[key]
          link[2] = new_key
          del _map[key]
          _map[new_key] = link
          val = dict.pop(od, key)
          if args:
              val = value
          dict.__setitem__(od, new_key, val)
  
      else:
          # in PY3, OrderedDict is implemented in C
          # no access to private variables __map
          found = False
          keys = [] # keys after key
          for k in od:
              if k == key:
                  found = True
                  continue
              if found:
                  keys.append(k)
          # warning: can not use OrderedDict.pop, which calls del self[key]
          getitem = dict.__getitem__
          setitem = OrderedDict.__setitem__
          delitem = OrderedDict.__delitem__
          v = getitem(od, key)
          delitem(od, key)
          if args:
              v = value
          setitem(od, new_key, v)
          # shift keys to after new_key
          for k in keys:
              # od[k] = od.pop(k) # can not call this directly in MIDict
              v = getitem(od, k)
              delitem(od, k)
              setitem(od, k, v)