docs: def run_sphinx(options, *option_sets):
      """Helper function to run sphinx with common options.
  
      Pass the names of namespaces to be used in the search path
      for options.  The "sphinx" namespace is automatically added
      to the end of the list, so passing (options, 'html') causes
      the options to be configured with a search path of ('html', 'sphinx').
      This lets the caller invoke sphinx with different sets of
      options for different purposes.
  
      Supported options include:
  
      docroot
        the root under which Sphinx will be working.
        default: docs
      builddir
        directory under the docroot where the resulting files are put.
        default: build
      sourcedir
        directory under the docroot for the source files
        default: (empty string)
      doctrees
        the location of the cached doctrees
        default: $builddir/doctrees
      confdir
        the location of the sphinx conf.py
        default: $sourcedir
      outdir
        the location of the generated output files
        default: $builddir/$builder
      builder
        the name of the sphinx builder to use
        default: html
      force_all
        write all files, not just new and changed
      freshenv
        don't use the saved environment, always read all files
      quiet
        Suppress all output
      template_args
        dictionary of values to be passed as name-value pairs to the HTML builder
        default: {}
      config_args
        dictionary of values to be passed as name-value pairs to configuration
        default: {}
      warnerror
        Flag indicating that Sphinx warnings should be treated as errors.
        Defaults to False.
      """
      if 'sphinx' not in option_sets:
          option_sets += ('sphinx',)
      kwds = dict(add_rest=False)
  
      # Set the search order of the options
      options.order(*option_sets, **kwds)
  
      paths = _get_and_create_paths(options)
      template_args = [
          '-A%s=%s' % (name, value)
          for (name, value) in getattr(options, 'template_args', {}).items()
      ]
      config_args = [
          '-D%s=%s' % (name, value)
          for (name, value) in getattr(options, 'config_args', {}).items()
      ]
      sphinxopts = []
      sphinxopts.extend([
          '-b', options.get('builder', 'html'),
          '-d', paths.doctrees,
          '-c', paths.confdir,
      ])
  
      if options.get('force_all', False):
          sphinxopts.append('-a')
      if options.get('freshenv', False):
          sphinxopts.append('-E')
      if options.get('warnerror', False):
          sphinxopts.append('-W')
      if options.get('quiet', False):
          sphinxopts.append('-Q')
  
      sphinxopts.extend(template_args)
      sphinxopts.extend(config_args)
      sphinxopts.extend([paths.srcdir, paths.outdir])
      rc = sh("sphinx-build {}".format(" ".join(sphinxopts)))
  
      options.order()
      return rc