docs: def spellcheck(config_file, names=None, groups=None, binary='', checker='', sources=None, verbose=0, debug=False):
      """Spell check."""
  
      hunspell = None
      aspell = None
      spellchecker = None
      config = util.read_config(config_file)
      if sources is None:
          sources = []
  
      matrix = config.get('matrix', [])
      preferred_checker = config.get('spellchecker', 'aspell')
      if not matrix:
          matrix = config.get('documents', [])
          if matrix:
              util.warn_deprecated("'documents' key in config is deprecated. 'matrix' should be used going forward.")
  
      groups = set() if groups is None else set(groups)
      names = set() if names is None else set(names)
  
      # Sources are only recognized when requesting a single name.
      if (len(names) != 1 and len(sources)):
          sources = []
  
      for task in iter_tasks(matrix, names, groups):
  
          if not checker:
              checker = preferred_checker
  
          if checker == "hunspell":  # pragma: no cover
              if hunspell is None:
                  hunspell = Hunspell(config, binary, verbose, debug)
              spellchecker = hunspell
  
          elif checker == "aspell":
              if aspell is None:
                  aspell = Aspell(config, binary, verbose, debug)
              spellchecker = aspell
          else:
              raise ValueError('%s is not a valid spellchecker!' % checker)
  
          spellchecker.log('Using %s to spellcheck %s' % (checker, task.get('name', '')), 1)
          for result in spellchecker.run_task(task, source_patterns=sources):
              spellchecker.log('Context: %s' % result.context, 2)
              yield result
          spellchecker.log("", 1)