nodes: 0, module; 1, function_definition; 2, function_name:collate; 3, parameters; 4, block; 5, list_splat_pattern; 6, dictionary_splat_pattern; 7, expression_statement; 8, expression_statement; 9, expression_statement; 10, expression_statement; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, function_definition; 15, for_statement; 16, while_statement; 17, identifier:iterables; 18, identifier:kwargs; 19, comment:"""Return an iterable ordered collation of the already-sorted items
      from each of ``iterables``, compared by kwarg ``key``.
  
      If ``reverse=True`` is passed, iterables must return their results in
      descending order rather than ascending.
  
      """; 20, assignment; 21, assignment; 22, assignment; 23, assignment; 24, assignment; 25, assignment; 26, function_name:gather_next_value; 27, parameters; 28, block; 29, pattern_list; 30, call; 31, block; 32, identifier:by_key; 33, block; 34, identifier:key; 35, call; 36, identifier:reverse; 37, call; 38, identifier:min_or_max; 39, conditional_expression:max if reverse else min; 40, identifier:rows; 41, list_comprehension; 42, identifier:next_values; 43, dictionary; 44, identifier:by_key; 45, list; 46, identifier:row; 47, identifier:index; 48, try_statement; 49, identifier:index; 50, identifier:row; 51, identifier:enumerate; 52, argument_list; 53, expression_statement; 54, expression_statement; 55, expression_statement; 56, expression_statement; 57, expression_statement; 58, expression_statement; 59, attribute; 60, argument_list; 61, attribute; 62, argument_list; 63, identifier:max; 64, identifier:reverse; 65, identifier:min; 66, call; 67, for_in_clause; 68, if_clause; 69, block; 70, except_clause; 71, else_clause; 72, identifier:rows; 73, call; 74, assignment; 75, call; 76, assignment; 77, yield; 78, call; 79, identifier:kwargs; 80, identifier:pop; 81, string; 82, lambda; 83, identifier:kwargs; 84, identifier:pop; 85, string; 86, False; 87, identifier:iter; 88, argument_list; 89, identifier:iterable; 90, identifier:iterables; 91, identifier:iterable; 92, expression_statement; 93, identifier:StopIteration; 94, block; 95, block; 96, identifier:gather_next_value; 97, argument_list; 98, pattern_list; 99, call; 100, attribute; 101, argument_list; 102, identifier:next_value; 103, call; 104, identifier:next_value; 105, identifier:gather_next_value; 106, argument_list; 107, string_content:key; 108, lambda_parameters; 109, identifier:a; 110, string_content:reverse; 111, identifier:iterable; 112, assignment; 113, pass_statement; 114, expression_statement; 115, expression_statement; 116, identifier:row; 117, identifier:index; 118, identifier:key_value; 119, identifier:index; 120, identifier:min_or_max; 121, argument_list; 122, identifier:by_key; 123, identifier:remove; 124, tuple; 125, attribute; 126, argument_list; 127, subscript; 128, identifier:index; 129, identifier:a; 130, identifier:next_value; 131, call; 132, assignment; 133, call; 134, identifier:by_key; 135, identifier:key_value; 136, identifier:index; 137, identifier:next_values; 138, identifier:pop; 139, identifier:index; 140, identifier:rows; 141, identifier:index; 142, identifier:next; 143, argument_list; 144, subscript; 145, identifier:next_value; 146, attribute; 147, argument_list; 148, identifier:row; 149, identifier:next_values; 150, identifier:index; 151, identifier:by_key; 152, identifier:append; 153, tuple; 154, call; 155, identifier:index; 156, identifier:key; 157, argument_list; 158, identifier:next_value
code: def collate(*iterables, **kwargs):
      """Return an iterable ordered collation of the already-sorted items
      from each of ``iterables``, compared by kwarg ``key``.
  
      If ``reverse=True`` is passed, iterables must return their results in
      descending order rather than ascending.
  
      """
      key = kwargs.pop('key', lambda a: a)
      reverse = kwargs.pop('reverse', False)
      min_or_max = max if reverse else min
  
      rows = [iter(iterable) for iterable in iterables if iterable]
      next_values = {}
      by_key = []
  
      def gather_next_value(row, index):
          try:
              next_value = next(row)
          except StopIteration:
              pass
          else:
              next_values[index] = next_value
              by_key.append((key(next_value), index))
  
      for index, row in enumerate(rows):
          gather_next_value(row, index)
  
      while by_key:
          key_value, index = min_or_max(by_key)
          by_key.remove((key_value, index))
          next_value = next_values.pop(index)
          yield next_value
          gather_next_value(rows[index], index)