code: def df_coercion(  # noqa: C901
      df: DataframeLike,
      engine: Engine,
      npartitions: Optional[int] = None,
      chunksize: Optional[int] = None,
      debug: bool = False,
  ) -> DataframeLike:
      """
      Go from df to engine of choice
  
      Supported coercions:
          pd <- pd
          cudf <- pd, cudf
          ddf <- pd, ddf
          dgdf <- pd, cudf, dgdf
      """
      logger.debug("@df_coercion %s -> %s", type(df), engine)
      if engine == Engine.PANDAS:
          if isinstance(df, pd.DataFrame):
              return df
          raise ValueError(
              "pandas engine mode requires pd.DataFrame input, received: %s"
              % str(type(df))
          )
  
      if engine == Engine.CUDF:
          import cudf
  
          if isinstance(df, pd.DataFrame):
              try:
                  return cudf.from_pandas(df)
              except:
                  failed_cols = []
                  out_gdf = cudf.from_pandas(df[[]])
                  for c in df.columns:
                      try:
                          out_gdf[c] = cudf.from_pandas(df[c])
                      except:
                          failed_cols.append(c)
                          out_gdf[c] = cudf.from_pandas(
                              df[c].astype(str)
                          )
                  logger.warning(
                      "CPU->GPU coercion failures on columns, converted their individual values to strings: %s",
                      ", ".join(
                          [
                              f"[{c} :: {df[c].dtype.name}]"
                              for c in failed_cols
                          ]
                      ),
                  )
                  return out_gdf
  
          if isinstance(df, cudf.DataFrame):
              return df
          raise ValueError(
              "cudf engine mode requires pd.DataFrame/cudf.DataFrame input, received: %s"
              % str(type(df))
          )
  
      if engine == Engine.DASK:
          import dask.dataframe
  
          if isinstance(df, pd.DataFrame):
              out = dask.dataframe.from_pandas(
                  df,
                  **{  # type: ignore[call-overload]
                      **(
                          {"npartitions": npartitions}
                          if npartitions is not None
                          else {}
                      ),
                      **(
                          {"chunksize": chunksize}
                          if chunksize is not None
                          else {}
                      ),
                  },
              )
              if debug:
                  out = out.persist()
                  logger.debug("pdf -> ddf: %s", out.compute())
              return out
          if isinstance(df, dask.dataframe.DataFrame):
              return df
          raise ValueError(
              "dask engine mode requires pd.DataFrame/dask.dataframe.DataFrame input, received: %s"
              % str(type(df))
          )
      if engine == Engine.DASK_CUDF:
          import cudf, dask_cudf, dask.dataframe
  
          if isinstance(df, pd.DataFrame):
              gdf = df_coercion(df, Engine.CUDF)
              return df_coercion(
                  gdf,
                  Engine.DASK_CUDF,
                  npartitions=npartitions,
                  chunksize=chunksize,
              )
          if isinstance(df, cudf.DataFrame):
              return dask_cudf.from_cudf(
                  df, npartitions=npartitions, chunksize=chunksize
              )
          if isinstance(df, dask_cudf.DataFrame):
              return df
          if isinstance(df, dask.dataframe.DataFrame):
              return df.map_partitions(
                  cudf.from_pandas
              )  # FIXME How does this get the right type?
          raise ValueError(
              "dask_cudf engine mode requires pd.DataFrame/cudf.DataFrame/dask.dataframe.DataFrame/dask_cudf.DataFrame input, received: %s"
              % str(type(df))
          )
  
      return ValueError("Did not get a value Engine type: %s" % engine)
  
imports: from typing import TYPE_CHECKING, Any, Dict, List, Optional
  from .Engine import Engine, DataframeLike, DataframeLocalLike
  import numpy, pandas, pyarrow, sys
  from .util import setup_logger
label_desc: Use image node_id 20 for calling a global function with example usage: df_coercion(df, engine, npartitions, chunksize, debug) and returns: ValueError, df, df, out, df, df_coercion, dask_cudf, df, df, cudf, out_gdf