code: def sort_values(
      df,
      by,
      max_branch=None,
      divisions=None,
      set_divisions=False,
      ignore_index=False,
      ascending=True,
      na_position="last",
      shuffle_method=None,
      sort_function=None,
      sort_function_kwargs=None,
  ):
      """Sort by the given list/tuple of column names."""
  
      if not isinstance(ascending, bool):
          raise ValueError("ascending must be either True or False")
      if na_position not in ("first", "last"):
          raise ValueError(
              "na_position must be either 'first' or 'last'"
          )
  
      npartitions = df.npartitions
      if isinstance(by, tuple):
          by = list(by)
      elif not isinstance(by, list):
          by = [by]
  
      # parse custom sort function / kwargs if provided
      sort_kwargs = {
          "by": by,
          "ascending": ascending,
          "na_position": na_position,
      }
      if sort_function is None:
          sort_function = M.sort_values
      if sort_function_kwargs is not None:
          sort_kwargs.update(sort_function_kwargs)
  
      # handle single partition case
      if npartitions == 1:
          return df.map_partitions(sort_function, **sort_kwargs)
  
      # Step 1 - Calculate new divisions (if necessary)
      if divisions is None:
          divisions = quantile_divisions(df, by, npartitions)
  
      # Step 2 - Perform repartitioning shuffle
      meta = df._meta._constructor_sliced([0])
      if not isinstance(divisions, (gd.Series, gd.DataFrame)):
          dtype = df[by[0]].dtype
          divisions = df._meta._constructor_sliced(
              divisions, dtype=dtype
          )
  
      partitions = df[by].map_partitions(
          _set_partitions_pre,
          divisions=divisions,
          ascending=ascending,
          na_position=na_position,
          meta=meta,
      )
  
      df2 = df.assign(_partitions=partitions)
      df3 = rearrange_by_column(
          df2,
          "_partitions",
          max_branch=max_branch,
          npartitions=len(divisions) - 1,
          shuffle_method=_get_shuffle_method(shuffle_method),
          ignore_index=ignore_index,
      ).drop(columns=["_partitions"])
      df3.divisions = (None,) * (df3.npartitions + 1)
  
      # Step 3 - Return final sorted df
      df4 = df3.map_partitions(sort_function, **sort_kwargs)
      if not isinstance(divisions, gd.DataFrame) and set_divisions:
          # Can't have multi-column divisions elsewhere in dask (yet)
          df4.divisions = tuple(methods.tolist(divisions))
  
      return df4
  
imports: import warnings
  from collections.abc import Iterator
  from functools import wraps
  import cupy
  import numpy
  import tlz
  from dask import config
  from dask.base import tokenize
  from dask.dataframe import methods
  from dask.dataframe.core import DataFrame, Index, Series
  from dask.dataframe.shuffle import rearrange_by_column
  from dask.highlevelgraph import HighLevelGraph
  from dask.utils import M
  import cudf
  from cudf.api.types import is_categorical_dtype
  from cudf.utils.nvtx_annotation import _dask_cudf_nvtx_annotate
label_desc: Use image node_id 8 for calling a global function with example usage: sort_values(df, by, max_branch, divisions, set_divisions, ignore_index, ascending, na_position, shuffle_method, sort_function, sort_function_kwargs) and returns: df4, df