Esempio n. 1
0
def sphinx_env(app_env: SphinxAppEnv):
    """This context enters the standard sphinx contexts,
    then registers the roles, directives and nodes saved in the app_env.

    The standard sphinx contexts:

    - Patch docutils.languages.get_language(), to suppress reporter warnings
    - Temporarily sets `os.environ['DOCUTILSCONFIG']` to the sphinx confdir
    - Saves copies of roles._roles and directives._directives & resets them on exit
    - Un-registers additional nodes (set via `register_node`) on exit
      (by deleting `GenericNodeVisitor` visit/depart methods)
    - Patches roles.roles and directives.directives functions to also look in domains
    """
    with patch_docutils(
            app_env.app.confdir), docutils_namespace(), sphinx_domains(
                app_env.app.env):
        from docutils.parsers.rst import directives, roles
        from sphinx.util.docutils import register_node

        if app_env.roles:
            roles._roles.update(app_env.roles)
        if app_env.directives:
            directives._directives.update(app_env.directives)
        for node in app_env.additional_nodes:
            register_node(node)
        # TODO how to make `unregister_node` thread safe

        yield
Esempio n. 2
0
def test_html_with_docutilsconf(app, status, warning):
    with patch_docutils(app.confdir):
        app.build()

    doctree = app.env.get_doctree('index')
    assert_node(doctree[0][1], [nodes.paragraph, ("Sphinx",
                                                  [nodes.footnote_reference, "1"])])
Esempio n. 3
0
def render_sphinx(content):
    with tempfile.TemporaryDirectory() as tmp_dir:
        src_path = pathlib.Path(tmp_dir, "src/contents.rst")
        src_path.parent.mkdir()
        with src_path.open("w") as src:
            src.write(content)

        build_path = pathlib.Path(tmp_dir, "build/contents.fjson")

        source_dir = str(src_path.parent)
        doctree_dir = os.path.join(source_dir, ".doctrees")
        confoverrides = {
            "extensions": ["zuul_sphinx"],
            "master_doc": "contents"
        }
        status_log = io.StringIO()

        # NOTE (fschmidt): This part needs to be in sync with the used version
        # of Sphinx. Current version is:
        # https://github.com/sphinx-doc/sphinx/blob/v1.8.1/sphinx/cmd/build.py#L299
        with patch_docutils(source_dir), docutils_namespace():
            # Remove the color from the Sphinx' console output. Otherwise
            # the lines cannot be parsed properly as some \n are not set properly.
            nocolor()
            app = Sphinx(
                srcdir=source_dir,
                confdir=None,
                outdir=str(build_path.parent),
                doctreedir=doctree_dir,
                buildername="json",
                confoverrides=confoverrides,
                status=status_log,
                warning=sys.stderr,
            )

            # Add the mocked SupportedOS directive to get the os information
            # without rendering it into the resulting HTML page
            app.add_directive("supported_os", SupportedOS)

            # Start the Sphinx build
            app.build(force_all=True, filenames=[])

            if app.statuscode:
                raise SphinxBuildError

        # Extract the platforms from the logger output
        platforms = []
        status_log.seek(0)
        for line in status_log.readlines():
            prefix, _, platform = line.partition(":")
            if prefix == SUPPORTED_OS_LOG_PREFIX:
                platforms.append(platform.strip().lower())

        with build_path.open() as build:
            html_parts = json.load(build)

    return {"html": html_parts["body"], "platforms": platforms}
Esempio n. 4
0
    def run(self) -> None:
        warnings.warn('setup.py build_sphinx is deprecated.',
                      RemovedInSphinx70Warning,
                      stacklevel=2)

        if not color_terminal():
            nocolor()
        if not self.verbose:  # type: ignore
            status_stream = StringIO()
        else:
            status_stream = sys.stdout  # type: ignore
        confoverrides: Dict[str, Any] = {}
        if self.project:
            confoverrides['project'] = self.project
        if self.version:
            confoverrides['version'] = self.version
        if self.release:
            confoverrides['release'] = self.release
        if self.today:
            confoverrides['today'] = self.today
        if self.copyright:
            confoverrides['copyright'] = self.copyright
        if self.nitpicky:
            confoverrides['nitpicky'] = self.nitpicky

        for builder, builder_target_dir in self.builder_target_dirs:
            app = None

            try:
                confdir = self.config_dir or self.source_dir
                with patch_docutils(confdir), docutils_namespace():
                    app = Sphinx(self.source_dir,
                                 self.config_dir,
                                 builder_target_dir,
                                 self.doctree_dir,
                                 builder,
                                 confoverrides,
                                 status_stream,
                                 freshenv=self.fresh_env,
                                 warningiserror=self.warning_is_error,
                                 verbosity=self.verbosity,
                                 keep_going=self.keep_going)
                    app.build(force_all=self.all_files)
                    if app.statuscode:
                        raise DistutilsExecError('caused by %s builder.' %
                                                 app.builder.name)
            except Exception as exc:
                handle_exception(app, self, exc, sys.stderr)
                if not self.pdb:
                    raise SystemExit(1) from exc

            if not self.link_index:
                continue

            src = app.config.root_doc + app.builder.out_suffix  # type: ignore
            dst = app.builder.get_outfilename('index')  # type: ignore
            os.symlink(src, dst)
Esempio n. 5
0
def test_html_with_docutilsconf(app, status, warning):
    with patch_docutils(app.confdir):
        app.builder.build(['contents'])

    result = (app.outdir / 'index.html').text(encoding='utf-8')

    assert regex_count(r'<th class="field-name">', result) == 0
    assert regex_count(r'<th class="field-name" colspan="2">', result) == 2
    assert regex_count(r'<td class="option-group">', result) == 0
    assert regex_count(r'<td class="option-group" colspan="2">', result) == 2
Esempio n. 6
0
def test_html_with_docutilsconf(app, status, warning):
    with patch_docutils(app.confdir):
        app.builder.build(['contents'])

    result = (app.outdir / 'contents.html').text(encoding='utf-8')

    assert regex_count(r'<th class="field-name">', result) == 0
    assert regex_count(r'<th class="field-name" colspan="2">', result) == 2
    assert regex_count(r'<td class="option-group">', result) == 0
    assert regex_count(r'<td class="option-group" colspan="2">', result) == 2
Esempio n. 7
0
def test_docutils_source_link_with_nonascii_file(app, status, warning):
    srcdir = path(app.srcdir)
    mb_name = u'\u65e5\u672c\u8a9e'
    try:
        (srcdir / (mb_name + '.txt')).write_text('')
    except UnicodeEncodeError:
        from sphinx.testing.path import FILESYSTEMENCODING
        raise pytest.skip.Exception(
            'nonascii filename not supported on this filesystem encoding: '
            '%s', FILESYSTEMENCODING)

    with patch_docutils(app.confdir):
        app.builder.build_all()
Esempio n. 8
0
def test_docutils_source_link_with_nonascii_file(app, status, warning):
    srcdir = path(app.srcdir)
    mb_name = '\u65e5\u672c\u8a9e'
    try:
        (srcdir / (mb_name + '.txt')).write_text('')
    except UnicodeEncodeError:
        from sphinx.testing.path import FILESYSTEMENCODING
        raise pytest.skip.Exception(
            'nonascii filename not supported on this filesystem encoding: '
            '%s', FILESYSTEMENCODING)

    with patch_docutils(app.confdir):
        app.builder.build_all()
Esempio n. 9
0
    def run(self):
        # type: () -> None
        if not color_terminal():
            nocolor()
        if not self.verbose:  # type: ignore
            status_stream = StringIO()
        else:
            status_stream = sys.stdout  # type: ignore
        confoverrides = {}
        if self.project:
            confoverrides['project'] = self.project
        if self.version:
            confoverrides['version'] = self.version
        if self.release:
            confoverrides['release'] = self.release
        if self.today:
            confoverrides['today'] = self.today
        if self.copyright:
            confoverrides['copyright'] = self.copyright

        for builder, builder_target_dir in self.builder_target_dirs:
            app = None

            try:
                confdir = self.config_dir or self.source_dir
                with patch_docutils(confdir), docutils_namespace():
                    app = Sphinx(self.source_dir,
                                 self.config_dir,
                                 builder_target_dir,
                                 self.doctree_dir,
                                 builder,
                                 confoverrides,
                                 status_stream,
                                 freshenv=self.fresh_env,
                                 warningiserror=self.warning_is_error)
                    app.build(force_all=self.all_files)
                    if app.statuscode:
                        raise DistutilsExecError('caused by %s builder.' %
                                                 app.builder.name)
            except Exception as exc:
                handle_exception(app, self, exc, sys.stderr)
                if not self.pdb:
                    raise SystemExit(1)

            if not self.link_index:
                continue

            src = app.config.master_doc + app.builder.out_suffix  # type: ignore
            dst = app.builder.get_outfilename('index')  # type: ignore
            os.symlink(src, dst)
Esempio n. 10
0
    def run(self):
        # type: () -> None
        if not color_terminal():
            nocolor()
        if not self.verbose:  # type: ignore
            status_stream = StringIO()
        else:
            status_stream = sys.stdout  # type: ignore
        confoverrides = {}  # type: Dict[str, Any]
        if self.project:
            confoverrides['project'] = self.project
        if self.version:
            confoverrides['version'] = self.version
        if self.release:
            confoverrides['release'] = self.release
        if self.today:
            confoverrides['today'] = self.today
        if self.copyright:
            confoverrides['copyright'] = self.copyright
        if self.nitpicky:
            confoverrides['nitpicky'] = self.nitpicky

        for builder, builder_target_dir in self.builder_target_dirs:
            app = None

            try:
                confdir = self.config_dir or self.source_dir
                with patch_docutils(confdir), docutils_namespace():
                    app = Sphinx(self.source_dir, self.config_dir,
                                 builder_target_dir, self.doctree_dir,
                                 builder, confoverrides, status_stream,
                                 freshenv=self.fresh_env,
                                 warningiserror=self.warning_is_error)
                    app.build(force_all=self.all_files)
                    if app.statuscode:
                        raise DistutilsExecError(
                            'caused by %s builder.' % app.builder.name)
            except Exception as exc:
                handle_exception(app, self, exc, sys.stderr)
                if not self.pdb:
                    raise SystemExit(1)

            if not self.link_index:
                continue

            src = app.config.master_doc + app.builder.out_suffix  # type: ignore
            dst = app.builder.get_outfilename('index')  # type: ignore
            os.symlink(src, dst)
Esempio n. 11
0
def test_man(app, status, warning):
    with patch_docutils(app.confdir):
        app.builder.build(['contents'])
    assert warning.getvalue() == ''
Esempio n. 12
0
def test_texinfo(app, status, warning):
    with patch_docutils(app.confdir):
        app.builder.build(['contents'])
Esempio n. 13
0
def build_main(argv=sys.argv[1:]):
    # type: (List[str]) -> int
    """Sphinx build "main" command-line entry."""

    parser = get_parser()
    args = parser.parse_args(argv)

    if args.noconfig:
        args.confdir = None
    elif not args.confdir:
        args.confdir = args.sourcedir

    if not args.doctreedir:
        args.doctreedir = os.path.join(args.outputdir, '.doctrees')

    # handle remaining filename arguments
    filenames = args.filenames
    missing_files = []
    for filename in filenames:
        if not os.path.isfile(filename):
            missing_files.append(filename)
    if missing_files:
        parser.error(__('cannot find files %r') % missing_files)

    if args.force_all and filenames:
        parser.error(__('cannot combine -a option and filenames'))

    if args.color == 'no' or (args.color == 'auto' and not color_terminal()):
        nocolor()

    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr

    if args.quiet:
        status = None

    if args.really_quiet:
        status = warning = None

    if warning and args.warnfile:
        try:
            warnfp = open(args.warnfile, 'w')
        except Exception as exc:
            parser.error(__('cannot open warning file %r: %s') % (
                args.warnfile, exc))
        warning = Tee(warning, warnfp)  # type: ignore
        error = warning

    confoverrides = {}
    for val in args.define:
        try:
            key, val = val.split('=', 1)
        except ValueError:
            parser.error(__('-D option argument must be in the form name=value'))
        confoverrides[key] = val

    for val in args.htmldefine:
        try:
            key, val = val.split('=')
        except ValueError:
            parser.error(__('-A option argument must be in the form name=value'))
        try:
            val = int(val)
        except ValueError:
            pass
        confoverrides['html_context.%s' % key] = val

    if args.nitpicky:
        confoverrides['nitpicky'] = True

    app = None
    try:
        confdir = args.confdir or args.sourcedir
        with patch_docutils(confdir), docutils_namespace():
            app = Sphinx(args.sourcedir, args.confdir, args.outputdir,
                         args.doctreedir, args.builder, confoverrides, status,
                         warning, args.freshenv, args.warningiserror,
                         args.tags, args.verbosity, args.jobs, args.keep_going)
            app.build(args.force_all, filenames)
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, args, exc, error)
        return 2
Esempio n. 14
0
def main(argv):
    # type: (List[unicode]) -> int
    parser = optparse.OptionParser(USAGE,
                                   epilog=EPILOG,
                                   formatter=MyFormatter())
    parser.add_option('--version',
                      action='store_true',
                      dest='version',
                      help='show version information and exit')

    group = parser.add_option_group('General options')
    group.add_option('-b',
                     metavar='BUILDER',
                     dest='builder',
                     default='html',
                     help='builder to use; default is html')
    group.add_option('-a',
                     action='store_true',
                     dest='force_all',
                     help='write all files; default is to only write new and '
                     'changed files')
    group.add_option('-E',
                     action='store_true',
                     dest='freshenv',
                     help='don\'t use a saved environment, always read '
                     'all files')
    group.add_option('-d',
                     metavar='PATH',
                     default=None,
                     dest='doctreedir',
                     help='path for the cached environment and doctree files '
                     '(default: outdir/.doctrees)')
    group.add_option('-j',
                     metavar='N',
                     default=1,
                     type='int',
                     dest='jobs',
                     help='build in parallel with N processes where possible')
    # this option never gets through to this point (it is intercepted earlier)
    # group.add_option('-M', metavar='BUILDER', dest='make_mode',
    #                 help='"make" mode -- as used by Makefile, like '
    #                 '"sphinx-build -M html"')

    group = parser.add_option_group('Build configuration options')
    group.add_option('-c',
                     metavar='PATH',
                     dest='confdir',
                     help='path where configuration file (conf.py) is located '
                     '(default: same as sourcedir)')
    group.add_option('-C',
                     action='store_true',
                     dest='noconfig',
                     help='use no config file at all, only -D options')
    group.add_option('-D',
                     metavar='setting=value',
                     action='append',
                     dest='define',
                     default=[],
                     help='override a setting in configuration file')
    group.add_option('-A',
                     metavar='name=value',
                     action='append',
                     dest='htmldefine',
                     default=[],
                     help='pass a value into HTML templates')
    group.add_option('-t',
                     metavar='TAG',
                     action='append',
                     dest='tags',
                     default=[],
                     help='define tag: include "only" blocks with TAG')
    group.add_option('-n',
                     action='store_true',
                     dest='nitpicky',
                     help='nit-picky mode, warn about all missing references')

    group = parser.add_option_group('Console output options')
    group.add_option('-v',
                     action='count',
                     dest='verbosity',
                     default=0,
                     help='increase verbosity (can be repeated)')
    group.add_option('-q',
                     action='store_true',
                     dest='quiet',
                     help='no output on stdout, just warnings on stderr')
    group.add_option('-Q',
                     action='store_true',
                     dest='really_quiet',
                     help='no output at all, not even warnings')
    group.add_option('--color',
                     dest='color',
                     action='store_const',
                     const='yes',
                     default='auto',
                     help='Do emit colored output (default: auto-detect)')
    group.add_option('-N',
                     '--no-color',
                     dest='color',
                     action='store_const',
                     const='no',
                     help='Do not emit colored output (default: auto-detect)')
    group.add_option('-w',
                     metavar='FILE',
                     dest='warnfile',
                     help='write warnings (and errors) to given file')
    group.add_option('-W',
                     action='store_true',
                     dest='warningiserror',
                     help='turn warnings into errors')
    group.add_option('-T',
                     action='store_true',
                     dest='traceback',
                     help='show full traceback on exception')
    group.add_option('-P',
                     action='store_true',
                     dest='pdb',
                     help='run Pdb on exception')

    # parse options
    try:
        opts, args = parser.parse_args(list(argv[1:]))
    except SystemExit as err:
        return err.code

    # handle basic options
    if opts.version:
        print('Sphinx (sphinx-build) %s' % __display_version__)
        return 0

    # get paths (first and second positional argument)
    try:
        srcdir = abspath(args[0])
        confdir = abspath(opts.confdir or srcdir)
        if opts.noconfig:
            confdir = None
        if not path.isdir(srcdir):
            print('Error: Cannot find source directory `%s\'.' % srcdir,
                  file=sys.stderr)
            return 1
        if not opts.noconfig and not path.isfile(path.join(confdir,
                                                           'conf.py')):
            print('Error: Config directory doesn\'t contain a conf.py file.',
                  file=sys.stderr)
            return 1
        outdir = abspath(args[1])
        if srcdir == outdir:
            print(
                'Error: source directory and destination directory are same.',
                file=sys.stderr)
            return 1
    except IndexError:
        parser.print_help()
        return 1
    except UnicodeError:
        print('Error: Multibyte filename not supported on this filesystem '
              'encoding (%r).' % fs_encoding,
              file=sys.stderr)
        return 1

    # handle remaining filename arguments
    filenames = args[2:]
    errored = False
    for filename in filenames:
        if not path.isfile(filename):
            print('Error: Cannot find file %r.' % filename, file=sys.stderr)
            errored = True
    if errored:
        return 1

    # likely encoding used for command-line arguments
    try:
        locale = __import__('locale')  # due to submodule of the same name
        likely_encoding = locale.getpreferredencoding()
    except Exception:
        likely_encoding = None

    if opts.force_all and filenames:
        print('Error: Cannot combine -a option and filenames.',
              file=sys.stderr)
        return 1

    if opts.color == 'no' or (opts.color == 'auto' and not color_terminal()):
        nocolor()

    doctreedir = abspath(opts.doctreedir or path.join(outdir, '.doctrees'))

    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr

    if opts.quiet:
        status = None
    if opts.really_quiet:
        status = warning = None
    if warning and opts.warnfile:
        try:
            warnfp = open(opts.warnfile, 'w')
        except Exception as exc:
            print('Error: Cannot open warning file %r: %s' %
                  (opts.warnfile, exc),
                  file=sys.stderr)
            sys.exit(1)
        warning = Tee(warning, warnfp)  # type: ignore
        error = warning

    confoverrides = {}
    for val in opts.define:
        try:
            key, val = val.split('=', 1)
        except ValueError:
            print('Error: -D option argument must be in the form name=value.',
                  file=sys.stderr)
            return 1
        if likely_encoding and isinstance(val, binary_type):
            try:
                val = val.decode(likely_encoding)
            except UnicodeError:
                pass
        confoverrides[key] = val

    for val in opts.htmldefine:
        try:
            key, val = val.split('=')
        except ValueError:
            print('Error: -A option argument must be in the form name=value.',
                  file=sys.stderr)
            return 1
        try:
            val = int(val)
        except ValueError:
            if likely_encoding and isinstance(val, binary_type):
                try:
                    val = val.decode(likely_encoding)
                except UnicodeError:
                    pass
        confoverrides['html_context.%s' % key] = val

    if opts.nitpicky:
        confoverrides['nitpicky'] = True

    app = None
    try:
        with patch_docutils(), docutils_namespace():
            app = Sphinx(srcdir, confdir, outdir, doctreedir, opts.builder,
                         confoverrides, status, warning, opts.freshenv,
                         opts.warningiserror, opts.tags, opts.verbosity,
                         opts.jobs)
            app.build(opts.force_all, filenames)
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, opts, exc, error)
        return 1
Esempio n. 15
0
def build_main(argv=sys.argv[1:]):
    # type: (List[str]) -> int
    """Sphinx build "main" command-line entry."""

    parser = get_parser()
    args = parser.parse_args(argv)

    if args.noconfig:
        args.confdir = None
    elif not args.confdir:
        args.confdir = args.sourcedir

    if not args.doctreedir:
        args.doctreedir = os.path.join(args.outputdir, '.doctrees')

    # handle remaining filename arguments
    filenames = args.filenames
    missing_files = []
    for filename in filenames:
        if not os.path.isfile(filename):
            missing_files.append(filename)
    if missing_files:
        parser.error(__('cannot find files %r') % missing_files)

    if args.force_all and filenames:
        parser.error(__('cannot combine -a option and filenames'))

    if args.color == 'no' or (args.color == 'auto' and not color_terminal()):
        nocolor()

    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr

    if args.quiet:
        status = None

    if args.really_quiet:
        status = warning = None

    if warning and args.warnfile:
        try:
            warnfp = open(args.warnfile, 'w')
        except Exception as exc:
            parser.error(__('cannot open warning file %r: %s') % (
                args.warnfile, exc))
        warning = Tee(warning, warnfp)  # type: ignore
        error = warning

    confoverrides = {}
    for val in args.define:
        try:
            key, val = val.split('=', 1)
        except ValueError:
            parser.error(__('-D option argument must be in the form name=value'))
        confoverrides[key] = val

    for val in args.htmldefine:
        try:
            key, val = val.split('=')
        except ValueError:
            parser.error(__('-A option argument must be in the form name=value'))
        try:
            val = int(val)
        except ValueError:
            pass
        confoverrides['html_context.%s' % key] = val

    if args.nitpicky:
        confoverrides['nitpicky'] = True

    app = None
    try:
        confdir = args.confdir or args.sourcedir
        with patch_docutils(confdir), docutils_namespace():
            app = Sphinx(args.sourcedir, args.confdir, args.outputdir,
                         args.doctreedir, args.builder, confoverrides, status,
                         warning, args.freshenv, args.warningiserror,
                         args.tags, args.verbosity, args.jobs, args.keep_going)
            app.build(args.force_all, filenames)
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, args, exc, error)
        return 2
Esempio n. 16
0
def build_main(argv: List[str] = sys.argv[1:]) -> int:
    """Sphinx build "main" command-line entry."""

    parser = get_parser()
    args = parser.parse_args(argv)

    if args.noconfig:
        args.confdir = None
    elif not args.confdir:
        args.confdir = args.sourcedir

    if not args.doctreedir:
        args.doctreedir = os.path.join(args.outputdir, '.doctrees')

    # handle remaining filename arguments
    filenames = args.filenames
    missing_files = []
    for filename in filenames:
        if not os.path.isfile(filename):
            missing_files.append(filename)
    if missing_files:
        parser.error(__('cannot find files %r') % missing_files)

    if args.force_all and filenames:
        parser.error(__('cannot combine -a option and filenames'))

    if args.color == 'no' or (args.color == 'auto' and not color_terminal()):
        nocolor()

    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr

    if args.quiet:
        status = None

    if args.really_quiet:
        status = warning = None

    if warning and args.warnfile:
        try:
            warnfp = open(args.warnfile, 'w')
        except Exception as exc:
            parser.error(
                __('cannot open warning file %r: %s') % (args.warnfile, exc))
        warning = Tee(warning, warnfp)  # type: ignore
        error = warning

    confoverrides = {}
    for val in args.define:
        try:
            key, val = val.split('=', 1)
        except ValueError:
            parser.error(
                __('-D option argument must be in the form name=value'))
        confoverrides[key] = val

    for val in args.htmldefine:
        try:
            key, val = val.split('=')
        except ValueError:
            parser.error(
                __('-A option argument must be in the form name=value'))
        try:
            val = int(val)
        except ValueError:
            pass
        confoverrides['html_context.%s' % key] = val

    if args.nitpicky:
        confoverrides['nitpicky'] = True

    app = None
    try:
        confdir = args.confdir or args.sourcedir
        with patch_docutils(confdir), docutils_namespace():
            app = Sphinx(args.sourcedir, args.confdir, args.outputdir,
                         args.doctreedir, args.builder, confoverrides, status,
                         warning, args.freshenv, args.warningiserror,
                         args.tags, args.verbosity, args.jobs, args.keep_going)
            app.build(args.force_all, filenames)

            # Post process equations if requested
            if os.environ.get('UPDATEHTMLEQS'):
                ival = os.environ.get('UPDATEHTMLEQS')
                ival = ival.strip()
                if ival == 'Y':
                    # Perform post processing of equations here
                    print("Performing post processing of equations.")

                    eqVerbose = ""
                    if os.environ.get('UPDATEHTMLEQSVERBOSE'):
                        eqVerbose = "-v"

                    #@python3 ./postProcessEquations.py -d $(BUILDDIR) -p html -b sphinx -s index.html $(UPDATEHTMLEQSVERBOSE)
                    builddir = os.sep.join(args.outputdir.split('/')[0:-1])
                    projdir = args.outputdir.split('/')[-1]
                    if builddir == projdir:
                        projdir = "."
                    if eqVerbose != "":
                        cmd = [
                            'python3', './postProcessEquations.py', '-d',
                            builddir, '-p', projdir, '-b', 'sphinx', '-s',
                            'index.html', eqVerbose
                        ]
                    else:
                        cmd = [
                            'python3', './postProcessEquations.py', '-d',
                            builddir, '-p', projdir, '-b', 'sphinx', '-s',
                            'index.html'
                        ]
                    print('Running:', cmd)
                    out = check_output(cmd)

            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, args, exc, error)
        return 2
Esempio n. 17
0
def main(argv=sys.argv[1:]):  # type: ignore
    # type: (List[unicode]) -> int
    parser = optparse.OptionParser(USAGE, epilog=EPILOG, formatter=MyFormatter())
    parser.add_option('--version', action='store_true', dest='version',
                      help='show version information and exit')

    group = parser.add_option_group('General options')
    group.add_option('-b', metavar='BUILDER', dest='builder', default='html',
                     help='builder to use; default is html')
    group.add_option('-a', action='store_true', dest='force_all',
                     help='write all files; default is to only write new and '
                     'changed files')
    group.add_option('-E', action='store_true', dest='freshenv',
                     help='don\'t use a saved environment, always read '
                     'all files')
    group.add_option('-d', metavar='PATH', default=None, dest='doctreedir',
                     help='path for the cached environment and doctree files '
                     '(default: outdir/.doctrees)')
    group.add_option('-j', metavar='N', default=1, type='int', dest='jobs',
                     help='build in parallel with N processes where possible')
    # this option never gets through to this point (it is intercepted earlier)
    # group.add_option('-M', metavar='BUILDER', dest='make_mode',
    #                 help='"make" mode -- as used by Makefile, like '
    #                 '"sphinx-build -M html"')

    group = parser.add_option_group('Build configuration options')
    group.add_option('-c', metavar='PATH', dest='confdir',
                     help='path where configuration file (conf.py) is located '
                     '(default: same as sourcedir)')
    group.add_option('-C', action='store_true', dest='noconfig',
                     help='use no config file at all, only -D options')
    group.add_option('-D', metavar='setting=value', action='append',
                     dest='define', default=[],
                     help='override a setting in configuration file')
    group.add_option('-A', metavar='name=value', action='append',
                     dest='htmldefine', default=[],
                     help='pass a value into HTML templates')
    group.add_option('-t', metavar='TAG', action='append',
                     dest='tags', default=[],
                     help='define tag: include "only" blocks with TAG')
    group.add_option('-n', action='store_true', dest='nitpicky',
                     help='nit-picky mode, warn about all missing references')

    group = parser.add_option_group('Console output options')
    group.add_option('-v', action='count', dest='verbosity', default=0,
                     help='increase verbosity (can be repeated)')
    group.add_option('-q', action='store_true', dest='quiet',
                     help='no output on stdout, just warnings on stderr')
    group.add_option('-Q', action='store_true', dest='really_quiet',
                     help='no output at all, not even warnings')
    group.add_option('--color', dest='color',
                     action='store_const', const='yes', default='auto',
                     help='Do emit colored output (default: auto-detect)')
    group.add_option('-N', '--no-color', dest='color',
                     action='store_const', const='no',
                     help='Do not emit colored output (default: auot-detect)')
    group.add_option('-w', metavar='FILE', dest='warnfile',
                     help='write warnings (and errors) to given file')
    group.add_option('-W', action='store_true', dest='warningiserror',
                     help='turn warnings into errors')
    group.add_option('-T', action='store_true', dest='traceback',
                     help='show full traceback on exception')
    group.add_option('-P', action='store_true', dest='pdb',
                     help='run Pdb on exception')

    # parse options
    try:
        opts, args = parser.parse_args(argv)
    except SystemExit as err:
        return err.code

    # handle basic options
    if opts.version:
        print('Sphinx (sphinx-build) %s' % __display_version__)
        return 0

    # get paths (first and second positional argument)
    try:
        srcdir = abspath(args[0])
        confdir = abspath(opts.confdir or srcdir)
        if opts.noconfig:
            confdir = None
        if not path.isdir(srcdir):
            print('Error: Cannot find source directory `%s\'.' % srcdir,
                  file=sys.stderr)
            return 1
        if not opts.noconfig and not path.isfile(path.join(confdir, 'conf.py')):
            print('Error: Config directory doesn\'t contain a conf.py file.',
                  file=sys.stderr)
            return 1
        outdir = abspath(args[1])
        if srcdir == outdir:
            print('Error: source directory and destination directory are same.',
                  file=sys.stderr)
            return 1
    except IndexError:
        parser.print_help()
        return 1
    except UnicodeError:
        print(
            'Error: Multibyte filename not supported on this filesystem '
            'encoding (%r).' % fs_encoding, file=sys.stderr)
        return 1

    # handle remaining filename arguments
    filenames = args[2:]
    errored = False
    for filename in filenames:
        if not path.isfile(filename):
            print('Error: Cannot find file %r.' % filename, file=sys.stderr)
            errored = True
    if errored:
        return 1

    # likely encoding used for command-line arguments
    try:
        locale = __import__('locale')  # due to submodule of the same name
        likely_encoding = locale.getpreferredencoding()
    except Exception:
        likely_encoding = None

    if opts.force_all and filenames:
        print('Error: Cannot combine -a option and filenames.', file=sys.stderr)
        return 1

    if opts.color == 'no' or (opts.color == 'auto' and not color_terminal()):
        nocolor()

    doctreedir = abspath(opts.doctreedir or path.join(outdir, '.doctrees'))

    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr

    if opts.quiet:
        status = None
    if opts.really_quiet:
        status = warning = None
    if warning and opts.warnfile:
        try:
            warnfp = open(opts.warnfile, 'w')
        except Exception as exc:
            print('Error: Cannot open warning file %r: %s' %
                  (opts.warnfile, exc), file=sys.stderr)
            sys.exit(1)
        warning = Tee(warning, warnfp)  # type: ignore
        error = warning

    confoverrides = {}
    for val in opts.define:
        try:
            key, val = val.split('=', 1)
        except ValueError:
            print('Error: -D option argument must be in the form name=value.',
                  file=sys.stderr)
            return 1
        if likely_encoding and isinstance(val, binary_type):
            try:
                val = val.decode(likely_encoding)
            except UnicodeError:
                pass
        confoverrides[key] = val

    for val in opts.htmldefine:
        try:
            key, val = val.split('=')
        except ValueError:
            print('Error: -A option argument must be in the form name=value.',
                  file=sys.stderr)
            return 1
        try:
            val = int(val)
        except ValueError:
            if likely_encoding and isinstance(val, binary_type):
                try:
                    val = val.decode(likely_encoding)
                except UnicodeError:
                    pass
        confoverrides['html_context.%s' % key] = val

    if opts.nitpicky:
        confoverrides['nitpicky'] = True

    app = None
    try:
        with patch_docutils(), docutils_namespace():
            app = Sphinx(srcdir, confdir, outdir, doctreedir, opts.builder,
                         confoverrides, status, warning, opts.freshenv,
                         opts.warningiserror, opts.tags, opts.verbosity, opts.jobs)
            app.build(opts.force_all, filenames)
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, opts, exc, error)
        return 1
Esempio n. 18
0
def main(argv=sys.argv[1:]):  # type: ignore
    # type: (List[unicode]) -> int

    parser = get_parser()
    args = parser.parse_args(argv)

    # get paths (first and second positional argument)
    try:
        srcdir = abspath(args.sourcedir)
        confdir = abspath(args.confdir or srcdir)
        if args.noconfig:
            confdir = None

        if not path.isdir(srcdir):
            parser.error('cannot find source directory (%s)' % srcdir)
        if not args.noconfig and not path.isfile(path.join(confdir,
                                                           'conf.py')):
            parser.error("config directory doesn't contain a conf.py file "
                         "(%s)" % confdir)

        outdir = abspath(args.outputdir)
        if srcdir == outdir:
            parser.error('source directory and destination directory are same')
    except UnicodeError:
        parser.error('multibyte filename not supported on this filesystem '
                     'encoding (%r)' % fs_encoding)

    # handle remaining filename arguments
    filenames = args.filenames
    missing_files = []
    for filename in filenames:
        if not path.isfile(filename):
            missing_files.append(filename)
    if missing_files:
        parser.error('cannot find files %r' % missing_files)

    # likely encoding used for command-line arguments
    try:
        locale = __import__('locale')  # due to submodule of the same name
        likely_encoding = locale.getpreferredencoding()
    except Exception:
        likely_encoding = None

    if args.force_all and filenames:
        parser.error('cannot combine -a option and filenames')

    if args.color == 'no' or (args.color == 'auto' and not color_terminal()):
        nocolor()

    doctreedir = abspath(args.doctreedir or path.join(outdir, '.doctrees'))

    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr

    if args.quiet:
        status = None

    if args.really_quiet:
        status = warning = None

    if warning and args.warnfile:
        try:
            warnfp = open(args.warnfile, 'w')
        except Exception as exc:
            parser.error('cannot open warning file %r: %s' %
                         (args.warnfile, exc))
        warning = Tee(warning, warnfp)  # type: ignore
        error = warning

    confoverrides = {}
    for val in args.define:
        try:
            key, val = val.split('=', 1)
        except ValueError:
            parser.error('-D option argument must be in the form name=value')
        if likely_encoding and isinstance(val, binary_type):
            try:
                val = val.decode(likely_encoding)
            except UnicodeError:
                pass
        confoverrides[key] = val

    for val in args.htmldefine:
        try:
            key, val = val.split('=')
        except ValueError:
            parser.error('-A option argument must be in the form name=value')
        try:
            val = int(val)
        except ValueError:
            if likely_encoding and isinstance(val, binary_type):
                try:
                    val = val.decode(likely_encoding)
                except UnicodeError:
                    pass
        confoverrides['html_context.%s' % key] = val

    if args.nitpicky:
        confoverrides['nitpicky'] = True

    app = None
    try:
        with patch_docutils(), docutils_namespace():
            app = Sphinx(srcdir, confdir, outdir, doctreedir, args.builder,
                         confoverrides, status, warning, args.freshenv,
                         args.warningiserror, args.tags, args.verbosity,
                         args.jobs)
            app.build(args.force_all, filenames)
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, args, exc, error)
        return 2
Esempio n. 19
0
def test_man(app, status, warning):
    with patch_docutils(app.confdir):
        app.builder.build(['contents'])
    assert warning.getvalue() == ''
Esempio n. 20
0
def build_sphinx(
    sourcedir,
    outputdir,
    *,
    use_external_toc=True,
    confdir=None,
    path_config=None,
    noconfig=False,
    confoverrides=None,
    doctreedir=None,
    filenames=None,
    force_all=False,
    quiet=False,
    really_quiet=False,
    builder="html",
    freshenv=False,
    warningiserror=False,
    tags=None,
    verbosity=0,
    jobs=None,
    keep_going=False,
) -> Union[int, Exception]:
    """Sphinx build "main" command-line entry.

    This is a slightly modified version of
    https://github.com/sphinx-doc/sphinx/blob/3.x/sphinx/cmd/build.py#L198.

    """
    #######################
    # Configuration creation
    sphinx_config, config_meta = get_final_config(
        user_yaml=Path(path_config) if path_config else None,
        cli_config=confoverrides or {},
        sourcedir=Path(sourcedir),
        use_external_toc=use_external_toc,
    )

    ##################################
    # Preparing Sphinx build arguments

    # Configuration directory
    if noconfig:
        confdir = None
    elif not confdir:
        confdir = sourcedir

    # Doctrees directory
    if not doctreedir:
        doctreedir = Path(outputdir).parent.joinpath(".doctrees")

    if jobs is None:
        jobs = 1

    # Manually re-building files in filenames
    if filenames is None:
        filenames = []
    missing_files = []
    for filename in filenames:
        if not op.isfile(filename):
            missing_files.append(filename)
    if missing_files:
        raise IOError("cannot find files %r" % missing_files)

    if force_all and filenames:
        raise ValueError("cannot combine -a option and filenames")

    # Debug args (hack to get this to pass through properly)
    def debug_args():
        pass

    debug_args.pdb = False
    debug_args.verbosity = False
    debug_args.traceback = False

    # Logging behavior
    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr
    if quiet:
        status = None
    if really_quiet:
        status = warning = None

    ###################
    # Build with Sphinx
    app = None  # In case we fail, this allows us to handle the exception
    try:
        # These patches temporarily override docutils global variables,
        # such as the dictionaries of directives, roles and nodes
        # NOTE: this action is not thread-safe and not suitable for asynchronous use!
        with patch_docutils(confdir), docutils_namespace():
            app = Sphinx(
                srcdir=sourcedir,
                confdir=confdir,
                outdir=outputdir,
                doctreedir=doctreedir,
                buildername=builder,
                confoverrides=sphinx_config,
                status=status,
                warning=warning,
                freshenv=freshenv,
                warningiserror=warningiserror,
                tags=tags,
                verbosity=verbosity,
                parallel=jobs,
                keep_going=keep_going,
            )
            app.srcdir = Path(app.srcdir).as_posix()
            app.outdir = Path(app.outdir).as_posix()
            app.confdir = Path(app.confdir).as_posix()
            app.doctreedir = Path(app.doctreedir).as_posix()

            # We have to apply this update after the sphinx initialisation,
            # since default_latex_documents is dynamically generated
            # see sphinx/builders/latex/__init__.py:default_latex_documents
            new_latex_documents = update_latex_documents(
                app.config.latex_documents, config_meta["latex_doc_overrides"])
            app.config.latex_documents = new_latex_documents

            # Build latex_doc tuples based on --individualpages option request
            if config_meta["latex_individualpages"]:
                from .pdf import autobuild_singlepage_latexdocs

                # Ask Builder to read the source files to fetch titles and documents
                app.builder.read()
                latex_documents = autobuild_singlepage_latexdocs(app)
                app.config.latex_documents = latex_documents

            app.build(force_all, filenames)

            return app.statuscode

    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, debug_args, exc, error)
        return exc
Esempio n. 21
0
def build_sphinx(
    sourcedir,
    outputdir,
    confdir=None,
    path_config=None,
    noconfig=False,
    confoverrides=None,
    doctreedir=None,
    filenames=None,
    force_all=False,
    quiet=False,
    really_quiet=False,
    builder="html",
    freshenv=False,
    warningiserror=False,
    tags=None,
    verbosity=0,
    jobs=None,
    keep_going=False,
) -> Union[int, Exception]:
    """Sphinx build "main" command-line entry.

    This is a slightly modified version of
    https://github.com/sphinx-doc/sphinx/blob/3.x/sphinx/cmd/build.py#L198.

    """
    #######################
    # Configuration creation
    sphinx_config, config_meta = get_final_config(
        user_yaml=Path(path_config) if path_config else None,
        cli_config=confoverrides or {},
        sourcedir=Path(sourcedir),
    )

    ##################################
    # Preparing Sphinx build arguments

    # Configuration directory
    if noconfig:
        confdir = None
    elif not confdir:
        confdir = sourcedir

    # Doctrees directory
    if not doctreedir:
        doctreedir = Path(outputdir).parent.joinpath(".doctrees")

    if jobs is None:
        jobs = 1

    # Manually re-building files in filenames
    if filenames is None:
        filenames = []
    missing_files = []
    for filename in filenames:
        if not op.isfile(filename):
            missing_files.append(filename)
    if missing_files:
        raise IOError("cannot find files %r" % missing_files)

    if force_all and filenames:
        raise ValueError("cannot combine -a option and filenames")

    # Debug args (hack to get this to pass through properly)
    def debug_args():
        pass

    debug_args.pdb = False
    debug_args.verbosity = False
    debug_args.traceback = False

    # Logging behavior
    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr
    if quiet:
        status = None
    if really_quiet:
        status = warning = None

    ###################
    # Build with Sphinx
    app = None  # In case we fail, this allows us to handle the exception
    try:
        # These patches temporarily override docutils global variables,
        # such as the dictionaries of directives, roles and nodes
        # NOTE: this action is not thread-safe and not suitable for asynchronous use!
        with patch_docutils(confdir), docutils_namespace():
            app = Sphinx(
                srcdir=sourcedir,
                confdir=confdir,
                outdir=outputdir,
                doctreedir=doctreedir,
                buildername=builder,
                confoverrides=sphinx_config,
                status=status,
                warning=warning,
                freshenv=freshenv,
                warningiserror=warningiserror,
                tags=tags,
                verbosity=verbosity,
                parallel=jobs,
                keep_going=keep_going,
            )
            app.srcdir = Path(app.srcdir).as_posix()
            app.outdir = Path(app.outdir).as_posix()
            app.confdir = Path(app.confdir).as_posix()
            app.doctreedir = Path(app.doctreedir).as_posix()

            # We have to apply this update after the sphinx initialisation,
            # since default_latex_documents is dynamically generated
            # see sphinx/builders/latex/__init__.py:default_latex_documents
            # TODO what if the user has specifically set latex_documents?
            default_latex_document = app.config.latex_documents[0]
            new_latex_document = update_latex_document(
                default_latex_document, config_meta["latex_doc_overrides"])
            app.config.latex_documents = [new_latex_document]

            app.build(force_all, filenames)

            # Write an index.html file in the root to redirect to the first page
            path_index = outputdir.joinpath("index.html")
            if sphinx_config["globaltoc_path"]:
                path_toc = Path(sphinx_config["globaltoc_path"])
                if not path_toc.exists():
                    raise IOError(("You gave a Configuration file path"
                                   f"that doesn't exist: {path_toc}"))
                if path_toc.suffix not in [".yml", ".yaml"]:
                    raise IOError("You gave a Configuration file path"
                                  f"that is not a YAML file: {path_toc}")
            else:
                path_toc = None

            if not path_index.exists() and path_toc:
                toc = yaml.safe_load(path_toc.read_text(encoding="utf8"))
                if isinstance(toc, dict):
                    first_page = toc["file"]
                else:
                    first_page = toc[0]["file"]
                first_page = first_page.split(".")[0] + ".html"
                with open(path_index, "w", encoding="utf8") as ff:
                    ff.write(REDIRECT_TEXT.format(first_page=first_page))
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, debug_args, exc, error)
        return exc
Esempio n. 22
0
def create_sphinx_app(
    conf_dir=None,
    confoverrides=None,
    source_dir=None,
    output_dir=None,
    doctree_dir=None,
) -> Tuple[Sphinx, dict, dict]:
    """Yield a Sphinx Application, within a context.

    This context implements the standard sphinx patches to docutils,
    including the addition of builtin and extension roles and directives.

    Parameters
    ----------
    conf_dir : str or None
        path where configuration file (conf.py) is located
    confoverrides : dict or None
        dictionary containing parameters that will update those set from conf.py

    """

    # below is taken from sphinx.cmd.build.main
    # note: this may be removed in future
    sphinx.locale.setlocale(locale.LC_ALL, "")
    sphinx.locale.init_console(os.path.join(package_dir, "locale"), "sphinx")

    # below is adapted from sphinx.cmd.build.build_main
    confoverrides = confoverrides or {}

    builder = "html"

    # these are not needed before build, but there existence is checked in ``Sphinx```
    # note source directory and output directory cannot be identical
    _source_temp = _out_temp = None
    if source_dir is None:
        source_dir = _source_temp = tempfile.mkdtemp()
    if output_dir is None and doctree_dir is None:
        doctree_dir = output_dir = _out_temp = tempfile.mkdtemp()
    elif doctree_dir is None:
        doctree_dir = _out_temp = tempfile.mkdtemp()
    elif output_dir is None:
        output_dir = _out_temp = tempfile.mkdtemp()

    app = None
    try:
        log_stream_status = StringIO()
        log_stream_warning = StringIO()
        with patch_docutils(conf_dir), docutils_namespace():
            from docutils.parsers.rst.directives import _directives
            from docutils.parsers.rst.roles import _roles
            from sphinx.util.docutils import additional_nodes

            app = Sphinx(
                source_dir,
                conf_dir,
                output_dir,
                doctree_dir,
                builder,
                confoverrides=confoverrides,
                status=log_stream_status,
                warning=log_stream_warning,
                # also originally parsed
                # args.freshenv, args.warningiserror,
                # args.tags, args.verbosity, args.jobs, args.keep_going
            )
            roles = copy.copy(_roles)
            directives = copy.copy(_directives)
            additional_nodes = copy.copy(additional_nodes)

    except (Exception, KeyboardInterrupt) as exc:
        # handle_exception(app, args, exc, error)
        raise exc
    finally:
        if _source_temp:
            shutil.rmtree(_source_temp, ignore_errors=True)
        if _out_temp:
            shutil.rmtree(_out_temp, ignore_errors=True)

    return SphinxAppEnv(app, roles, directives, additional_nodes,
                        log_stream_status, log_stream_warning)
Esempio n. 23
0
def main(argv=sys.argv[1:]):  # type: ignore
    # type: (List[unicode]) -> int

    parser = get_parser()
    # parse options
    try:
        args = parser.parse_args(argv)
    except SystemExit as err:
        return err.code

    # get paths (first and second positional argument)
    try:
        srcdir = abspath(args.sourcedir)
        confdir = abspath(args.confdir or srcdir)
        if args.noconfig:
            confdir = None
        if not path.isdir(srcdir):
            print('Error: Cannot find source directory `%s\'.' % srcdir,
                  file=sys.stderr)
            return 1
        if not args.noconfig and not path.isfile(path.join(confdir, 'conf.py')):
            print('Error: Config directory doesn\'t contain a conf.py file.',
                  file=sys.stderr)
            return 1
        outdir = abspath(args.outputdir)
        if srcdir == outdir:
            print('Error: source directory and destination directory are same.',
                  file=sys.stderr)
            return 1
    except UnicodeError:
        print(
            'Error: Multibyte filename not supported on this filesystem '
            'encoding (%r).' % fs_encoding, file=sys.stderr)
        return 1

    # handle remaining filename arguments
    filenames = args.filenames
    errored = False
    for filename in filenames:
        if not path.isfile(filename):
            print('Error: Cannot find file %r.' % filename, file=sys.stderr)
            errored = True
    if errored:
        return 1

    # likely encoding used for command-line arguments
    try:
        locale = __import__('locale')  # due to submodule of the same name
        likely_encoding = locale.getpreferredencoding()
    except Exception:
        likely_encoding = None

    if args.force_all and filenames:
        print('Error: Cannot combine -a option and filenames.', file=sys.stderr)
        return 1

    if args.color == 'no' or (args.color == 'auto' and not color_terminal()):
        nocolor()

    doctreedir = abspath(args.doctreedir or path.join(outdir, '.doctrees'))

    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr

    if args.quiet:
        status = None
    if args.really_quiet:
        status = warning = None
    if warning and args.warnfile:
        try:
            warnfp = open(args.warnfile, 'w')
        except Exception as exc:
            print('Error: Cannot open warning file %r: %s' %
                  (args.warnfile, exc), file=sys.stderr)
            sys.exit(1)
        warning = Tee(warning, warnfp)  # type: ignore
        error = warning

    confoverrides = {}
    for val in args.define:
        try:
            key, val = val.split('=', 1)
        except ValueError:
            print('Error: -D option argument must be in the form name=value.',
                  file=sys.stderr)
            return 1
        if likely_encoding and isinstance(val, binary_type):
            try:
                val = val.decode(likely_encoding)
            except UnicodeError:
                pass
        confoverrides[key] = val

    for val in args.htmldefine:
        try:
            key, val = val.split('=')
        except ValueError:
            print('Error: -A option argument must be in the form name=value.',
                  file=sys.stderr)
            return 1
        try:
            val = int(val)
        except ValueError:
            if likely_encoding and isinstance(val, binary_type):
                try:
                    val = val.decode(likely_encoding)
                except UnicodeError:
                    pass
        confoverrides['html_context.%s' % key] = val

    if args.nitpicky:
        confoverrides['nitpicky'] = True

    app = None
    try:
        with patch_docutils(), docutils_namespace():
            app = Sphinx(srcdir, confdir, outdir, doctreedir, args.builder,
                         confoverrides, status, warning, args.freshenv,
                         args.warningiserror, args.tags, args.verbosity, args.jobs)
            app.build(args.force_all, filenames)
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, args, exc, error)
        return 1
Esempio n. 24
0
def test_texinfo(app, status, warning):
    with patch_docutils(app.confdir):
        app.builder.build(['contents'])
Esempio n. 25
0
def build_sphinx(
    sourcedir,
    outputdir,
    confdir=None,
    noconfig=False,
    confoverrides=None,
    htmloverrides=None,
    doctreedir=None,
    filenames=None,
    force_all=False,
    quiet=False,
    really_quiet=False,
    nitpicky=False,
    builder="html",
    freshenv=False,
    warningiserror=False,
    tags=None,
    verbosity=0,
    jobs=None,
    keep_going=False,
):
    """Sphinx build "main" command-line entry.

    This is a slightly modified version of
    https://github.com/sphinx-doc/sphinx/blob/3.x/sphinx/cmd/build.py#L198.
    """

    # Manual configuration overrides
    if confoverrides is None:
        confoverrides = {}
    config = DEFAULT_CONFIG.copy()
    config.update(confoverrides)

    # HTML-specific configuration
    if htmloverrides is None:
        htmloverrides = {}
    for key, val in htmloverrides.items():
        config["html_context.%s" % key] = val

    # Configuration directory
    if noconfig:
        confdir = None
    elif not confdir:
        confdir = sourcedir

    # Doctrees directory
    if not doctreedir:
        doctreedir = op.join(outputdir, ".doctrees")

    if jobs is None:
        jobs = 1

    # Manually re-building files in filenames
    if filenames is None:
        filenames = []
    missing_files = []
    for filename in filenames:
        if not op.isfile(filename):
            missing_files.append(filename)
    if missing_files:
        raise ValueError("cannot find files %r" % missing_files)

    if force_all and filenames:
        raise ValueError("cannot combine -a option and filenames")

    # Debug args (hack to get this to pass through properly)
    def debug_args():
        pass

    debug_args.pdb = False
    debug_args.verbosity = False
    debug_args.traceback = False

    # Logging behavior
    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr
    if quiet:
        status = None
    if really_quiet:
        status = warning = None

    # Error on warnings
    if nitpicky:
        config["nitpicky"] = True

    app = None  # In case we fail, this allows us to handle the exception
    try:
        with patch_docutils(confdir), docutils_namespace():
            app = Sphinx(
                sourcedir,
                confdir,
                outputdir,
                doctreedir,
                builder,
                config,
                status,
                warning,
                freshenv,
                warningiserror,
                tags,
                verbosity,
                jobs,
                keep_going,
            )
            app.build(force_all, filenames)

            # Write an index.html file in the root to redirect to the first page
            path_index = outputdir.joinpath("index.html")
            if config["globaltoc_path"]:
                path_toc = Path(config["globaltoc_path"])
                if not path_toc.exists():
                    raise ValueError(
                        f"You gave a Table of Contents path that doesn't exist: {path_toc}"
                    )
                if path_toc.suffix not in [".yml", ".yaml"]:
                    raise ValueError(
                        f"You gave a Table of Contents path that is not a YAML file: {path_toc}"
                    )
            else:
                path_toc = None

            if not path_index.exists() and path_toc:
                toc = yaml.safe_load(path_toc.read_text())
                first_page = toc[0]["file"].split(".")[0] + ".html"
                with open(path_index, "w") as ff:
                    ff.write(REDIRECT_TEXT.format(first_page=first_page))
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, debug_args, exc, error)
        return 2
Esempio n. 26
0
dark_highlighter = PygmentsBridge("html", "sphinx_library.theme.LibraryDark")
with open(os.path.join(SASS_DIR, "_pygments-dark.scss"), "w") as f:
    f.write(disclaimer)
    f.write(dark_highlighter.get_stylesheet())

# Compile theme scss.
sass.compile(
    output_style="compressed",
    dirname=(SASS_DIR, CSS_DIR),
)

# Copy pygments to main static dir, to override sphinx's pygments file.
os.replace(
    os.path.join(CSS_DIR, "pygments.css"),
    os.path.join(STATIC_DIR, "pygments.css"),
)


# -- BUILD PROJECT DOCS --------------------------------------------------------

with patch_docutils(DOCS_IN_DIR), docutils_namespace():
    app = Sphinx(
        srcdir=DOCS_IN_DIR,
        confdir=DOCS_IN_DIR,
        outdir=DOCS_OUT_DIR,
        doctreedir=os.path.join(DOCS_OUT_DIR, ".doctrees"),
        buildername="html",
        warningiserror=True
    )
    app.build()
Esempio n. 27
0
def build_sphinx(
    sourcedir,
    outputdir,
    confdir=None,
    path_config=None,
    noconfig=False,
    confoverrides=None,
    extra_extensions=None,
    htmloverrides=None,
    latexoverrides=None,
    doctreedir=None,
    filenames=None,
    force_all=False,
    quiet=False,
    really_quiet=False,
    nitpicky=False,
    builder="html",
    freshenv=False,
    warningiserror=False,
    tags=None,
    verbosity=0,
    jobs=None,
    keep_going=False,
):
    """Sphinx build "main" command-line entry.

    This is a slightly modified version of
    https://github.com/sphinx-doc/sphinx/blob/3.x/sphinx/cmd/build.py#L198.

    Extra parameters
    ----------------

    extra_extensions : list | None
        A list of extra extensions to load into Sphinx. This must be done
        before Sphinx is initialized otherwise the extensions aren't properly
        initialized.
    """

    if confoverrides is None:
        confoverrides = {}
    if latexoverrides is None:
        latexoverrides = {}

    #######################
    # Configuration updates

    # Start with the default Sphinx config
    sphinx_config = DEFAULT_CONFIG.copy()

    # Update with the *default* config.yml
    default_yaml_config = yaml.safe_load(PATH_YAML_DEFAULT.read_text())
    new_config = yaml_to_sphinx(default_yaml_config)
    _recursive_update(sphinx_config, new_config)

    # Update with the given config file, if it exists
    if path_config:
        path_config = Path(path_config)
        yaml_config = yaml.safe_load(path_config.read_text())

        # Check for manual Sphinx over-rides which we'll apply later to take precedence
        sphinx_overrides = yaml_config.get("sphinx", {}).get("config")
        if sphinx_overrides:
            confoverrides.update(sphinx_overrides)

        # Some latex-specific changes we need to make if we're building latex
        if builder == "latex":
            # First update the overrides with the latex config
            latexoverrides.update(yaml_config.get("latex", {}))

            # If we have a document title and no explicit latex title, use the doc title
            if "title" in yaml_config.keys():
                latex_documents = latexoverrides.get("latex_documents", {})
                if "title" not in latex_documents:
                    latex_documents["title"] = yaml_config["title"]
                latexoverrides["latex_documents"] = latex_documents

        new_config = yaml_to_sphinx(yaml_config)
        _recursive_update(sphinx_config, new_config)

    # Manual configuration overrides from the CLI
    _recursive_update(sphinx_config, confoverrides)

    # HTML-specific configuration from the CLI
    if htmloverrides is None:
        htmloverrides = {}
    for key, val in htmloverrides.items():
        sphinx_config["html_context.%s" % key] = val

    # #LaTeX-specific configuration
    # TODO: if this is included we should ignore latex_documents
    # if latexoverrides is None:
    #     latexoverrides = {}
    # for key, val in latexoverrides.items():
    #     config[key] = val

    # Add the folder `_static` if it exists
    if Path(sourcedir).joinpath("_static").is_dir():
        paths_static = sphinx_config.get("html_static_path", [])
        paths_static.append("_static")
        sphinx_config["html_static_path"] = paths_static

    # Flags from the CLI
    # Raise more warnings
    if nitpicky:
        sphinx_config["nitpicky"] = True

    ##################################
    # Preparing Sphinx build arguments

    # Configuration directory
    if noconfig:
        confdir = None
    elif not confdir:
        confdir = sourcedir

    # Doctrees directory
    if not doctreedir:
        doctreedir = Path(outputdir).parent.joinpath(".doctrees")

    if jobs is None:
        jobs = 1

    # Manually re-building files in filenames
    if filenames is None:
        filenames = []
    missing_files = []
    for filename in filenames:
        if not op.isfile(filename):
            missing_files.append(filename)
    if missing_files:
        raise ValueError("cannot find files %r" % missing_files)

    if force_all and filenames:
        raise ValueError("cannot combine -a option and filenames")

    # Debug args (hack to get this to pass through properly)
    def debug_args():
        pass

    debug_args.pdb = False
    debug_args.verbosity = False
    debug_args.traceback = False

    # Logging behavior
    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr
    if quiet:
        status = None
    if really_quiet:
        status = warning = None

    ###################
    # Build with Sphinx
    app = None  # In case we fail, this allows us to handle the exception
    try:
        # This patch is what Sphinx does, so we copy it blindly...
        with patch_docutils(confdir), docutils_namespace():
            app = Sphinx(
                srcdir=sourcedir,
                confdir=confdir,
                outdir=outputdir,
                doctreedir=doctreedir,
                buildername=builder,
                confoverrides=sphinx_config,
                status=status,
                warning=warning,
                freshenv=freshenv,
                warningiserror=warningiserror,
                tags=tags,
                verbosity=verbosity,
                parallel=jobs,
                keep_going=keep_going,
            )
            # Apply Latex Overrides for latex_documents
            if (latexoverrides is not None
                    and "latex_documents" in latexoverrides.keys()):
                from .pdf import update_latex_documents

                latex_documents = update_latex_documents(
                    app.config.latex_documents[0], latexoverrides)
                app.config.latex_documents = [latex_documents]
            app.build(force_all, filenames)

            # Write an index.html file in the root to redirect to the first page
            path_index = outputdir.joinpath("index.html")
            if sphinx_config["globaltoc_path"]:
                path_toc = Path(sphinx_config["globaltoc_path"])
                if not path_toc.exists():
                    raise ValueError(("You gave a Configuration file path"
                                      f"that doesn't exist: {path_toc}"))
                if path_toc.suffix not in [".yml", ".yaml"]:
                    raise ValueError("You gave a Configuration file path"
                                     f"that is not a YAML file: {path_toc}")
            else:
                path_toc = None

            if not path_index.exists() and path_toc:
                toc = yaml.safe_load(path_toc.read_text())
                if isinstance(toc, dict):
                    first_page = toc["file"]
                else:
                    first_page = toc[0]["file"]
                first_page = first_page.split(".")[0] + ".html"
                with open(path_index, "w") as ff:
                    ff.write(REDIRECT_TEXT.format(first_page=first_page))
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, debug_args, exc, error)
        return exc
Esempio n. 28
0
def build_sphinx(
    sourcedir,
    outputdir,
    confdir=None,
    noconfig=False,
    confoverrides=None,
    extra_extensions=None,
    htmloverrides=None,
    latexoverrides=None,
    doctreedir=None,
    filenames=None,
    force_all=False,
    quiet=False,
    really_quiet=False,
    nitpicky=False,
    builder="html",
    freshenv=False,
    warningiserror=False,
    tags=None,
    verbosity=0,
    jobs=None,
    keep_going=False,
):
    """Sphinx build "main" command-line entry.

    This is a slightly modified version of
    https://github.com/sphinx-doc/sphinx/blob/3.x/sphinx/cmd/build.py#L198.

    Extra parameters
    ----------------

    extra_extensions : list | None
        A list of extra extensions to load into Sphinx. This must be done
        before Sphinx is initialized otherwise the extensions aren't properly
        initialized.
    """

    # Manual configuration overrides
    if confoverrides is None:
        confoverrides = {}
    config = DEFAULT_CONFIG.copy()
    config.update(confoverrides)

    if extra_extensions:
        if not isinstance(extra_extensions, list):
            extra_extensions = [extra_extensions]
        for ext in extra_extensions:
            config["extensions"].append(ext)

    # HTML-specific configuration
    if htmloverrides is None:
        htmloverrides = {}
    for key, val in htmloverrides.items():
        config["html_context.%s" % key] = val

    # #LaTeX-specific configuration
    # TODO: if this is included we should ignore latex_documents
    # if latexoverrides is None:
    #     latexoverrides = {}
    # for key, val in latexoverrides.items():
    #     config[key] = val

    # Configuration directory
    if noconfig:
        confdir = None
    elif not confdir:
        confdir = sourcedir

    # Doctrees directory
    if not doctreedir:
        doctreedir = Path(outputdir).parent.joinpath(".doctrees")

    if jobs is None:
        jobs = 1

    # Manually re-building files in filenames
    if filenames is None:
        filenames = []
    missing_files = []
    for filename in filenames:
        if not op.isfile(filename):
            missing_files.append(filename)
    if missing_files:
        raise ValueError("cannot find files %r" % missing_files)

    if force_all and filenames:
        raise ValueError("cannot combine -a option and filenames")

    # Debug args (hack to get this to pass through properly)
    def debug_args():
        pass

    debug_args.pdb = False
    debug_args.verbosity = False
    debug_args.traceback = False

    # Logging behavior
    status = sys.stdout
    warning = sys.stderr
    error = sys.stderr
    if quiet:
        status = None
    if really_quiet:
        status = warning = None

    # Raise more warnings
    if nitpicky:
        config["nitpicky"] = True

    app = None  # In case we fail, this allows us to handle the exception
    try:
        with patch_docutils(confdir), docutils_namespace():
            app = Sphinx(
                sourcedir,
                confdir,
                outputdir,
                doctreedir,
                builder,
                config,
                status,
                warning,
                freshenv,
                warningiserror,
                tags,
                verbosity,
                jobs,
                keep_going,
            )
            # Apply Latex Overrides for latex_documents
            if (
                latexoverrides is not None
                and "latex_documents" in latexoverrides.keys()
            ):
                from .pdf import update_latex_documents

                latex_documents = update_latex_documents(
                    app.config.latex_documents[0], latexoverrides
                )
                app.config.latex_documents = [latex_documents]
            app.build(force_all, filenames)

            # Write an index.html file in the root to redirect to the first page
            path_index = outputdir.joinpath("index.html")
            if config["globaltoc_path"]:
                path_toc = Path(config["globaltoc_path"])
                if not path_toc.exists():
                    raise ValueError(
                        (
                            f"You gave a Configuration file path"
                            "that doesn't exist: {path_toc}"
                        )
                    )
                if path_toc.suffix not in [".yml", ".yaml"]:
                    raise ValueError(
                        f"You gave a Configuration file path"
                        "that is not a YAML file: {path_toc}"
                    )
            else:
                path_toc = None

            if not path_index.exists() and path_toc:
                toc = yaml.safe_load(path_toc.read_text())
                if isinstance(toc, dict):
                    first_page = toc["file"]
                else:
                    first_page = toc[0]["file"]
                first_page = first_page.split(".")[0] + ".html"
                with open(path_index, "w") as ff:
                    ff.write(REDIRECT_TEXT.format(first_page=first_page))
            return app.statuscode
    except (Exception, KeyboardInterrupt) as exc:
        handle_exception(app, debug_args, exc, error)
        return exc