def _MI_setitem(self, args, value):
    'Separate __setitem__ function of MIMapping'
    indices = self.indices
    N = len(indices)
    empty = N == 0
    if empty: # init the dict
        index1, key, index2, index1_last = MI_parse_args(self, args, allow_new=True)
        exist_names = [index1]
        item = [key]
        try:
            MI_check_index_name(index2)
            exist_names.append(index2)
            item.append(value)
        except TypeError:
            Nvalue, value = get_value_len(value)
            if len(index2) != Nvalue:
                raise ValueError(
                    'Number of keys (%s) based on argument %s does not match '
                    'number of values (%s)' % (len(index2), index2, Nvalue))
            exist_names.extend(index2)
            item.extend(value)
        if index1_last:
            exist_names = exist_names[1:] + exist_names[:1]
            item = item[1:] + item[:1]

        _MI_init(self, [item], exist_names)
        return

    index1, key, index2, item, old_value = MI_parse_args(self, args, allow_new=True)
    names = force_list(indices.keys())
    is_new_key = item is None
    single = isinstance(index2, int)

    if single:
        index2_list = [index2]
        value = [value]
        old_value = [old_value]
    else:
        index2_list = index2
        Nvalue, value = get_value_len(value)
        if len(index2_list) != Nvalue:
            raise ValueError('Number of keys (%s) based on argument %s does not match '
                             'number of values (%s)' % (len(index2_list), index2, Nvalue))
        if is_new_key:
            old_value = [None] * Nvalue  # fake it

    # remove duplicate in index2_list
    index2_d = OrderedDict()
    for e, index in enumerate(index2_list):
        index2_d[index] = e # order of each unique index
    if len(index2_d) < len(index2_list): # exist duplicate indices
        idx = index2_d.values()
        index2_list = mget_list(index2_list, idx)
        value = mget_list(value, idx)
        old_value = mget_list(old_value, idx)

    # check duplicate values
    for i, v, old_v in zip(index2_list, value, old_value):
        # index2_list may contain index1; not allow duplicate value for index1 either
        if v in indices[i]:
            if is_new_key or v != old_v:
                raise ValueExistsError(v, i, names[i])

    if is_new_key:
        if set(index2_list + [index1]) != set(range(N)):
            raise ValueError('Indices of the new item do not match existing indices')

        d = {}
        d[index1] = key
        # index2_list may also override index1
        d.update(zip(index2_list, value))
        values = [d[i] for i in range(N)]  # reorder based on the indices
        key = values[0]
        val = values[1] if len(values) == 2 else values[1:]
        super(MIMapping, self).__setitem__(key, val)
        for i, v in zip(names[1:], values[1:]):
            indices[i][v] = key

    else: # not new key
#        import pdb;pdb.set_trace()
        key1 = item[0]
        item2 = list(item)  # copy item first
        mset_list(item2, index2_list, value) # index2_list may also override index1
        key2 = item2[0]
        val = item2[1] if len(item2) == 2 else item2[1:]
        if key1 == key2:
            super(MIMapping, self).__setitem__(key1, val)
        else:
            od_replace_key(self, key1, key2, val)

        for i, v_old, v_new in zip(names[1:], item[1:], item2[1:]):
            od_replace_key(indices[i], v_old, v_new, key2)