code: def _make_n_folds(
      full_data: Dataset,
      folds: Optional[
          Union[
              Iterable[Tuple[np.ndarray, np.ndarray]],
              _LGBMBaseCrossValidator,
          ]
      ],
      nfold: int,
      params: Dict[str, Any],
      seed: int,
      fpreproc: Optional[_LGBM_PreprocFunction],
      stratified: bool,
      shuffle: bool,
      eval_train_metric: bool,
  ) -> CVBooster:
      """Make a n-fold list of Booster from random indices."""
      full_data = full_data.construct()
      num_data = full_data.num_data()
      if folds is not None:
          if not hasattr(folds, "__iter__") and not hasattr(
              folds, "split"
          ):
              raise AttributeError(
                  "folds should be a generator or iterator of (train_idx, test_idx) tuples "
                  "or scikit-learn splitter object with split method"
              )
          if hasattr(folds, "split"):
              group_info = full_data.get_group()
              if group_info is not None:
                  group_info = np.array(
                      group_info, dtype=np.int32, copy=False
                  )
                  flatted_group = np.repeat(
                      range(len(group_info)), repeats=group_info
                  )
              else:
                  flatted_group = np.zeros(num_data, dtype=np.int32)
              folds = folds.split(
                  X=np.empty(num_data),
                  y=full_data.get_label(),
                  groups=flatted_group,
              )
      else:
          if any(
              params.get(obj_alias, "")
              in {
                  "lambdarank",
                  "rank_xendcg",
                  "xendcg",
                  "xe_ndcg",
                  "xe_ndcg_mart",
                  "xendcg_mart",
              }
              for obj_alias in _ConfigAliases.get("objective")
          ):
              if not SKLEARN_INSTALLED:
                  raise LightGBMError(
                      "scikit-learn is required for ranking cv"
                  )
              # ranking task, split according to groups
              group_info = np.array(
                  full_data.get_group(), dtype=np.int32, copy=False
              )
              flatted_group = np.repeat(
                  range(len(group_info)), repeats=group_info
              )
              group_kfold = _LGBMGroupKFold(n_splits=nfold)
              folds = group_kfold.split(
                  X=np.empty(num_data), groups=flatted_group
              )
          elif stratified:
              if not SKLEARN_INSTALLED:
                  raise LightGBMError(
                      "scikit-learn is required for stratified cv"
                  )
              skf = _LGBMStratifiedKFold(
                  n_splits=nfold, shuffle=shuffle, random_state=seed
              )
              folds = skf.split(
                  X=np.empty(num_data), y=full_data.get_label()
              )
          else:
              if shuffle:
                  randidx = np.random.RandomState(seed).permutation(
                      num_data
                  )
              else:
                  randidx = np.arange(num_data)
              kstep = int(num_data / nfold)
              test_id = [
                  randidx[i : i + kstep]
                  for i in range(0, num_data, kstep)
              ]
              train_id = [
                  np.concatenate(
                      [test_id[i] for i in range(nfold) if k != i]
                  )
                  for k in range(nfold)
              ]
              folds = zip(train_id, test_id)
  
      ret = CVBooster()
      for train_idx, test_idx in folds:
          train_set = full_data.subset(sorted(train_idx))
          valid_set = full_data.subset(sorted(test_idx))
          # run preprocessing on the data set if needed
          if fpreproc is not None:
              train_set, valid_set, tparam = fpreproc(
                  train_set, valid_set, params.copy()
              )
          else:
              tparam = params
          booster_for_fold = Booster(tparam, train_set)
          if eval_train_metric:
              booster_for_fold.add_valid(train_set, "train")
          booster_for_fold.add_valid(valid_set, "valid")
          ret.boosters.append(booster_for_fold)
      return ret
  
imports: import copy
  import json
  from collections import OrderedDict, defaultdict
  from operator import attrgetter
  from pathlib import Path
  from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
  import numpy
  from .None import callback
  from .basic import Booster, Dataset, LightGBMError, _choose_param_value, _ConfigAliases, _InnerPredictor, _LGBM_BoosterEvalMethodResultType, _LGBM_BoosterEvalMethodResultWithStandardDeviationType, _LGBM_CategoricalFeatureConfiguration, _LGBM_CustomObjectiveFunction, _LGBM_EvalFunctionResultType, _LGBM_FeatureNameConfiguration, _log_warning
  from .compat import SKLEARN_INSTALLED, _LGBMBaseCrossValidator, _LGBMGroupKFold, _LGBMStratifiedKFold
label_desc: Use image node_id 2 for calling a global function with example usage: _make_n_folds(full_data, folds, nfold, params, seed, fpreproc, stratified, shuffle, eval_train_metric) and returns: ret