code: def generate_docstring(
      X="dense",
      X_shape="(n_samples, n_features)",
      y="dense",
      y_shape="(n_samples, 1)",
      convert_dtype_cast=False,
      skip_parameters=[],
      skip_parameters_heading=False,
      prepend_parameters=True,
      parameters=False,
      return_values=False,
  ):
      """
      Decorator to generate dostrings of common functions in the codebase.
      It will auto detect what parameters and default values the function has.
      Unfortunately due to using cython, we cannot (cheaply) do detection of
      return values.
  
      Currently auto detected variables include:
      - X
      - y
      - convert_dtype
      - sample_weights
      - return_sparse
      - sparse_tol
  
      Typical usage scenarios:
  
      Examples
      --------
  
      # for a function that passes all dense parameters, no need to specify
      # anything, and the decorator auto detects the parameters and defaults
  
      @generate_docstring()
      def fit(self, X, y, convert_dtype=True):
  
      # for a function that takes X as dense or sparse
  
      @generate_docstring(X='dense_sparse')
      def fit(self, X, y, sample_weight=None):
  
      # to specify return values
  
      @generate_docstring(return_values={'name': 'preds',
                                         'type': 'dense',
                                         'description': 'Predicted values',
                                         'shape': '(n_samples, 1)'})
  
  
      Parameters
      -----------
      X : str (default = 'dense')
          Data type of variable X. Currently accepted types are: dense,
          dense_anydtype, dense_intdtype, sparse, dense_sparse
      X_shape : str (default = '(n_samples, n_features)')
          Shape of variable X
      y : str (default = 'dense')
          Data type of variable y. Currently accepted types are: dense,
          dense_anydtype, dense_intdtype, sparse, dense_sparse
      y_shape : str (default = '(n_samples, 1)')
          Shape of variable y
      convert_dtype_cast : Boolean or str (default = False)
          If not false, use it to specify when convert_dtype is used to convert
          to a single specific dtype (as opposed to converting the dtype of one
          variable to the dtype of another for example). Example of this is how
          NearestNeighbors and UMAP use convert_dtype to convert inputs to
          np.float32.
      skip_parameters : list of str (default = [])
          Use if you want the decorator to skip generating a docstring entry
          for a specific parameter
      skip_parameters_heading : boolean (default = False)
          Set to True to not generate the Parameters section heading
      prepend_parameters : boolean (default = True)
          Use when setting skip_parameters_heading to True, so that the
          parameters inserted by the decorator are inserted before the
          parameters you already have in your docstring.
      return_values : dict or list of dicts (default = False)
          Use to generate docstrings of return values. One dictionary per
          return value, this is the format:
              {'name': 'name_of_variable',
               'type': 'data type of returned value',
               'description': 'Description of variable',
               'shape': 'shape of returned variable'}
  
          If type is one of dense or dense_sparse then the type is generated
          from the corresponding entry in _return_values_docstrings. Otherwise
          the type is used as specified.
      """
  
      def deco(func):
          params = signature(func).parameters
          if func.__doc__ is None:
              func.__doc__ = ""
          # Add parameter section header if needed, can be skipped
          if (
              "X" in params or "y" in params or parameters
          ) and not skip_parameters_heading:
              func.__doc__ += "\nParameters\n----------\n"
  
          # Check if we want to prepend the parameters
          if skip_parameters_heading and prepend_parameters:
              loc_pars = func.__doc__.find("----------") + 11
              current_params_in_docstring = func.__doc__[loc_pars:]
  
              func.__doc__ = func.__doc__[:loc_pars]
  
          # Process each parameter
          for par, value in params.items():
              if par == "self":
                  pass
  
              # X and y are the most common
              elif par == "X" and par not in skip_parameters:
                  func.__doc__ += _parameters_docstrings[X].format(
                      name=par, shape=X_shape
                  )
              elif par == "y" and par not in skip_parameters:
                  func.__doc__ += _parameters_docstrings[y].format(
                      name=par, shape=y_shape
                  )
  
              # convert_dtype requires some magic to distinguish
              # whether we use the fit version or the version
              # for the other methods.
              elif (
                  par == "convert_dtype" and par not in skip_parameters
              ):
                  if not convert_dtype_cast:
                      if func.__name__ == "fit":
                          k = "convert_dtype_fit"
                      else:
                          k = "convert_dtype_other"
  
                      func.__doc__ += _parameters_docstrings[k].format(
                          default=params["convert_dtype"].default,
                          func_name=func.__name__,
                      )
  
                  else:
                      func.__doc__ += _parameters_docstrings[
                          "convert_dtype_single"
                      ].format(
                          default=params["convert_dtype"].default,
                          dtype=convert_dtype_cast,
                      )
  
              # All other parameters only take a default (for now).
              else:
                  if par in _simple_params:
                      func.__doc__ += _parameters_docstrings[
                          par
                      ].format(default=params[par].default)
              func.__doc__ += "\n\n"
  
          if skip_parameters_heading and prepend_parameters:
              # indexing at 8 to match indentation of inserted parameters
              # this can be replaced with indentation detection
              # https://github.com/rapidsai/cuml/issues/2714
              func.__doc__ += current_params_in_docstring[8:]
  
          # Add return section header if needed, no option to skip currently.
          if return_values:
              func.__doc__ += "\nReturns\n-------\n"
  
              # convenience call to allow users to pass a single return
              # value as a dictionary instead of a list of dictionaries
              rets = (
                  [return_values]
                  if not isinstance(return_values, list)
                  else return_values
              )
  
              # process each entry in the return_values
              # auto naming of predicted variable names will be a
              # future improvement
              for ret in rets:
                  if ret["type"] in _return_values_docstrings:
                      key = ret["type"]
                      # non custom types don't take the type parameter
                      del ret["type"]
                  else:
                      key = "custom_type"
  
                  # ret is already a dictionary, we just use it for the named
                  # parameters
                  func.__doc__ += _return_values_docstrings[key].format(
                      **ret
                  )
                  func.__doc__ += "\n\n"
  
          return func
  
      return deco
  
label_desc: Use image node_id 1 for calling a global function with example usage: generate_docstring(X, X_shape, y, y_shape, convert_dtype_cast, skip_parameters, skip_parameters_heading, prepend_parameters, parameters, return_values) and returns: deco, func