nodes: 0, module; 1, function_definition; 2, function_name:copartition; 3, parameters; 4, block; 5, identifier:self; 6, identifier:axis; 7, identifier:other; 8, identifier:how_to_join; 9, identifier:sort; 10, default_parameter; 11, expression_statement; 12, if_statement; 13, expression_statement; 14, expression_statement; 15, comment:# We have to set these because otherwise when we perform the functions it may; 16, comment:# end up serializing this entire object.; 17, expression_statement; 18, expression_statement; 19, comment:# Start with this and we'll repartition the first time, and then not again.; 20, expression_statement; 21, expression_statement; 22, function_definition; 23, for_statement; 24, return_statement; 25, identifier:force_repartition; 26, False; 27, comment:"""Copartition two QueryCompiler objects.
  
          Args:
              axis: The axis to copartition along.
              other: The other Query Compiler(s) to copartition against.
              how_to_join: How to manage joining the index object ("left", "right", etc.)
              sort: Whether or not to sort the joined index.
              force_repartition: 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:
              A tuple (left query compiler, right query compiler list, joined index).
          """; 28, call; 29, block; 30, assignment; 31, assignment; 32, assignment; 33, assignment; 34, assignment; 35, assignment; 36, function_name:compute_reindex; 37, parameters; 38, block; 39, identifier:i; 40, call; 41, comment:# If the indices are equal we can skip partitioning so long as we are not; 42, comment:# forced to repartition. See note above about `force_repartition`.; 43, block; 44, expression_list; 45, identifier:isinstance; 46, argument_list; 47, expression_statement; 48, identifier:index_obj; 49, parenthesized_expression; 50, identifier:joined_index; 51, call; 52, identifier:left_old_idx; 53, conditional_expression:self.index if axis == 0 else self.columns; 54, identifier:right_old_idxes; 55, identifier:index_obj; 56, identifier:reindexed_self; 57, attribute; 58, identifier:reindexed_other_list; 59, list; 60, identifier:old_idx; 61, expression_statement; 62, function_definition; 63, return_statement; 64, identifier:range; 65, argument_list; 66, if_statement; 67, if_statement; 68, expression_statement; 69, expression_statement; 70, identifier:reindexed_self; 71, identifier:reindexed_other_list; 72, identifier:joined_index; 73, identifier:other; 74, call; 75, assignment; 76, conditional_expression:[o.index for o in other] if axis == 0 else [o.columns for o in other]; 77, attribute; 78, argument_list; 79, attribute; 80, comparison_operator:axis == 0; 81, attribute; 82, identifier:self; 83, identifier:data; 84, comment:"""Create a function based on the old index and axis.
  
              Args:
                  old_idx: The old index/columns
  
              Returns:
                  A function that will be run in each partition.
              """; 85, function_name:reindex_partition; 86, parameters; 87, block; 88, identifier:reindex_partition; 89, call; 90, boolean_operator; 91, block; 92, else_clause; 93, boolean_operator; 94, block; 95, else_clause; 96, assignment; 97, call; 98, identifier:type; 99, argument_list; 100, identifier:other; 101, list; 102, list_comprehension; 103, comparison_operator:axis == 0; 104, list_comprehension; 105, identifier:self; 106, identifier:_join_index_objects; 107, binary_operator:axis ^ 1; 108, identifier:index_obj; 109, identifier:how_to_join; 110, keyword_argument; 111, identifier:self; 112, identifier:index; 113, identifier:axis; 114, integer:0; 115, identifier:self; 116, identifier:columns; 117, identifier:df; 118, if_statement; 119, return_statement; 120, identifier:len; 121, argument_list; 122, comparison_operator:i != 0; 123, parenthesized_expression; 124, expression_statement; 125, block; 126, call; 127, not_operator; 128, expression_statement; 129, block; 130, pattern_list; 131, call; 132, attribute; 133, argument_list; 134, identifier:self; 135, identifier:other; 136, attribute; 137, for_in_clause; 138, identifier:axis; 139, integer:0; 140, attribute; 141, for_in_clause; 142, identifier:axis; 143, integer:1; 144, identifier:sort; 145, identifier:sort; 146, comparison_operator:axis == 0; 147, block; 148, else_clause; 149, identifier:new_df; 150, identifier:other; 151, identifier:i; 152, integer:0; 153, boolean_operator; 154, assignment; 155, expression_statement; 156, attribute; 157, argument_list; 158, identifier:force_repartition; 159, assignment; 160, expression_statement; 161, identifier:reindexed_self; 162, identifier:reindexed_other; 163, attribute; 164, argument_list; 165, identifier:reindexed_other_list; 166, identifier:append; 167, identifier:reindexed_other; 168, identifier:o; 169, identifier:index; 170, identifier:o; 171, identifier:other; 172, identifier:o; 173, identifier:columns; 174, identifier:o; 175, identifier:other; 176, identifier:axis; 177, integer:0; 178, expression_statement; 179, expression_statement; 180, expression_statement; 181, block; 182, call; 183, not_operator; 184, identifier:reindex_left; 185, None; 186, assignment; 187, subscript; 188, identifier:equals; 189, identifier:joined_index; 190, identifier:reindex_right; 191, None; 192, assignment; 193, identifier:reindexed_self; 194, identifier:copartition_datasets; 195, identifier:axis; 196, attribute; 197, identifier:reindex_left; 198, identifier:reindex_right; 199, assignment; 200, assignment; 201, assignment; 202, expression_statement; 203, expression_statement; 204, expression_statement; 205, attribute; 206, argument_list; 207, identifier:force_repartition; 208, identifier:reindex_left; 209, call; 210, identifier:right_old_idxes; 211, identifier:i; 212, identifier:reindex_right; 213, call; 214, subscript; 215, identifier:data; 216, attribute; 217, identifier:old_idx; 218, identifier:new_df; 219, call; 220, attribute; 221, call; 222, assignment; 223, assignment; 224, assignment; 225, identifier:left_old_idx; 226, identifier:equals; 227, identifier:joined_index; 228, attribute; 229, argument_list; 230, attribute; 231, argument_list; 232, identifier:other; 233, identifier:i; 234, identifier:df; 235, identifier:index; 236, attribute; 237, argument_list; 238, identifier:new_df; 239, identifier:index; 240, attribute; 241, argument_list; 242, attribute; 243, identifier:old_idx; 244, identifier:new_df; 245, call; 246, attribute; 247, call; 248, identifier:self; 249, identifier:_prepare_method; 250, call; 251, subscript; 252, identifier:_prepare_method; 253, call; 254, identifier:df; 255, identifier:reindex; 256, keyword_argument; 257, identifier:pandas; 258, identifier:RangeIndex; 259, call; 260, identifier:df; 261, identifier:columns; 262, attribute; 263, argument_list; 264, identifier:new_df; 265, identifier:columns; 266, attribute; 267, argument_list; 268, identifier:compute_reindex; 269, argument_list; 270, identifier:other; 271, identifier:i; 272, identifier:compute_reindex; 273, argument_list; 274, identifier:index; 275, identifier:joined_index; 276, identifier:len; 277, argument_list; 278, identifier:df; 279, identifier:reindex; 280, keyword_argument; 281, identifier:pandas; 282, identifier:RangeIndex; 283, call; 284, identifier:left_old_idx; 285, subscript; 286, attribute; 287, identifier:columns; 288, identifier:joined_index; 289, identifier:len; 290, argument_list; 291, identifier:right_old_idxes; 292, identifier:i; 293, identifier:new_df; 294, identifier:index; 295, attribute; 296, identifier:new_df; 297, identifier:columns
code: def copartition(self, axis, other, how_to_join, sort, force_repartition=False):
          """Copartition two QueryCompiler objects.
  
          Args:
              axis: The axis to copartition along.
              other: The other Query Compiler(s) to copartition against.
              how_to_join: How to manage joining the index object ("left", "right", etc.)
              sort: Whether or not to sort the joined index.
              force_repartition: 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:
              A tuple (left query compiler, right query compiler list, joined index).
          """
          if isinstance(other, type(self)):
              other = [other]
  
          index_obj = (
              [o.index for o in other] if axis == 0 else [o.columns for o in other]
          )
          joined_index = self._join_index_objects(
              axis ^ 1, index_obj, how_to_join, sort=sort
          )
          # We have to set these because otherwise when we perform the functions it may
          # end up serializing this entire object.
          left_old_idx = self.index if axis == 0 else self.columns
          right_old_idxes = index_obj
  
          # Start with this and we'll repartition the first time, and then not again.
          reindexed_self = self.data
          reindexed_other_list = []
  
          def compute_reindex(old_idx):
              """Create a function based on the old index and axis.
  
              Args:
                  old_idx: The old index/columns
  
              Returns:
                  A function that will be run in each partition.
              """
  
              def reindex_partition(df):
                  if axis == 0:
                      df.index = old_idx
                      new_df = df.reindex(index=joined_index)
                      new_df.index = pandas.RangeIndex(len(new_df.index))
                  else:
                      df.columns = old_idx
                      new_df = df.reindex(columns=joined_index)
                      new_df.columns = pandas.RangeIndex(len(new_df.columns))
                  return new_df
  
              return reindex_partition
  
          for i in range(len(other)):
  
              # If the indices are equal we can skip partitioning so long as we are not
              # forced to repartition. See note above about `force_repartition`.
              if i != 0 or (left_old_idx.equals(joined_index) and not force_repartition):
                  reindex_left = None
              else:
                  reindex_left = self._prepare_method(compute_reindex(left_old_idx))
              if right_old_idxes[i].equals(joined_index) and not force_repartition:
                  reindex_right = None
              else:
                  reindex_right = other[i]._prepare_method(
                      compute_reindex(right_old_idxes[i])
                  )
  
              reindexed_self, reindexed_other = reindexed_self.copartition_datasets(
                  axis, other[i].data, reindex_left, reindex_right
              )
              reindexed_other_list.append(reindexed_other)
          return reindexed_self, reindexed_other_list, joined_index