code: def benchmark_with_object(
      cls, *, dtype="int", nulls=None, cols=None, rows=None
  ):
      """Pass "standard" cudf fixtures to functions without renaming parameters.
  
      The fixture generation logic in conftest.py provides a plethora of useful
      fixtures to allow developers to easily select an appropriate cross-section
      of the space of objects to apply a particular benchmark to. However, the
      usage of these fixtures is cumbersome because creating them in a principled
      fashion results in long names and very specific naming schemes. This
      decorator abstracts that naming logic away from the developer, allowing
      them to instead focus on defining the fixture semantically by describing
      its properties.
  
      Parameters
      ----------
      cls : Union[str, Type]
          The class of object to test. May either be specified as the type
          itself, or using the name (as a string). If a string, the case is
          irrelevant as the string will be converted to all lowercase.
      dtype : Union[str, Iterable[str]], default 'int'
          The dtype or set of dtypes to use.
      nulls : Optional[bool], default None
          Whether to test nullable or non-nullable data. If None, both nullable
          and non-nullable data are included.
      cols : Optional[int], None
          The number of columns. Only valid if cls == 'dataframe'. If None, use
          all possible numbers of columns. Specifying multiple values is
          unsupported.
      rows : Optional[int], None
          The number of rows. If None, use all possible numbers of rows.
          Specifying multiple values is unsupported.
  
      Raises
      ------
      AssertionError
          If any of the parameters do not correspond to extant fixtures.
  
      Examples
      --------
      # Note: As an internal function, this example is not meant for doctesting.
  
      @benchmark_with_object("dataframe", dtype="int", nulls=False)
      def bench_columns(benchmark, df):
          benchmark(df.columns)
      """
      if inspect.isclass(cls):
          cls = cls.__name__
      cls = cls.lower()
  
      supported_classes = (
          "column",
          "series",
          "index",
          "dataframe",
          "indexedframe",
          "frame_or_index",
      )
      assert cls in supported_classes, (
          f"cls {cls} is invalid, choose from "
          f"{', '.join(supported_classes)}"
      )
  
      if not isinstance(dtype, list):
          dtype = [dtype]
      assert all(dt in column_generators for dt in dtype), (
          f"The only supported dtypes are "
          f"{', '.join(column_generators)}"
      )
  
      dtype_str = "_dtype_" + "_or_".join(dtype)
  
      null_str = ""
      if nulls is not None:
          null_str = f"_nulls_{nulls}".lower()
  
      col_str = ""
      if cols is not None:
          assert cols in NUM_COLS, (
              f"You have requested a DataFrame with {cols} columns but fixtures "
              f"only exist for the values {', '.join(NUM_COLS)}"
          )
          col_str = f"_cols_{cols}"
  
      row_str = ""
      if rows is not None:
          assert rows in NUM_ROWS, (
              f"You have requested a {cls} with {rows} rows but fixtures "
              f"only exist for the values {', '.join(NUM_ROWS)}"
          )
          row_str = f"_rows_{rows}"
  
      fixture_name = f"{cls}{dtype_str}{null_str}{col_str}{row_str}"
  
      def deco(bm):
          # pytest's test collection process relies on parsing the globals dict
          # to find test functions and identify their parameters for the purpose
          # of fixtures and parameters. Therefore, the primary purpose of this
          # decorator is to define a new benchmark function with a signature
          # identical to that of the decorated benchmark except with the user's
          # fixture name replaced by the true fixture name based on the arguments
          # to benchmark_with_object.
          parameters = inspect.signature(bm).parameters
  
          # Note: This logic assumes that any benchmark using this fixture has at
          # least two parameters since they must be using both the
          # pytest-benchmark `benchmark` fixture and the cudf object.
          params_str = ", ".join(f"{p}" for p in parameters if p != cls)
          arg_str = ", ".join(
              f"{p}={p}" for p in parameters if p != cls
          )
  
          if params_str:
              params_str += ", "
          if arg_str:
              arg_str += ", "
  
          params_str += f"{fixture_name}"
          arg_str += f"{cls}={fixture_name}"
  
          src = textwrap.dedent(
              f"""
              import makefun
              @makefun.wraps(
                  bm,
                  remove_args=("{cls}",),
                  prepend_args=("{fixture_name}",)
              )
              def wrapped_bm({params_str}):
                  return bm({arg_str})
              """
          )
          globals_ = {"bm": bm}
          exec(src, globals_)
          wrapped_bm = globals_["wrapped_bm"]
          # In case marks were applied to the original benchmark, copy them over.
          if marks := getattr(bm, "pytestmark", None):
              wrapped_bm.pytestmark = marks
          wrapped_bm.place_as = bm
          return wrapped_bm
  
      return deco
  
imports: import inspect
  import re
  import textwrap
  from collections.abc import MutableSet
  from itertools import groupby
  from numbers import Real
  import pytest_cases
  from config import NUM_COLS, NUM_ROWS, cudf, cupy
label_desc: Use image node_id 3 for calling a global function with example usage: benchmark_with_object(cls) and returns: deco, wrapped_bm