# Buggy code
def _copartition(self, axis, other, how, sort, force_repartition=False):
    """
    Copartition two dataframes.

    Perform aligning of partitions, index and partition blocks.

    Parameters
    ----------
    axis : 0 or 1
        The axis to copartition along (0 - rows, 1 - columns).
    other : BasePandasFrame
        The other dataframes(s) to copartition against.
    how : str
        How to manage joining the index object ("left", "right", etc.)
    sort : boolean
        Whether or not to sort the joined index.
    force_repartition : bool, default False
        Whether or not to force the repartitioning. By default,
        this method will skip repartitioning if it is possible. This is because
        reindexing is extremely inefficient. Because this method is used to
        `join` or `append`, it is vital that the internal indices match.

    Returns
    -------
    Tuple
        A tuple (left data, right data list, joined index).
    """
    if isinstance(other, type(self)):
        other = [other]

    # define helper functions
    def get_axis_lengths(partitions, axis):
        if axis:
            return [obj.width() for obj in partitions[0]]
        return [obj.length() for obj in partitions.T[0]]

    self_index = self.axes[axis]
    others_index = [o.axes[axis] for o in other]
    joined_index, make_reindexer = self._join_index_objects(
        axis, [self_index] + others_index, how, sort
    )

    # define conditions for reindexing and repartitioning `self` frame
    do_reindex_self = not self_index.equals(joined_index)
    do_repartition_self = force_repartition or do_reindex_self

    # perform repartitioning and reindexing for `self` frame if needed
    if do_repartition_self:
        reindexed_self = self._frame_mgr_cls.map_axis_partitions(
            axis,
            self._partitions,
            # self frame has 0 idx
            make_reindexer(do_reindex_self, 0),
        )
    else:
        reindexed_self = self._partitions

    # define length of `self` and `other` frames to aligning purpose
    self_lengths = get_axis_lengths(reindexed_self, axis)
    others_lengths = [o._axes_lengths[axis] for o in other]

    # define conditions for reindexing and repartitioning `other` frames
    do_reindex_others = [not index.equals(joined_index) for index in others_index]

    do_repartition_others = [None] * len(other)
    for i in range(len(other)):
        do_repartition_others[i] = (
            force_repartition
            or do_reindex_others[i]
            or others_lengths[i] != self_lengths
        )

    # perform repartitioning and reindexing for `other` frames if needed
    reindexed_other_list = [None] * len(other)
    for i in range(len(other)):
        if do_repartition_others[i]:
            reindexed_other_list[i] = other[i]._frame_mgr_cls.map_axis_partitions(
                axis,
                other[i]._partitions,
                # indices of others frame start from 1 (0 - self frame)
                make_reindexer(do_reindex_others[i], 1 + i),
                lengths=self_lengths,
            )
        else:
            reindexed_other_list[i] = other[i]._partitions

    return reindexed_self, reindexed_other_list, joined_index


# Traceback (TypeError)
Traceback (most recent call last):
File "test_outer.py", line 13, in <module>
md_df["b"] = pd.Series(np.zeros(len(md_df))) # TypeError
File "/localdisk/dchigare/repos/modin_bp/modin/pandas/dataframe.py", line 1978, in __setitem__
join="left",
File "/localdisk/dchigare/repos/modin_bp/modin/backends/pandas/query_compiler.py", line 303, in concat
new_modin_frame = self._modin_frame._concat(axis, other_modin_frame, join, sort)
File "/localdisk/dchigare/repos/modin_bp/modin/engines/base/frame/data.py", line 1850, in _concat
axis ^ 1, others, how, sort, force_repartition=True
File "/localdisk/dchigare/repos/modin_bp/modin/engines/base/frame/data.py", line 1701, in _copartition
joined_index = self._join_index_objects(axis, index_other_obj, how, sort)
File "/localdisk/dchigare/repos/modin_bp/modin/engines/base/frame/data.py", line 980, in _join_index_objects
joined_obj = merge_index(joined_obj, obj)
File "/localdisk/dchigare/repos/modin_bp/modin/engines/base/frame/data.py", line 974, in merge_index
return obj1.join(obj2, how=how, sort=sort)
File "/localdisk/dchigare/miniconda3/envs/modin_tests/lib/python3.7/site-packages/pandas/core/indexes/datetimelike.py", line 893, in join
sort=sort,
File "/localdisk/dchigare/miniconda3/envs/modin_tests/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 3483, in join
return this.join(other, how=how, return_indexers=return_indexers)
File "/localdisk/dchigare/miniconda3/envs/modin_tests/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 3494, in join
other, how=how, return_indexers=return_indexers
File "/localdisk/dchigare/miniconda3/envs/modin_tests/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 3815, in _join_monotonic
join_index, lidx, ridx = self._left_indexer(sv, ov)
File "/localdisk/dchigare/miniconda3/envs/modin_tests/lib/python3.7/site-packages/pandas/core/indexes/base.py", line 257, in _left_indexer
return libjoin.left_join_indexer(left, right)
File "pandas/_libs/join.pyx", line 357, in pandas._libs.join.left_join_indexer
TypeError: '<' not supported between instances of 'Timestamp' and 'int'

# Fixed code
def _copartition(self, axis, other, how, sort, force_repartition=False):
    """
    Copartition two dataframes.

    Perform aligning of partitions, index and partition blocks.

    Parameters
    ----------
    axis : 0 or 1
        The axis to copartition along (0 - rows, 1 - columns).
    other : BasePandasFrame
        The other dataframes(s) to copartition against.
    how : str
        How to manage joining the index object ("left", "right", etc.)
    sort : boolean
        Whether or not to sort the joined index.
    force_repartition : bool, default False
        Whether or not to force the repartitioning. By default,
        this method will skip repartitioning if it is possible. This is because
        reindexing is extremely inefficient. Because this method is used to
        `join` or `append`, it is vital that the internal indices match.

    Returns
    -------
    Tuple
        A tuple (left data, right data list, joined index).
    """
    if isinstance(other, type(self)):
        other = [other]

    # define helper functions
    def get_axis_lengths(partitions, axis):
        if axis:
            return [obj.width() for obj in partitions[0]]
        return [obj.length() for obj in partitions.T[0]]

    self_index = self.axes[axis]
    others_index = [o.axes[axis] for o in other]
    joined_index, make_reindexer = self._join_index_objects(
        axis, [self_index] + others_index, how, sort
    )

    frames = [self] + other
    non_empty_frames_idx = [i for i, o in enumerate(frames) if o._partitions.size != 0]

    # If all frames are empty
    if len(non_empty_frames_idx) == 0:
        return self._partitions, [o._partitions for o in other], joined_index

    base_frame_idx = non_empty_frames_idx[0]
    base_frame = frames[base_frame_idx]

    other_frames = frames[base_frame_idx + 1 :]

    # Picking first non-empty frame
    base_frame = frames[non_empty_frames_idx[0]]
    base_index = base_frame.axes[axis]

    # define conditions for reindexing and repartitioning `self` frame
    do_reindex_base = not base_index.equals(joined_index)
    do_repartition_base = force_repartition or do_reindex_base

    # perform repartitioning and reindexing for `base_frame` if needed
    if do_repartition_base:
        reindexed_base = base_frame._frame_mgr_cls.map_axis_partitions(
            axis,
            base_frame._partitions,
            make_reindexer(do_reindex_base, base_frame_idx),
        )
    else:
        reindexed_base = base_frame._partitions

    # define length of base and `other` frames to aligning purpose
    base_lengths = get_axis_lengths(reindexed_base, axis)
    others_lengths = [o._axes_lengths[axis] for o in other_frames]

    # define conditions for reindexing and repartitioning `other` frames
    do_reindex_others = [not o.axes[axis].equals(joined_index) for o in other_frames]

    do_repartition_others = [None] * len(other_frames)
    for i in range(len(other_frames)):
        do_repartition_others[i] = (
            force_repartition
            or do_reindex_others[i]
            or others_lengths[i] != base_lengths
        )

    # perform repartitioning and reindexing for `other` frames if needed
    reindexed_other_list = [None] * len(other_frames)
    for i in range(len(other_frames)):
        if do_repartition_others[i]:
            # indices of others frame start from `base_frame_idx` + 1
            reindexed_other_list[i] = other_frames[
                i
            ]._frame_mgr_cls.map_axis_partitions(
                axis,
                other[i]._partitions,
                make_reindexer(do_repartition_others[i], base_frame_idx + 1 + i),
                lengths=base_lengths,
            )
        else:
            reindexed_other_list[i] = other_frames[i]._partitions
    reindexed_frames = (
        [frames[i]._partitions for i in range(base_frame_idx)]
        + [reindexed_base]
        + reindexed_other_list
    )
    return reindexed_frames[0], reindexed_frames[1:], joined_index