code: def concatenate_managers(
      mgrs_indexers, axes: list[Index], concat_axis: AxisInt, copy: bool
  ) -> Manager:
      """
      Concatenate block managers into one.
  
      Parameters
      ----------
      mgrs_indexers : list of (BlockManager, {axis: indexer,...}) tuples
      axes : list of Index
      concat_axis : int
      copy : bool
  
      Returns
      -------
      BlockManager
      """
      # TODO(ArrayManager) this assumes that all managers are of the same type
      if isinstance(mgrs_indexers[0][0], ArrayManager):
          return _concatenate_array_managers(
              mgrs_indexers, axes, concat_axis, copy
          )
  
      # Assertions disabled for performance
      # for tup in mgrs_indexers:
      #    # caller is responsible for ensuring this
      #    indexers = tup[1]
      #    assert concat_axis not in indexers
  
      if concat_axis == 0:
          return _concat_managers_axis0(mgrs_indexers, axes, copy)
  
      mgrs_indexers = _maybe_reindex_columns_na_proxy(
          axes, mgrs_indexers
      )
  
      concat_plans = [
          _get_mgr_concatenation_plan(mgr, indexers)
          for mgr, indexers in mgrs_indexers
      ]
      concat_plan = _combine_concat_plans(concat_plans)
      blocks = []
  
      for placement, join_units in concat_plan:
          unit = join_units[0]
          blk = unit.block
  
          if len(join_units) == 1 and not join_units[0].indexers:
              values = blk.values
              if copy:
                  values = values.copy()
              else:
                  values = values.view()
              fastpath = True
          elif _is_uniform_join_units(join_units):
              vals = [ju.block.values for ju in join_units]
  
              if not blk.is_extension:
                  # _is_uniform_join_units ensures a single dtype, so
                  #  we can use np.concatenate, which is more performant
                  #  than concat_compat
                  values = np.concatenate(vals, axis=1)
              else:
                  # TODO(EA2D): special-casing not needed with 2D EAs
                  values = concat_compat(vals, axis=1)
                  values = ensure_block_shape(values, ndim=2)
  
              values = ensure_wrapped_if_datetimelike(values)
  
              fastpath = blk.values.dtype == values.dtype
          else:
              values = _concatenate_join_units(join_units, copy=copy)
              fastpath = False
  
          if fastpath:
              b = blk.make_block_same_class(values, placement=placement)
          else:
              b = new_block_2d(values, placement=placement)
  
          blocks.append(b)
  
      return BlockManager(tuple(blocks), axes)
  
imports: from __future__ import annotations
  import copy
  import itertools
  from typing import TYPE_CHECKING, Sequence, cast
  import numpy
  from pandas._libs import NaT, internals
  from pandas._libs.missing import NA
  from pandas._typing import ArrayLike, AxisInt, DtypeObj, Manager, Shape
  from pandas.util._decorators import cache_readonly
  from pandas.core.dtypes.astype import astype_array
  from pandas.core.dtypes.cast import ensure_dtype_can_hold_na, find_common_type, np_find_common_type
  from pandas.core.dtypes.common import is_1d_only_ea_dtype, is_dtype_equal, is_scalar, needs_i8_conversion
  from pandas.core.dtypes.concat import concat_compat
  from pandas.core.dtypes.dtypes import DatetimeTZDtype, ExtensionDtype
  from pandas.core.dtypes.missing import is_valid_na_for_dtype, isna, isna_all
  import pandas.core.algorithms
  from pandas.core.arrays import DatetimeArray, ExtensionArray
  from pandas.core.arrays.sparse import SparseDtype
  from pandas.core.construction import ensure_wrapped_if_datetimelike
  from pandas.core.internals.array_manager import ArrayManager, NullArrayProxy
  from pandas.core.internals.blocks import ensure_block_shape, new_block_2d
  from pandas.core.internals.managers import BlockManager
label_desc: Use image node_id 3 for calling a global function with example usage: concatenate_managers(mgrs_indexers, axes, concat_axis, copy) and returns: BlockManager, _concatenate_array_managers, _concat_managers_axis0