# Buggy code
def dataframe_sort_values(
    df,
    by,
    axis=0,
    ascending=True,
    inplace=False,
    kind="quicksort",
    na_position="last",
    ignore_index=False,
    parallel_kind="PSRS",
    psrs_kinds=None,
):
    """
    Sort by the values along either axis.
    :param df: input DataFrame.
    :param by: Name or list of names to sort by.
    :param axis: Axis to be sorted.
    :param ascending: Sort ascending vs. descending. Specify list for multiple sort orders.
    If this is a list of bools, must match the length of the by.
    :param inplace: If True, perform operation in-place.
    :param kind: Choice of sorting algorithm. See also ndarray.np.sort for more information.
    mergesort is the only stable algorithm. For DataFrames, this option is only applied
    when sorting on a single column or label.
    :param na_position: Puts NaNs at the beginning if first; last puts NaNs at the end.
    :param ignore_index: If True, the resulting axis will be labeled 0, 1, …, n - 1.
    :param parallel_kind: {'PSRS'}, optional. Parallel sorting algorithm, for the details, refer to:
    http://csweb.cs.wfu.edu/bigiron/LittleFE-PSRS/build/html/PSRSalgorithm.html
    :param psrs_kinds: Sorting algorithms during PSRS algorithm.
    :return: sorted dataframe.

    Examples
    --------
    >>> import mars.dataframe as md
    >>> raw = pd.DataFrame({
    ...     'col1': ['A', 'A', 'B', np.nan, 'D', 'C'],
    ...     'col2': [2, 1, 9, 8, 7, 4],
    ...     'col3': [0, 1, 9, 4, 2, 3],
    ... })
    >>> df = md.DataFrame(raw)
    >>> df.execute()
        col1 col2 col3
    0   A    2    0
    1   A    1    1
    2   B    9    9
    3   NaN  8    4
    4   D    7    2
    5   C    4    3

    Sort by col1

    >>> df.sort_values(by=['col1']).execute()
        col1 col2 col3
    0   A    2    0
    1   A    1    1
    2   B    9    9
    5   C    4    3
    4   D    7    2
    3   NaN  8    4

    Sort by multiple columns

    >>> df.sort_values(by=['col1', 'col2']).execute()
        col1 col2 col3
    1   A    1    1
    0   A    2    0
    2   B    9    9
    5   C    4    3
    4   D    7    2
    3   NaN  8    4

    Sort Descending

    >>> df.sort_values(by='col1', ascending=False).execute()
        col1 col2 col3
    4   D    7    2
    5   C    4    3
    2   B    9    9
    0   A    2    0
    1   A    1    1
    3   NaN  8    4

    """
    if na_position not in ["last", "first"]:  # pragma: no cover
        raise TypeError(f"invalid na_position: {na_position}")
    axis = validate_axis(axis, df)
    if axis != 0:
        raise NotImplementedError("Only support sort on axis 0")
    psrs_kinds = _validate_sort_psrs_kinds(psrs_kinds)
    by = by if isinstance(by, (list, tuple)) else [by]
    op = DataFrameSortValues(
        by=by,
        axis=axis,
        ascending=ascending,
        inplace=inplace,
        kind=kind,
        na_position=na_position,
        ignore_index=ignore_index,
        parallel_kind=parallel_kind,
        psrs_kinds=psrs_kinds,
        output_types=[OutputType.dataframe],
    )
    sorted_df = op(df)
    if inplace:
        df.data = sorted_df.data
    else:
        return sorted_df


# Traceback (ValueError)
In [9]: df = pd.DataFrame({
...:     'col1': np.random.randint(0, 100, (100000,)),
...:     'col2': np.random.choice(['a', 'b', 'c'], (100000,)),
...:     'col3': np.arange(100000)
...: })
...: df.iloc[-100:, :] = pd.NA

In [10]: df.to_csv('test.csv', index=False)

In [11]: md.read_csv('test.csv').execute()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-560f5a720bd9> in <module>
----> 1 md.read_csv('test.csv').execute()

~/Documents/mars_dev/mars/mars/core.py in execute(self, session, **kw)
626
627         if wait:
--> 628             return run()
629         else:
630             thread_executor = ThreadPoolExecutor(1)

~/Documents/mars_dev/mars/mars/core.py in run()
622
623         def run():
--> 624             self.data.execute(session, **kw)
625             return self
626

~/Documents/mars_dev/mars/mars/core.py in execute(self, session, **kw)
373
374         if wait:
--> 375             return run()
376         else:
377             # leverage ThreadPoolExecutor to submit task,

~/Documents/mars_dev/mars/mars/core.py in run()
368         def run():
369             # no more fetch, thus just fire run
--> 370             session.run(self, **kw)
371             # return Tileable or ExecutableTuple itself
372             return self

~/Documents/mars_dev/mars/mars/session.py in run(self, *tileables, **kw)
476         tileables = tuple(mt.tensor(t) if not isinstance(t, (Entity, Base)) else t
477                           for t in tileables)
--> 478         result = self._sess.run(*tileables, **kw)
479
480         for t in tileables:

~/Documents/mars_dev/mars/mars/session.py in run(self, *tileables, **kw)
105             # set number of running cores
106             self.context.set_ncores(kw['n_parallel'])
--> 107             res = self._executor.execute_tileables(tileables, **kw)
108             return res
109

~/Documents/mars_dev/mars/mars/utils.py in _inner(*args, **kwargs)
437         def _inner(*args, **kwargs):
438             with self:
--> 439                 return func(*args, **kwargs)
440
441         return _inner

~/Documents/mars_dev/mars/mars/executor.py in execute_tileables(self, tileables, fetch, n_parallel, n_thread, print_progress, mock, compose, name)
876                                    n_parallel=n_parallel or n_thread,
877                                    print_progress=print_progress, mock=mock,
--> 878                                    chunk_result=chunk_result)
879
880                 # update shape of tileable and its chunks whatever it's successful or not

~/Documents/mars_dev/mars/mars/executor.py in execute_graph(self, graph, keys, n_parallel, print_progress, mock, no_intermediate, compose, retval, chunk_result)
688             print_progress=print_progress, mock=mock, mock_max_memory=self._mock_max_memory,
689             fetch_keys=fetch_keys, no_intermediate=no_intermediate)
--> 690         res = graph_execution.execute(retval)
691         self._mock_max_memory = max(self._mock_max_memory, graph_execution._mock_max_memory)
692         if mock:

~/Documents/mars_dev/mars/mars/executor.py in execute(self, retval)
569         # wait until all the futures completed
570         for future in executed_futures:
--> 571             future.result()
572
573         if retval:

~/miniconda3/envs/py3.7.2/lib/python3.7/concurrent/futures/_base.py in result(self, timeout)
430                 raise CancelledError()
431             elif self._state == FINISHED:
--> 432                 return self.__get_result()
433             else:
434                 raise TimeoutError()

~/miniconda3/envs/py3.7.2/lib/python3.7/concurrent/futures/_base.py in __get_result(self)
382     def __get_result(self):
383         if self._exception:
--> 384             raise self._exception
385         else:
386             return self._result

~/miniconda3/envs/py3.7.2/lib/python3.7/concurrent/futures/thread.py in run(self)
55
56         try:
---> 57             result = self.fn(*self.args, **self.kwargs)
58         except BaseException as exc:
59             self.future.set_exception(exc)

~/Documents/mars_dev/mars/mars/utils.py in _inner(*args, **kwargs)
437         def _inner(*args, **kwargs):
438             with self:
--> 439                 return func(*args, **kwargs)
440
441         return _inner

~/Documents/mars_dev/mars/mars/executor.py in _execute_operand(self, op)
441             # so we pass the first operand's first output to Executor.handle
442             first_op = ops[0]
--> 443             Executor.handle(first_op, results, self._mock)
444
445             # update maximal memory usage during execution

~/Documents/mars_dev/mars/mars/executor.py in handle(cls, op, results, mock)
639                 # The `UFuncTypeError` was introduced by numpy#12593 since v1.17.0.
640                 try:
--> 641                     return runner(results, op)
642                 except UFuncTypeError as e:
643                     raise TypeError(str(e)).with_traceback(sys.exc_info()[2]) from None

~/Documents/mars_dev/mars/mars/dataframe/datasource/read_csv.py in execute(cls, ctx, op)
321                     df = df[op.usecols]
322             else:
--> 323                 df = cls._cudf_read_csv(op) if op.gpu else cls._pandas_read_csv(f, op)
324
325         ctx[out_df.key] = df

~/Documents/mars_dev/mars/mars/dataframe/datasource/read_csv.py in _pandas_read_csv(cls, f, op)
272                 csv_kwargs['keep_default_na'] = False
273             df = pd.read_csv(b, sep=op.sep, names=op.names, index_col=op.index_col, usecols=usecols,
--> 274                              dtype=dtypes.to_dict(), nrows=op.nrows, **csv_kwargs)
275             if op.keep_usecols_order:
276                 df = df[op.usecols]

~/miniconda3/envs/py3.7.2/lib/python3.7/site-packages/pandas/io/parsers.py in parser_f(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, dialect, error_bad_lines, warn_bad_lines, delim_whitespace, low_memory, memory_map, float_precision)
674         )
675
--> 676         return _read(filepath_or_buffer, kwds)
677
678     parser_f.__name__ = name

~/miniconda3/envs/py3.7.2/lib/python3.7/site-packages/pandas/io/parsers.py in _read(filepath_or_buffer, kwds)
452
453     try:
--> 454         data = parser.read(nrows)
455     finally:
456         parser.close()

~/miniconda3/envs/py3.7.2/lib/python3.7/site-packages/pandas/io/parsers.py in read(self, nrows)
1131     def read(self, nrows=None):
1132         nrows = _validate_integer("nrows", nrows)
-> 1133         ret = self._engine.read(nrows)
1134
1135         # May alter columns / col_dict

~/miniconda3/envs/py3.7.2/lib/python3.7/site-packages/pandas/io/parsers.py in read(self, nrows)
2035     def read(self, nrows=None):
2036         try:
-> 2037             data = self._reader.read(nrows)
2038         except StopIteration:
2039             if self._first_chunk:

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader.read()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._read_low_memory()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._read_rows()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._convert_column_data()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._convert_tokens()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._convert_with_dtype()

ValueError: Integer column has NA values in column 0

# Fixed code
def dataframe_sort_values(
    df,
    by,
    axis=0,
    ascending=True,
    inplace=False,
    kind="quicksort",
    na_position="last",
    ignore_index=False,
    parallel_kind="PSRS",
    psrs_kinds=None,
):
    """
    Sort by the values along either axis.

    Parameters
    ----------
    df : Mars DataFrame
         Input dataframe.
    by : str
         Name or list of names to sort by.
    axis : %(axes_single_arg)s, default 0
         Axis to be sorted.
    ascending : bool or list of bool, default True
         Sort ascending vs. descending. Specify list for multiple sort
         orders.  If this is a list of bools, must match the length of
         the by.
    inplace : bool, default False
         If True, perform operation in-place.
    kind : {'quicksort', 'mergesort', 'heapsort'}, default 'quicksort'
         Choice of sorting algorithm. See also ndarray.np.sort for more
         information.  `mergesort` is the only stable algorithm. For
         DataFrames, this option is only applied when sorting on a single
         column or label.
    na_position : {'first', 'last'}, default 'last'
         Puts NaNs at the beginning if `first`; `last` puts NaNs at the
         end.
    ignore_index : bool, default False
         If True, the resulting axis will be labeled 0, 1, …, n - 1.
    parallel_kind : {'PSRS'}, default 'PSRS'
         Parallel sorting algorithm, for the details, refer to:
         http://csweb.cs.wfu.edu/bigiron/LittleFE-PSRS/build/html/PSRSalgorithm.html

    Returns
    -------
    sorted_obj : DataFrame or None
        DataFrame with sorted values if inplace=False, None otherwise.

    Examples
    --------
    >>> import mars.dataframe as md
    >>> df = md.DataFrame({
    ...     'col1': ['A', 'A', 'B', np.nan, 'D', 'C'],
    ...     'col2': [2, 1, 9, 8, 7, 4],
    ...     'col3': [0, 1, 9, 4, 2, 3],
    ... })
    >>> df.execute()
        col1 col2 col3
    0   A    2    0
    1   A    1    1
    2   B    9    9
    3   NaN  8    4
    4   D    7    2
    5   C    4    3

    Sort by col1

    >>> df.sort_values(by=['col1']).execute()
        col1 col2 col3
    0   A    2    0
    1   A    1    1
    2   B    9    9
    5   C    4    3
    4   D    7    2
    3   NaN  8    4

    Sort by multiple columns

    >>> df.sort_values(by=['col1', 'col2']).execute()
        col1 col2 col3
    1   A    1    1
    0   A    2    0
    2   B    9    9
    5   C    4    3
    4   D    7    2
    3   NaN  8    4

    Sort Descending

    >>> df.sort_values(by='col1', ascending=False).execute()
        col1 col2 col3
    4   D    7    2
    5   C    4    3
    2   B    9    9
    0   A    2    0
    1   A    1    1
    3   NaN  8    4

    Putting NAs first

    >>> df.sort_values(by='col1', ascending=False, na_position='first').execute()
        col1 col2 col3
    3   NaN  8    4
    4   D    7    2
    5   C    4    3
    2   B    9    9
    0   A    2    0
    1   A    1    1
    """

    if na_position not in ["last", "first"]:  # pragma: no cover
        raise TypeError(f"invalid na_position: {na_position}")
    axis = validate_axis(axis, df)
    if axis != 0:
        raise NotImplementedError("Only support sort on axis 0")
    psrs_kinds = _validate_sort_psrs_kinds(psrs_kinds)
    by = by if isinstance(by, (list, tuple)) else [by]
    op = DataFrameSortValues(
        by=by,
        axis=axis,
        ascending=ascending,
        inplace=inplace,
        kind=kind,
        na_position=na_position,
        ignore_index=ignore_index,
        parallel_kind=parallel_kind,
        psrs_kinds=psrs_kinds,
        output_types=[OutputType.dataframe],
    )
    sorted_df = op(df)
    if inplace:
        df.data = sorted_df.data
    else:
        return sorted_df