docs: def make_constrained_cfg_and_lbl_list(varied_dict, constraint_func=None,
                                        slice_dict=None,
                                        defaultslice=slice(0, 1)):
      r"""
      Args:
          varied_dict (dict):  parameters to vary with possible variations
          constraint_func (func): function to restirct parameter variations
          slice_dict (dict):  dict of slices for each param of valid possible values
          defaultslice (slice): default slice used if slice is not specified in slice_dict
  
      Returns:
          tuple: (cfgdict_list, cfglbl_list)
  
      CommandLine:
          python -m utool.util_gridsearch --test-make_constrained_cfg_and_lbl_list
  
      Example:
          >>> # DISABLE_DOCTEST
          >>> from utool.util_gridsearch import *  # NOQA
          >>> # build test data
          >>> varied_dict = {
          ...     'p': [.1, .3, 1.0, 2.0],
          ...     'dcvs_clip_max': [.1, .2, .5],
          ...     'K': [3, 5],
          ... }
          >>> constraint_func = None
          >>> # execute function
          >>> (cfgdict_list, cfglbl_list) = make_constrained_cfg_and_lbl_list(varied_dict, constraint_func)
          >>> # verify results
          >>> result = six.text_type((cfgdict_list, cfglbl_list))
          >>> print(result)
      """
      # Restrict via slices
      if slice_dict is None:
          varied_dict_ = varied_dict
      else:
          varied_dict_ = {
              key: val[slice_dict.get(key, defaultslice)]
              for key, val in six.iteritems(varied_dict)
          }
      # Enumerate all combinations
      cfgdict_list_ = util_dict.all_dict_combinations(varied_dict_)
      if constraint_func is not None:
          # Remove invalid combinations
          cfgdict_list = constrain_cfgdict_list(cfgdict_list_, constraint_func)
      else:
          cfgdict_list = cfgdict_list_
      # Get labels and return
      cfglbl_list = make_cfglbls(cfgdict_list, varied_dict)
      return cfgdict_list, cfglbl_list