docs: def customize_base_cfg(cfgname, cfgopt_strs, base_cfg, cfgtype,
                         alias_keys=None, valid_keys=None, offset=0,
                         strict=True):
      """
      Args:
          cfgname (str): config name
          cfgopt_strs (str): mini-language defining key variations
          base_cfg (dict): specifies the default cfg to customize
          cfgtype (?):
          alias_keys (None): (default = None)
          valid_keys (None): if base_cfg is not specied, this defines the valid
              keys (default = None)
          offset (int): (default = 0)
          strict (bool): (default = True)
  
      Returns:
          list: cfg_combo - list of config dicts defining customized configs
              based on cfgopt_strs. customized configs always are given an
              _cfgindex, _cfgstr, and _cfgname key.
  
      CommandLine:
          python -m utool.util_gridsearch --test-customize_base_cfg:0
  
  
      Ignore:
          >>> cfgname = 'default'
          >>> cfgopt_strs = 'dsize=1000,per_name=[1,2]'
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_gridsearch import *  # NOQA
          >>> import utool as ut
          >>> cfgname = 'name'
          >>> cfgopt_strs = 'b=[1,2]'
          >>> base_cfg = {}
          >>> alias_keys = None
          >>> cfgtype = None
          >>> offset = 0
          >>> valid_keys = None
          >>> strict = False
          >>> cfg_combo = customize_base_cfg(cfgname, cfgopt_strs, base_cfg, cfgtype,
          >>>                                alias_keys, valid_keys, offset, strict)
          >>> result = ('cfg_combo = %s' % (ut.repr2(cfg_combo, nl=1),))
          >>> print(result)
          cfg_combo = [
              {'_cfgindex': 0, '_cfgname': 'name', '_cfgstr': 'name:b=[1,2]', '_cfgtype': None, 'b': 1},
              {'_cfgindex': 1, '_cfgname': 'name', '_cfgstr': 'name:b=[1,2]', '_cfgtype': None, 'b': 2},
          ]
      """
      import utool as ut
      cfg = base_cfg.copy()
      # Parse config options without expansion
      cfg_options = noexpand_parse_cfgstrs(cfgopt_strs, alias_keys)
      # Ensure that nothing bad is being updated
      if strict:
          parsed_keys = cfg_options.keys()
          if valid_keys is not None:
              ut.assert_all_in(parsed_keys, valid_keys,
                               'keys specified not in valid set')
          else:
              ut.assert_all_in(parsed_keys, cfg.keys(),
                               'keys specified not in default options')
      # Finalize configuration dict
      cfg.update(cfg_options)
      cfg['_cfgtype'] = cfgtype
      cfg['_cfgname'] = cfgname
      # Perform expansion
      cfg_combo = ut.all_dict_combinations(cfg)
      #if len(cfg_combo) > 1:
      for combox, cfg_ in enumerate(cfg_combo, start=offset):
          cfg_['_cfgindex'] = combox
      for cfg_ in cfg_combo:
          if len(cfgopt_strs) > 0:
              cfg_['_cfgstr'] = cfg_['_cfgname'] + NAMEVARSEP + cfgopt_strs
          else:
              cfg_['_cfgstr'] = cfg_['_cfgname']
      return cfg_combo