# Buggy code
def _join_index_objects(axis, indexes, how, sort):
    """
    Join the pair of index objects (columns or rows) by a given strategy.

    Unlike Index.join() in Pandas, if axis is 1, the sort is
    False, and how is "outer", the result will _not_ be sorted.

    Parameters
    ----------
    axis : 0 or 1
        The axis index object to join (0 - rows, 1 - columns).
    indexes : list(Index)
        The indexes to join on.
    how : {'left', 'right', 'inner', 'outer'}
        The type of join to join to make.
    sort : boolean
        Whether or not to sort the joined index

    Returns
    -------
    (Index, func)
        Joined index with make_reindexer func
    """
    assert isinstance(indexes, list)

    # define helper functions
    def merge(left_index, right_index):
        if axis == 1 and how == "outer" and not sort:
            return left_index.union(right_index, sort=False)
        else:
            return left_index.join(right_index, how=how, sort=sort)

    # define condition for joining indexes
    do_join_index = False
    for index in indexes[1:]:
        if not indexes[0].equals(index):
            do_join_index = True
            break

    # define condition for joining indexes with getting indexers
    is_duplicates = any(not index.is_unique for index in indexes) and axis == 0
    indexers = []
    if is_duplicates:
        indexers = [None] * len(indexes)

    # perform joining indexes
    if do_join_index:
        if len(indexes) == 2 and is_duplicates:
            # in case of count of indexes > 2 we should perform joining all indexes
            # after that get indexers
            # in the fast path we can obtain joined_index and indexers in one call
            joined_index, indexers[0], indexers[1] = indexes[0].join(
                indexes[1], how=how, sort=sort, return_indexers=True
            )
        else:
            joined_index = indexes[0]
            # TODO: revisit for performance
            for index in indexes[1:]:
                joined_index = merge(joined_index, index)

            if is_duplicates:
                for i, index in enumerate(indexes):
                    indexers[i] = index.get_indexer_for(joined_index)
    else:
        joined_index = indexes[0].copy()

    def make_reindexer(do_reindex: bool, frame_idx: int):
        # the order of the frames must match the order of the indexes
        if not do_reindex:
            return lambda df: df

        if is_duplicates:
            assert indexers != []

            return lambda df: df._reindex_with_indexers(
                {0: [joined_index, indexers[frame_idx]]},
                copy=True,
                allow_dups=True,
            )

        return lambda df: df.reindex(joined_index, axis=axis)

    return joined_index, make_reindexer


# 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 _join_index_objects(axis, indexes, how, sort):
    """
    Join the pair of index objects (columns or rows) by a given strategy.

    Unlike Index.join() in Pandas, if axis is 1, the sort is
    False, and how is "outer", the result will _not_ be sorted.

    Parameters
    ----------
    axis : 0 or 1
        The axis index object to join (0 - rows, 1 - columns).
    indexes : list(Index)
        The indexes to join on.
    how : {'left', 'right', 'inner', 'outer', None}
        The type of join to join to make. If `None` then joined index
        considered to be the first index in the `indexes` list.
    sort : boolean
        Whether or not to sort the joined index

    Returns
    -------
    (Index, func)
        Joined index with make_reindexer func
    """
    assert isinstance(indexes, list)

    # define helper functions
    def merge(left_index, right_index):
        if axis == 1 and how == "outer" and not sort:
            return left_index.union(right_index, sort=False)
        else:
            return left_index.join(right_index, how=how, sort=sort)

    # define condition for joining indexes
    all_indices_equal = all(indexes[0].equals(index) for index in [indexes[1:]])
    do_join_index = how is not None and not all_indices_equal

    # define condition for joining indexes with getting indexers
    need_indexers = (
        axis == 0
        and not all_indices_equal
        and any(not index.is_unique for index in indexes)
    )
    indexers = None

    # perform joining indexes
    if do_join_index:
        if len(indexes) == 2 and need_indexers:
            # in case of count of indexes > 2 we should perform joining all indexes
            # after that get indexers
            # in the fast path we can obtain joined_index and indexers in one call
            indexers = [None, None]
            joined_index, indexers[0], indexers[1] = indexes[0].join(
                indexes[1], how=how, sort=sort, return_indexers=True
            )
        else:
            joined_index = indexes[0]
            # TODO: revisit for performance
            for index in indexes[1:]:
                joined_index = merge(joined_index, index)
    else:
        joined_index = indexes[0].copy()

    if need_indexers and indexers is None:
        indexers = [index.get_indexer_for(joined_index) for index in indexes]

    def make_reindexer(do_reindex: bool, frame_idx: int):
        # the order of the frames must match the order of the indexes
        if not do_reindex:
            return lambda df: df

        if need_indexers:
            assert indexers is not None

            return lambda df: df._reindex_with_indexers(
                {0: [joined_index, indexers[frame_idx]]},
                copy=True,
                allow_dups=True,
            )

        return lambda df: df.reindex(joined_index, axis=axis)

    return joined_index, make_reindexer