Ejemplo n.º 1
0
    def __init__(self, dirname, filename, overrides, tags):
        self.overrides = overrides
        self.values = Config.config_values.copy()
        config = {}
        if "extensions" in overrides:  # XXX do we need this?
            if isinstance(overrides["extensions"], string_types):
                config["extensions"] = overrides.pop("extensions").split(",")
            else:
                config["extensions"] = overrides.pop("extensions")
        if dirname is not None:
            config_file = path.join(dirname, filename)
            config["__file__"] = config_file
            config["tags"] = tags
            with cd(dirname):
                # we promise to have the config dir as current dir while the
                # config file is executed
                try:
                    execfile_(filename, config)
                except SyntaxError as err:
                    raise ConfigError(CONFIG_SYNTAX_ERROR % err)
                except SystemExit:
                    raise ConfigError(CONFIG_EXIT_ERROR)

        self._raw_config = config
        # these two must be preinitialized because extensions can add their
        # own config values
        self.setup = config.get("setup", None)
        self.extensions = config.get("extensions", [])
Ejemplo n.º 2
0
 def __init__(self, dirname, filename, overrides, tags):
     self.overrides = overrides
     self.values = Config.config_values.copy()
     config = {}
     if dirname is not None:
         config_file = path.join(dirname, filename)
         config['__file__'] = config_file
         config['tags'] = tags
         with cd(dirname):
             # we promise to have the config dir as current dir while the
             # config file is executed
             try:
                 execfile_(filename, config)
             except SyntaxError as err:
                 raise ConfigError(CONFIG_SYNTAX_ERROR % err)
             except SystemExit:
                 raise ConfigError(CONFIG_EXIT_ERROR)
     # override extensions after loading the configuration (otherwise it's pointless...)
     if 'extensions' in overrides:
         if isinstance(overrides['extensions'], string_types):
             config['extensions'] = overrides.pop('extensions').split(',')
         else:
             config['extensions'] = overrides.pop('extensions')
     self._raw_config = config
     # these two must be preinitialized because extensions can add their
     # own config values
     self.setup = config.get('setup', None)
     self.extensions = config.get('extensions', [])
Ejemplo n.º 3
0
def setup_command(request, tempdir, rootdir):
    """
    Run `setup.py build_sphinx` with args and kwargs,
    pass it to the test and clean up properly.
    """
    if hasattr(request.node, 'get_closest_marker'):  # pytest-3.6.0 or newer
        marker = request.node.get_closest_marker('setup_command')
    else:
        marker = request.node.get_marker('setup_command')
    args = marker.args if marker else []

    pkgrootdir = tempdir / 'test-setup'
    (rootdir / 'test-setup').copytree(pkgrootdir)

    with cd(pkgrootdir):
        pythonpath = os.path.dirname(os.path.dirname(sphinx.__file__))
        if os.getenv('PYTHONPATH'):
            pythonpath = os.getenv('PYTHONPATH') + os.pathsep + pythonpath
        command = [sys.executable, 'setup.py', 'build_sphinx']
        command.extend(args)

        proc = subprocess.Popen(
            command,
            env=dict(os.environ, PYTHONPATH=pythonpath),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE)
        yield namedtuple('setup', 'pkgroot,proc')(pkgrootdir, proc)
Ejemplo n.º 4
0
 def build_latexpdfja(self):
     # type: () -> int
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         os.system('%s all-pdf-ja' % self.makecmd)
     return 0
Ejemplo n.º 5
0
def eval_config_file(filename, tags):
    # type: (unicode, Tags) -> Dict[unicode, Any]
    """Evaluate a config file."""
    namespace = {}  # type: Dict[unicode, Any]
    namespace['__file__'] = filename
    namespace['tags'] = tags

    with cd(path.dirname(filename)):
        # during executing config file, current dir is changed to ``confdir``.
        try:
            execfile_(filename, namespace)
        except SyntaxError as err:
            msg = __("There is a syntax error in your configuration file: %s")
            if PY3:
                msg += __("\nDid you change the syntax from 2.x to 3.x?")
            raise ConfigError(msg % err)
        except SystemExit:
            msg = __("The configuration file (or one of the modules it imports) "
                     "called sys.exit()")
            raise ConfigError(msg)
        except Exception:
            msg = __("There is a programmable error in your configuration file:\n\n%s")
            raise ConfigError(msg % traceback.format_exc())

    return namespace
Ejemplo n.º 6
0
 def build_info(self):
     # type: () -> int
     if self.run_generic_build('texinfo') > 0:
         return 1
     with cd(self.builddir_join('texinfo')):
         os.system('%s info' % self.makecmd)
     return 0
Ejemplo n.º 7
0
def compile_math(latex, builder):
    # type: (unicode, Builder) -> unicode
    """Compile LaTeX macros for math to DVI."""
    tempdir = ensure_tempdir(builder)
    filename = path.join(tempdir, 'math.tex')
    with codecs.open(filename, 'w', 'utf-8') as f:  # type: ignore
        f.write(latex)

    # build latex command; old versions of latex don't have the
    # --output-directory option, so we have to manually chdir to the
    # temp dir to run it.
    command = [builder.config.imgmath_latex, '--interaction=nonstopmode']
    # add custom args from the config file
    command.extend(builder.config.imgmath_latex_args)
    command.append('math.tex')

    with cd(tempdir):
        try:
            p = Popen(command, stdout=PIPE, stderr=PIPE)
        except OSError as err:
            if err.errno != ENOENT:   # No such file or directory
                raise
            logger.warning(__('LaTeX command %r cannot be run (needed for math '
                              'display), check the imgmath_latex setting'),
                           builder.config.imgmath_latex)
            raise InvokeError

    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise MathExtError('latex exited with error', stderr, stdout)

    return path.join(tempdir, 'math.dvi')
Ejemplo n.º 8
0
def build_latex_doc(app, status, warning, engine, docclass):
    app.config.latex_engine = engine
    app.config.latex_documents[0] = app.config.latex_documents[0][:4] + (docclass,)

    LaTeXTranslator.ignore_missing_images = True
    app.builder.build_all()

    # file from latex_additional_files
    assert (app.outdir / 'svgimg.svg').isfile()

    # now, try to run latex over it
    with cd(app.outdir):
        try:
            ensuredir(engine)
            p = Popen([engine, '--interaction=nonstopmode',
                       '-output-directory=%s' % engine, 'SphinxTests.tex'],
                      stdout=PIPE, stderr=PIPE)
        except OSError:  # most likely the latex executable was not found
            raise SkipTest
        else:
            stdout, stderr = p.communicate()
            if p.returncode != 0:
                print(stdout)
                print(stderr)
                assert False, '%s exited with return code %s' % (
                    engine, p.returncode)
Ejemplo n.º 9
0
 def build_latexpdfja(self):
     # type: () -> int
     if self.run_generic_build('latex') > 0:
         return 1
     try:
         with cd(self.builddir_join('latex')):
             return subprocess.call([self.makecmd, 'all-pdf-ja'])
     except OSError:
         print('Error: Failed to run: %s' % self.makecmd)
         return 1
Ejemplo n.º 10
0
 def build_info(self):
     # type: () -> int
     if self.run_generic_build('texinfo') > 0:
         return 1
     try:
         with cd(self.builddir_join('texinfo')):
             return subprocess.call([self.makecmd, 'info'])
     except OSError:
         print('Error: Failed to run: %s' % self.makecmd)
         return 1
Ejemplo n.º 11
0
def get_master_doc(conf_file):
    '''returns the master_doc' variable stored in the given config file'''
    if not os.path.isfile(conf_file):
        raise ValueError("Not conf.py file: '%s'" % conf_file)

    # execute conf file to get the master document
    # Copied from sphinx.util.pycompat.py
    _globals = {"__file__": conf_file}  # the namespace where toe xec stuff with six
    with cd(os.path.dirname(conf_file)):
        execfile_("conf.py", _globals)

    if 'master_doc' not in _globals:
        raise ValueError("'master_doc' undefined in '%s'" % conf_file)

    return _globals['master_doc']
Ejemplo n.º 12
0
    def build_latexpdf(self):
        # type: () -> int
        if self.run_generic_build('latex') > 0:
            return 1

        if sys.platform == 'win32':
            makecmd = os.environ.get('MAKE', 'make.bat')
        else:
            makecmd = self.makecmd
        try:
            with cd(self.builddir_join('latex')):
                return subprocess.call([makecmd, 'all-pdf'])
        except OSError:
            print('Error: Failed to run: %s' % makecmd)
            return 1
Ejemplo n.º 13
0
def compile_latex_document(app):
    # now, try to run latex over it
    with cd(app.outdir):
        try:
            ensuredir(app.config.latex_engine)
            p = Popen([app.config.latex_engine,
                       '--interaction=nonstopmode',
                       '-output-directory=%s' % app.config.latex_engine,
                       'SphinxTests.tex'],
                      stdout=PIPE, stderr=PIPE)
        except OSError:  # most likely the latex executable was not found
            raise SkipTest
        else:
            stdout, stderr = p.communicate()
            if p.returncode != 0:
                print(stdout)
                print(stderr)
                assert False, '%s exited with return code %s' % (
                    app.config.latex_engine, p.returncode)
Ejemplo n.º 14
0
    def __init__(self, dirname, filename, overrides, tags):
        # type: (unicode, unicode, Dict, Tags) -> None
        self.overrides = overrides
        self.values = Config.config_values.copy()
        config = {}  # type: Dict[unicode, Any]
        if dirname is not None:
            config_file = path.join(dirname, filename)
            config['__file__'] = config_file
            config['tags'] = tags
            with cd(dirname):
                # we promise to have the config dir as current dir while the
                # config file is executed
                try:
                    execfile_(filename, config)
                except SyntaxError as err:
                    raise ConfigError(CONFIG_SYNTAX_ERROR % err)
                except SystemExit:
                    raise ConfigError(CONFIG_EXIT_ERROR)
                except Exception:
                    raise ConfigError(CONFIG_ERROR % traceback.format_exc())

        self._raw_config = config
        # these two must be preinitialized because extensions can add their
        # own config values
        self.setup = config.get('setup', None)  # type: Callable

        if 'extensions' in overrides:
            if isinstance(overrides['extensions'], string_types):
                config['extensions'] = overrides.pop('extensions').split(',')
            else:
                config['extensions'] = overrides.pop('extensions')
        self.extensions = config.get('extensions', [])  # type: List[unicode]

        # correct values of copyright year that are not coherent with
        # the SOURCE_DATE_EPOCH environment variable (if set)
        # See https://reproducible-builds.org/specs/source-date-epoch/
        if getenv('SOURCE_DATE_EPOCH') is not None:
            for k in ('copyright', 'epub_copyright'):
                if k in config:
                    config[k] = copyright_year_re.sub(r'\g<1>%s' % format_date('%Y'),
                                                      config[k])
Ejemplo n.º 15
0
def setup_command(request, tempdir):
    """
    Run `setup.py build_sphinx` with args and kwargs,
    pass it to the test and clean up properly.
    """
    marker = request.node.get_marker('setup_command')
    args = marker.args if marker else []

    pkgrootdir = tempdir / 'root'
    root.copytree(pkgrootdir)

    with cd(pkgrootdir):
        pythonpath = os.path.dirname(os.path.dirname(sphinx.__file__))
        if os.getenv('PYTHONPATH'):
            pythonpath = os.getenv('PYTHONPATH') + os.pathsep + pythonpath
        command = [sys.executable, 'setup.py', 'build_sphinx']
        command.extend(args)

        proc = subprocess.Popen(command,
                                env=dict(os.environ, PYTHONPATH=pythonpath),
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        yield namedtuple('setup', 'pkgroot,proc')(pkgrootdir, proc)
Ejemplo n.º 16
0
    def __init__(self, dirname, filename, overrides, tags):
        self.overrides = overrides
        self.values = Config.config_values.copy()
        config = {}
        if 'extensions' in overrides:  # XXX do we need this?
            if isinstance(overrides['extensions'], string_types):
                config['extensions'] = overrides.pop('extensions').split(',')
            else:
                config['extensions'] = overrides.pop('extensions')
        if dirname is not None:
            config_file = path.join(dirname, filename)
            config['__file__'] = config_file
            config['tags'] = tags
            with cd(dirname):
                # we promise to have the config dir as current dir while the
                # config file is executed
                try:
                    execfile_(filename, config)
                except SyntaxError as err:
                    raise ConfigError(CONFIG_SYNTAX_ERROR % err)
                except SystemExit:
                    raise ConfigError(CONFIG_EXIT_ERROR)

        self._raw_config = config
        # these two must be preinitialized because extensions can add their
        # own config values
        self.setup = config.get('setup', None)
        self.extensions = config.get('extensions', [])

        # correct values of copyright year that are not coherent with
        # the SOURCE_DATE_EPOCH environment variable (if set)
        # See https://reproducible-builds.org/specs/source-date-epoch/
        if getenv('SOURCE_DATE_EPOCH') is not None:
            for k in ('copyright', 'epub_copyright'):
                if k in config:
                    config[k] = copyright_year_re.sub(
                        '\g<1>%s' % format_date('%Y'), config[k])
Ejemplo n.º 17
0
def test_msgfmt(app):
    app.builder.build_all()
    (app.outdir / 'en' / 'LC_MESSAGES').makedirs()
    with cd(app.outdir):
        try:
            p = Popen(['msginit', '--no-translator', '-i', 'markup.pot',
                       '--locale', 'en_US'],
                      stdout=PIPE, stderr=PIPE)
        except OSError:
            pytest.skip()  # most likely msginit was not found
        else:
            stdout, stderr = p.communicate()
            if p.returncode != 0:
                print(stdout)
                print(stderr)
                assert False, 'msginit exited with return code %s' % \
                    p.returncode
        assert (app.outdir / 'en_US.po').isfile(), 'msginit failed'
        try:
            p = Popen(['msgfmt', 'en_US.po', '-o',
                       os.path.join('en', 'LC_MESSAGES', 'test_root.mo')],
                      stdout=PIPE, stderr=PIPE)
        except OSError:
            pytest.skip()  # most likely msgfmt was not found
        else:
            stdout, stderr = p.communicate()
            if p.returncode != 0:
                print(stdout)
                print(stderr)
                assert False, 'msgfmt exited with return code %s' % \
                    p.returncode
        mo = app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo'
        assert mo.isfile(), 'msgfmt failed'

    _ = gettext.translation('test_root', app.outdir, languages=['en']).gettext
    assert _("Testing various markup") == u"Testing various markup"
Ejemplo n.º 18
0
def test_msgfmt(app):
    app.builder.build_all()
    (app.outdir / 'en' / 'LC_MESSAGES').makedirs()
    with cd(app.outdir):
        try:
            p = Popen(['msginit', '--no-translator', '-i', 'markup.pot',
                       '--locale', 'en_US'],
                      stdout=PIPE, stderr=PIPE)
        except OSError:
            pytest.skip()  # most likely msginit was not found
        else:
            stdout, stderr = p.communicate()
            if p.returncode != 0:
                print(stdout)
                print(stderr)
                assert False, 'msginit exited with return code %s' % \
                    p.returncode
        assert (app.outdir / 'en_US.po').isfile(), 'msginit failed'
        try:
            p = Popen(['msgfmt', 'en_US.po', '-o',
                       os.path.join('en', 'LC_MESSAGES', 'test_root.mo')],
                      stdout=PIPE, stderr=PIPE)
        except OSError:
            pytest.skip()  # most likely msgfmt was not found
        else:
            stdout, stderr = p.communicate()
            if p.returncode != 0:
                print(stdout)
                print(stderr)
                assert False, 'msgfmt exited with return code %s' % \
                    p.returncode
        mo = app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo'
        assert mo.isfile(), 'msgfmt failed'

    _ = gettext.translation('test_root', app.outdir, languages=['en']).gettext
    assert _("Testing various markup") == u"Testing various markup"
Ejemplo n.º 19
0
    def __init__(self, dirname, filename, overrides, tags):
        self.overrides = overrides
        self.values = Config.config_values.copy()
        config = {}
        if "extensions" in overrides:  # XXX do we need this?
            if isinstance(overrides["extensions"], string_types):
                config["extensions"] = overrides.pop("extensions").split(",")
            else:
                config["extensions"] = overrides.pop("extensions")
        if dirname is not None:
            config_file = path.join(dirname, filename)
            config["__file__"] = config_file
            config["tags"] = tags
            with cd(dirname):
                # we promise to have the config dir as current dir while the
                # config file is executed
                try:
                    execfile_(filename, config)
                except SyntaxError as err:
                    raise ConfigError(CONFIG_SYNTAX_ERROR % err)
                except SystemExit:
                    raise ConfigError(CONFIG_EXIT_ERROR)

        self._raw_config = config
        # these two must be preinitialized because extensions can add their
        # own config values
        self.setup = config.get("setup", None)
        self.extensions = config.get("extensions", [])

        # correct values of copyright year that are not coherent with
        # the SOURCE_DATE_EPOCH environment variable (if set)
        # See https://reproducible-builds.org/specs/source-date-epoch/
        if getenv("SOURCE_DATE_EPOCH") is not None:
            for k in ("copyright", "epub_copyright"):
                if k in config:
                    config[k] = copyright_year_re.sub("\g<1>%s" % format_date("%Y"), config[k])
Ejemplo n.º 20
0
def eval_config_file(filename, tags):
    # type: (unicode, Tags) -> Dict[unicode, Any]
    """Evaluate a config file."""
    namespace = {}  # type: Dict[unicode, Any]
    namespace['__file__'] = filename
    namespace['tags'] = tags

    with cd(path.dirname(filename)):
        # during executing config file, current dir is changed to ``confdir``.
        try:
            execfile_(filename, namespace)
        except SyntaxError as err:
            msg = __("There is a syntax error in your configuration file: %s\n"
                     "Did you change the syntax from 2.x to 3.x?")
            raise ConfigError(msg % err)
        except SystemExit:
            msg = __("The configuration file (or one of the modules it imports) "
                     "called sys.exit()")
            raise ConfigError(msg)
        except Exception:
            msg = __("There is a programmable error in your configuration file:\n\n%s")
            raise ConfigError(msg % traceback.format_exc())

    return namespace
Ejemplo n.º 21
0
def test_msgfmt(app):
    app.builder.build_all()
    (app.outdir / 'en' / 'LC_MESSAGES').makedirs()
    with cd(app.outdir):
        try:
            args = [
                'msginit', '--no-translator', '-i', 'markup.pot', '--locale',
                'en_US'
            ]
            subprocess.run(args, stdout=PIPE, stderr=PIPE, check=True)
        except OSError:
            pytest.skip()  # most likely msginit was not found
        except CalledProcessError as exc:
            print(exc.stdout)
            print(exc.stderr)
            assert False, 'msginit exited with return code %s' % exc.returncode

        assert (app.outdir / 'en_US.po').isfile(), 'msginit failed'
        try:
            args = [
                'msgfmt', 'en_US.po', '-o',
                os.path.join('en', 'LC_MESSAGES', 'test_root.mo')
            ]
            subprocess.run(args, stdout=PIPE, stderr=PIPE, check=True)
        except OSError:
            pytest.skip()  # most likely msgfmt was not found
        except CalledProcessError as exc:
            print(exc.stdout)
            print(exc.stderr)
            assert False, 'msgfmt exited with return code %s' % exc.returncode

        mo = app.outdir / 'en' / 'LC_MESSAGES' / 'test_root.mo'
        assert mo.isfile(), 'msgfmt failed'

    _ = gettext.translation('test_root', app.outdir, languages=['en']).gettext
    assert _("Testing various markup") == "Testing various markup"
Ejemplo n.º 22
0
def compile_latex_document(app):
    # now, try to run latex over it
    with cd(app.outdir):
        try:
            ensuredir(app.config.latex_engine)
            # keep a copy of latex file for this engine in case test fails
            copyfile('SphinxTests.tex',
                     app.config.latex_engine + '/SphinxTests.tex')
            p = Popen([
                app.config.latex_engine, '--interaction=nonstopmode',
                '-output-directory=%s' % app.config.latex_engine,
                'SphinxTests.tex'
            ],
                      stdout=PIPE,
                      stderr=PIPE)
        except OSError:  # most likely the latex executable was not found
            raise SkipTest
        else:
            stdout, stderr = p.communicate()
            if p.returncode != 0:
                print(stdout)
                print(stderr)
                assert False, '%s exited with return code %s' % (
                    app.config.latex_engine, p.returncode)
Ejemplo n.º 23
0
def build(path_book, path_output, config, toc, warningiserror, builder):
    """Convert your book's content to HTML or a PDF."""
    # Paths for our notebooks
    PATH_BOOK = Path(path_book).absolute()
    if not PATH_BOOK.is_dir():
        _error(f"Path to book isn't a directory: {PATH_BOOK}")

    # `book_config` is manual over-rides, `config` is the path to a _config.yml file
    book_config = {}

    # Choose sphinx builder
    builder_dict = {
        "html": "html",
        "linkcheck": "linkcheck",
        "pdfhtml": "singlehtml",
        "latex": "latex",
        "pdflatex": "latex",
    }
    if builder not in builder_dict.keys():
        allowed_keys = tuple(builder_dict.keys())
        _error(
            f"Value for --builder must be one of {allowed_keys}. Got '{builder}'"
        )
    sphinx_builder = builder_dict[builder]

    # Table of contents
    if toc is None:
        if PATH_BOOK.joinpath("_toc.yml").exists():
            toc = PATH_BOOK.joinpath("_toc.yml")
        else:
            _error("Couldn't find a Table of Contents file. To auto-generate "
                   f"one, run\n\n\tjupyter-book toc {path_book}")
    book_config["globaltoc_path"] = str(toc)

    # Configuration file
    path_config = config
    if path_config is None:
        # Check if there's a `_config.yml` file in the source directory
        if PATH_BOOK.joinpath("_config.yml").exists():
            path_config = str(PATH_BOOK.joinpath("_config.yml"))

    if path_config:
        if not Path(path_config).exists():
            raise ValueError(
                f"Config file path given, but not found: {path_config}")

    # Builder-specific overrides
    if builder == "pdfhtml":
        book_config["html_theme_options"] = {"single_page": True}

    BUILD_PATH = path_output if path_output is not None else PATH_BOOK
    BUILD_PATH = Path(BUILD_PATH).joinpath("_build")
    if builder in ["html", "pdfhtml", "linkcheck"]:
        OUTPUT_PATH = BUILD_PATH.joinpath("html")
    elif builder in ["latex", "pdflatex"]:
        OUTPUT_PATH = BUILD_PATH.joinpath("latex")

    # Now call the Sphinx commands to build
    exc = build_sphinx(
        PATH_BOOK,
        OUTPUT_PATH,
        noconfig=True,
        path_config=path_config,
        confoverrides=book_config,
        builder=sphinx_builder,
        warningiserror=warningiserror,
    )

    if exc:
        if builder == "linkcheck":
            _error(
                "The link checker either didn't finish or found broken links.\n"
                "See the report above.")
        else:
            _error("There was an error in building your book. "
                   "Look above for the error message.")
    else:
        # Builder-specific options
        if builder == "html":
            path_output_rel = Path(op.relpath(OUTPUT_PATH, Path()))
            path_index = path_output_rel.joinpath("index.html")
            _message_box(f"""\
            Finished generating HTML for book.

            Your book's HTML pages are here:
                {path_output_rel}{os.sep}

            You can look at your book by opening this file in a browser:
                {path_index}

            Or paste this line directly into your browser bar:
                file://{path_index.resolve()}\
            """)
        if builder == "linkcheck":
            _message_box(
                "All links in your book are valid. See above for details.")
        if builder == "pdfhtml":
            print("Finished generating HTML for book...")
            print("Converting book HTML into PDF...")
            path_pdf_output = OUTPUT_PATH.parent.joinpath("pdf")
            path_pdf_output.mkdir(exist_ok=True)
            path_pdf_output = path_pdf_output.joinpath("book.pdf")
            html_to_pdf(OUTPUT_PATH.joinpath("index.html"), path_pdf_output)
            path_pdf_output_rel = Path(op.relpath(path_pdf_output, Path()))
            _message_box(f"""\
            Finished generating PDF via HTML for book. Your PDF is here:

                {path_pdf_output_rel}\
            """)
        if builder == "pdflatex":
            print("Finished generating latex for book...")
            print("Converting book latex into PDF...")
            # Convert to PDF via tex and template built Makefile and make.bat
            if sys.platform == "win32":
                makecmd = os.environ.get("MAKE", "make.bat")
            else:
                makecmd = os.environ.get("MAKE", "make")
            try:
                with cd(OUTPUT_PATH):
                    output = subprocess.run([makecmd, "all-pdf"])
                    if output.returncode != 0:
                        _error("Error: Failed to build pdf")
                        return output.returncode
                _message_box(f"""\
                A PDF of your book can be found at:

                    {OUTPUT_PATH}
                """)
            except OSError:
                _error("Error: Failed to run: %s" % makecmd)
                return 1
Ejemplo n.º 24
0
def test_autogen(rootdir, tempdir):
    with cd(rootdir / 'test-templating'):
        args = ['-o', tempdir, '-t', '.', 'autosummary_templating.txt']
        autogen_main(args)
        assert (tempdir / 'sphinx.application.TemplateBridge.rst').exists()
Ejemplo n.º 25
0
 def build_info(self):
     # type: () -> int
     if self.run_generic_build('texinfo') > 0:
         return 1
     with cd(self.builddir_join('texinfo')):
         return subprocess.call([self.makecmd, 'info'])
Ejemplo n.º 26
0
 def build_info(self):
     if self.run_generic_build('texinfo') > 0:
         return 1
     with cd(self.builddir_join('texinfo')):
         os.system('make info')
Ejemplo n.º 27
0
 def build_latexpdf(self):
     # type: () -> int
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         return subprocess.call([self.makecmd, 'all-pdf'])
Ejemplo n.º 28
0
 def build_latexpdf(self):
     # type: () -> int
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         os.system('make all-pdf')
Ejemplo n.º 29
0
from sphinx.builders.html import StandaloneHTMLBuilder

_orig_setup = None


#
# import symbols from original conf file manually
#
import imp
with open(conffile, 'r') as config_file:
    from sphinx.util.osutil import cd
    mod = imp.new_module("target_conf")
    mod.__file__ = conffile

    with cd(os.path.dirname(conffile)):
        exec(config_file, mod.__dict__)

    sys.modules['target_conf'] = mod
    G = globals()
    for (k,v) in mod.__dict__.items():
        if k not in G:
            G[k] = v
        if k == "setup":
            G["_orig_setup"] = v


class GollumBuilder(StandaloneHTMLBuilder):
    name = "gollum"
    theme = "gollum"
Ejemplo n.º 30
0
def main(argv=None):

    if argv is None:
        argv = sys.argv

    print("CGATReport: version %s started" % str("$Id$"))
    t = time.time()

    parser = optparse.OptionParser(version="%prog version: $Id$",
                                   usage=globals()["__doc__"])

    parser.add_option("-j", "-a", "--num-jobs", dest="num_jobs", type="int",
                      help="number of parallel jobs to run [default=%default]")

    parser.add_option("-v", "--verbose", dest="loglevel", type="int",
                      help="loglevel. The higher, the more output "
                      "[default=%default]")

    parser.set_defaults(num_jobs=2,
                        loglevel=10,)

    parser.disable_interspersed_args()

    (options, args) = parser.parse_args()

    assert args[0].endswith(
        "sphinx-build"), "command line should contain sphinx-build"

    sphinx_parser = optparse.OptionParser(
        version="%prog version: $Id$",
        usage=globals()["__doc__"])

    sphinx_parser.add_option("-b", type="string")
    sphinx_parser.add_option("-a")
    sphinx_parser.add_option("-E")
    sphinx_parser.add_option("-t", type="string")
    sphinx_parser.add_option("-d", type="string")
    sphinx_parser.add_option("-c", dest="confdir", type="string")
    sphinx_parser.add_option("-C")
    sphinx_parser.add_option("-D", type="string")
    sphinx_parser.add_option("-A", type="string")
    sphinx_parser.add_option("-n")
    sphinx_parser.add_option("-Q")
    sphinx_parser.add_option("-q")
    sphinx_parser.add_option("-w", type="string")
    sphinx_parser.add_option("-W")
    sphinx_parser.add_option("-P")
    sphinx_parser.add_option("-j", dest="num_jobs", type="int")

    sphinx_parser.set_defaults(
        confdir=None)

    (sphinx_options, sphinx_args) = sphinx_parser.parse_args(args[1:])

    sourcedir = sphinx_args[0]
    # local conf.py overrides anything
    if os.path.exists("conf.py"):
        sphinx_options.confdir = "."
    elif sphinx_options.confdir is None:
        sphinx_options.confdir = sourcedir

    # import conf.py for source_suffix
    config_file = os.path.join(sphinx_options.confdir, "conf.py")
    if not os.path.exists(config_file):
        raise IOError("could not find {}".format(config_file))

    config = {"__file__": config_file}
    with cd(sphinx_options.confdir):
        exec(compile(open(os.path.join(config_file)).read(),
                     "conf.py", 'exec'), config)

    rst_files = getDirectives(options, args, sourcedir)

    cleanTrackers(rst_files, options, args)

    buildPlots(rst_files, options, args, sourcedir)

    buildDocument(options, args)

    print("CGATReport: finished in %i seconds" % (time.time() - t))

    debug("build.py: profile: finished: %i seconds" % (time.time() - t))
Ejemplo n.º 31
0
 def build_info(self):
     if self.run_generic_build('texinfo') > 0:
         return 1
     with cd(self.builddir_join('texinfo')):
         os.system('make info')
Ejemplo n.º 32
0
 def build_latexpdfja(self):
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         os.system('make all-pdf-ja')
Ejemplo n.º 33
0
 def build_xelatexpdf(self):
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         os.system('make PDFLATEX=xelatex all-pdf')
Ejemplo n.º 34
0
 def build_latexpdf(self):
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         os.system('%s all-pdf' % self.makecmd)
Ejemplo n.º 35
0
def build(path_book, path_output, config, toc, warningiserror, builder):
    """Convert your book's content to HTML or a PDF."""
    # Paths for our notebooks
    PATH_BOOK = Path(path_book).absolute()
    if not PATH_BOOK.is_dir():
        _error(f"Path to book isn't a directory: {PATH_BOOK}")

    book_config = {}
    builder_dict = {
        "html": "html",
        "linkcheck": "linkcheck",
        "pdfhtml": "singlehtml",
        "latex": "latex",
        "pdflatex": "latex",
    }
    if builder not in builder_dict.keys():
        allowed_keys = tuple(builder_dict.keys())
        _error(
            f"Value for --builder must be one of {allowed_keys}. Got '{builder}'"
        )
    sphinx_builder = builder_dict[builder]

    # Table of contents
    if toc is None:
        if PATH_BOOK.joinpath("_toc.yml").exists():
            toc = PATH_BOOK.joinpath("_toc.yml")
        else:
            _error("Couldn't find a Table of Contents file. To auto-generate "
                   f"one, run\n\n\tjupyter-book toc {path_book}")
    book_config["globaltoc_path"] = str(toc)

    # Configuration file
    if config is None:
        if PATH_BOOK.joinpath("_config.yml").exists():
            config = PATH_BOOK.joinpath("_config.yml")

    extra_extensions = None
    if config is not None:
        book_config["yaml_config_path"] = str(config)
        config_yaml = yaml.safe_load(config.read_text())
        # Pop the extra extensions since we need to append, not replace
        extra_extensions = config_yaml.pop("sphinx",
                                           {}).get("extra_extensions")
        # Support Top Level config Passthrough
        # https://www.sphinx-doc.org/en/latest/usage/configuration.html#project-information
        sphinx_options = ["project", "author", "copyright"]
        for option in sphinx_options:
            if option in config_yaml.keys():
                book_config[option] = config_yaml[option]

    # Builder-specific overrides
    latex_config = None
    if builder == "pdfhtml":
        book_config["html_theme_options"] = {"single_page": True}
    if builder == "pdflatex":
        if "latex" in config_yaml.keys():
            latex_config = config_yaml.pop("latex")
        if "title" in config_yaml.keys():
            # Note: a latex_documents specified title takes precendence
            # over a top level title
            if (latex_config is not None
                    and "title" not in latex_config["latex_documents"].keys()):
                latex_config["latex_documents"]["title"] = config_yaml["title"]
            else:
                latex_config = {
                    "latex_documents": {
                        "title": config_yaml["title"]
                    }
                }

    BUILD_PATH = path_output if path_output is not None else PATH_BOOK
    BUILD_PATH = Path(BUILD_PATH).joinpath("_build")
    if builder in ["html", "pdfhtml", "linkcheck"]:
        OUTPUT_PATH = BUILD_PATH.joinpath("html")
    elif builder in ["latex", "pdflatex"]:
        OUTPUT_PATH = BUILD_PATH.joinpath("latex")

    # Now call the Sphinx commands to build
    exc = build_sphinx(
        PATH_BOOK,
        OUTPUT_PATH,
        noconfig=True,
        confoverrides=book_config,
        latexoverrides=latex_config,
        builder=sphinx_builder,
        warningiserror=warningiserror,
        extra_extensions=extra_extensions,
    )

    if exc:
        if builder == "linkcheck":
            _error(
                "The link checker either didn't finish or found broken links.\n"
                "See the report above.")
        else:
            _error("There was an error in building your book. "
                   "Look above for the error message.")
    else:
        # Builder-specific options
        if builder == "html":
            path_output_rel = Path(op.relpath(OUTPUT_PATH, Path()))
            path_index = path_output_rel.joinpath("index.html")
            _message_box(f"""\
            Finished generating HTML for book.

            Your book's HTML pages are here:
                {path_output_rel}{os.sep}

            You can look at your book by opening this file in a browser:
                {path_index}

            Or paste this line directly into your browser bar:
                file://{path_index.resolve()}\
            """)
        if builder == "linkcheck":
            _message_box(
                "All links in your book are valid. See above for details.")
        if builder == "pdfhtml":
            print("Finished generating HTML for book...")
            print("Converting book HTML into PDF...")
            path_pdf_output = OUTPUT_PATH.parent.joinpath("pdf")
            path_pdf_output.mkdir(exist_ok=True)
            path_pdf_output = path_pdf_output.joinpath("book.pdf")
            html_to_pdf(OUTPUT_PATH.joinpath("index.html"), path_pdf_output)
            path_pdf_output_rel = Path(op.relpath(path_pdf_output, Path()))
            _message_box(f"""\
            Finished generating PDF via HTML for book. Your PDF is here:

                {path_pdf_output_rel}\
            """)
        if builder == "pdflatex":
            print("Finished generating latex for book...")
            print("Converting book latex into PDF...")
            # Convert to PDF via tex and template built Makefile and make.bat
            if sys.platform == "win32":
                makecmd = os.environ.get("MAKE", "make.bat")
            else:
                makecmd = os.environ.get("MAKE", "make")
            try:
                with cd(OUTPUT_PATH):
                    output = subprocess.run([makecmd, "all-pdf"])
                    if output.returncode != 0:
                        _error("Error: Failed to build pdf")
                        return output.returncode
                _message_box(f"""\
                A PDF of your book can be found at:

                    {OUTPUT_PATH}
                """)
            except OSError:
                _error("Error: Failed to run: %s" % makecmd)
                return 1
Ejemplo n.º 36
0
def render_math(self, math):
    """Render the LaTeX math expression *math* using latex and dvipng or
    dvisvgm.

    Return the filename relative to the built document and the "depth",
    that is, the distance of image bottom and baseline in pixels, if the
    option to use preview_latex is switched on.

    Error handling may seem strange, but follows a pattern: if LaTeX or dvipng
    (dvisvgm) aren't available, only a warning is generated (since that enables
    people on machines without these programs to at least build the rest of the
    docs successfully).  If the programs are there, however, they may not fail
    since that indicates a problem in the math source.
    """
    image_format = self.builder.config.imgmath_image_format
    if image_format not in ("png", "svg"):
        raise MathExtError('imgmath_image_format must be either "png" or "svg"')

    font_size = self.builder.config.imgmath_font_size
    use_preview = self.builder.config.imgmath_use_preview
    latex = DOC_HEAD + self.builder.config.imgmath_latex_preamble
    latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % (font_size, int(round(font_size * 1.2)), math)

    shasum = "%s.%s" % (sha1(latex.encode("utf-8")).hexdigest(), image_format)
    relfn = posixpath.join(self.builder.imgpath, "math", shasum)
    outfn = path.join(self.builder.outdir, self.builder.imagedir, "math", shasum)
    if path.isfile(outfn):
        depth = read_png_depth(outfn)
        return relfn, depth

    # if latex or dvipng (dvisvgm) has failed once, don't bother to try again
    if hasattr(self.builder, "_imgmath_warned_latex") or hasattr(self.builder, "_imgmath_warned_image_translator"):
        return None, None

    # use only one tempdir per build -- the use of a directory is cleaner
    # than using temporary files, since we can clean up everything at once
    # just removing the whole directory (see cleanup_tempdir)
    if not hasattr(self.builder, "_imgmath_tempdir"):
        tempdir = self.builder._imgmath_tempdir = tempfile.mkdtemp()
    else:
        tempdir = self.builder._imgmath_tempdir

    tf = codecs.open(path.join(tempdir, "math.tex"), "w", "utf-8")
    tf.write(latex)
    tf.close()

    # build latex command; old versions of latex don't have the
    # --output-directory option, so we have to manually chdir to the
    # temp dir to run it.
    ltx_args = [self.builder.config.imgmath_latex, "--interaction=nonstopmode"]
    # add custom args from the config file
    ltx_args.extend(self.builder.config.imgmath_latex_args)
    ltx_args.append("math.tex")

    with cd(tempdir):
        try:
            p = Popen(ltx_args, stdout=PIPE, stderr=PIPE)
        except OSError as err:
            if err.errno != ENOENT:  # No such file or directory
                raise
            self.builder.warn(
                "LaTeX command %r cannot be run (needed for math "
                "display), check the imgmath_latex setting" % self.builder.config.imgmath_latex
            )
            self.builder._imgmath_warned_latex = True
            return None, None

    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise MathExtError("latex exited with error", stderr, stdout)

    ensuredir(path.dirname(outfn))
    if image_format == "png":
        image_translator = "dvipng"
        image_translator_executable = self.builder.config.imgmath_dvipng
        # use some standard dvipng arguments
        image_translator_args = [self.builder.config.imgmath_dvipng]
        image_translator_args += ["-o", outfn, "-T", "tight", "-z9"]
        # add custom ones from config value
        image_translator_args.extend(self.builder.config.imgmath_dvipng_args)
        if use_preview:
            image_translator_args.append("--depth")
    elif image_format == "svg":
        image_translator = "dvisvgm"
        image_translator_executable = self.builder.config.imgmath_dvisvgm
        # use some standard dvisvgm arguments
        image_translator_args = [self.builder.config.imgmath_dvisvgm]
        image_translator_args += ["-o", outfn]
        # add custom ones from config value
        image_translator_args.extend(self.builder.config.imgmath_dvisvgm_args)
        # last, the input file name
        image_translator_args.append(path.join(tempdir, "math.dvi"))
    else:
        raise MathExtError('imgmath_image_format must be either "png" or "svg"')

    # last, the input file name
    image_translator_args.append(path.join(tempdir, "math.dvi"))

    try:
        p = Popen(image_translator_args, stdout=PIPE, stderr=PIPE)
    except OSError as err:
        if err.errno != ENOENT:  # No such file or directory
            raise
        self.builder.warn(
            "%s command %r cannot be run (needed for math " "display), check the imgmath_%s setting" % image_translator,
            image_translator_executable,
            image_translator,
        )
        self.builder._imgmath_warned_image_translator = True
        return None, None

    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise MathExtError("%s exited with error", image_translator, stderr, stdout)
    depth = None
    if use_preview and image_format == "png":  # depth is only useful for png
        for line in stdout.splitlines():
            m = depth_re.match(line)
            if m:
                depth = int(m.group(1))
                write_png_depth(outfn, depth)
                break

    return relfn, depth
Ejemplo n.º 37
0
 def build_latexpdfja(self):
     # type: () -> int
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         os.system('%s all-pdf-ja' % self.makecmd)
Ejemplo n.º 38
0
def build(path_book, path_output, config, toc, warningiserror, builder):
    """Convert your book's content to HTML or a PDF."""
    # Paths for our notebooks
    PATH_BOOK = Path(path_book).absolute()

    # `book_config` is manual over-rides, `config` is the path to a _config.yml file
    book_config = {}

    # Table of contents
    # TODO Set TOC dynamically to default value and let Click handle this check
    if toc is None:
        toc = PATH_BOOK.joinpath("_toc.yml")
    else:
        toc = Path(toc)

    if not toc.exists():
        _error(
            "Couldn't find a Table of Contents file. To auto-generate "
            f"one, run\n\n\tjupyter-book toc {path_book}"
        )
    book_config["globaltoc_path"] = str(toc)

    # Configuration file
    path_config = config
    if path_config is None:
        # Check if there's a `_config.yml` file in the source directory
        if PATH_BOOK.joinpath("_config.yml").exists():
            path_config = str(PATH_BOOK.joinpath("_config.yml"))
    if path_config:
        if not Path(path_config).exists():
            raise ValueError(f"Config file path given, but not found: {path_config}")

    # Builder-specific overrides
    if builder == "pdfhtml":
        book_config["html_theme_options"] = {"single_page": True}

    # TODO Use click to set value of path_output dynamically based on path_book
    BUILD_PATH = path_output if path_output is not None else PATH_BOOK
    BUILD_PATH = Path(BUILD_PATH).joinpath("_build")
    if builder in ["html", "pdfhtml", "linkcheck"]:
        OUTPUT_PATH = BUILD_PATH.joinpath("html")
    elif builder in ["latex", "pdflatex"]:
        OUTPUT_PATH = BUILD_PATH.joinpath("latex")

    # Check whether the table of contents has changed. If so we rebuild all
    freshenv = False
    if toc and BUILD_PATH.joinpath(".doctrees").exists():
        toc_modified = toc.stat().st_mtime
        build_files = BUILD_PATH.rglob(".doctrees/*")
        build_modified = max([os.stat(ii).st_mtime for ii in build_files])

        # If the toc file has been modified after the build we need to force rebuild
        freshenv = toc_modified > build_modified

    # Now call the Sphinx commands to build
    exc = build_sphinx(
        PATH_BOOK,
        OUTPUT_PATH,
        noconfig=True,
        path_config=path_config,
        confoverrides=book_config,
        builder=BUILDER_OPTS[builder],
        warningiserror=warningiserror,
        freshenv=freshenv,
    )

    if exc:
        if builder == "linkcheck":
            _error(
                "The link checker either didn't finish or found broken links.\n"
                "See the report above."
            )
        else:
            _error(
                "There was an error in building your book. "
                "Look above for the error message."
            )
    else:
        # Builder-specific options
        if builder == "html":
            path_output_rel = Path(op.relpath(OUTPUT_PATH, Path()))
            path_index = path_output_rel.joinpath("index.html")
            _message_box(
                f"""\
            Finished generating HTML for book.

            Your book's HTML pages are here:
                {path_output_rel}{os.sep}

            You can look at your book by opening this file in a browser:
                {path_index}

            Or paste this line directly into your browser bar:
                file://{path_index.resolve()}\
            """
            )
        if builder == "linkcheck":
            _message_box("All links in your book are valid. See above for details.")
        if builder == "pdfhtml":
            print("Finished generating HTML for book...")
            print("Converting book HTML into PDF...")
            path_pdf_output = OUTPUT_PATH.parent.joinpath("pdf")
            path_pdf_output.mkdir(exist_ok=True)
            path_pdf_output = path_pdf_output.joinpath("book.pdf")
            html_to_pdf(OUTPUT_PATH.joinpath("index.html"), path_pdf_output)
            path_pdf_output_rel = Path(op.relpath(path_pdf_output, Path()))
            _message_box(
                f"""\
            Finished generating PDF via HTML for book. Your PDF is here:

                {path_pdf_output_rel}\
            """
            )
        if builder == "pdflatex":
            print("Finished generating latex for book...")
            print("Converting book latex into PDF...")
            # Convert to PDF via tex and template built Makefile and make.bat
            if sys.platform == "win32":
                makecmd = os.environ.get("MAKE", "make.bat")
            else:
                makecmd = os.environ.get("MAKE", "make")
            try:
                with cd(OUTPUT_PATH):
                    output = subprocess.run([makecmd, "all-pdf"])
                    if output.returncode != 0:
                        _error("Error: Failed to build pdf")
                        return output.returncode
                _message_box(
                    f"""\
                A PDF of your book can be found at:

                    {OUTPUT_PATH}
                """
                )
            except OSError:
                _error("Error: Failed to run: %s" % makecmd)
                return 1
Ejemplo n.º 39
0
 def build_latexpdf(self):
     # type: () -> int
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         os.system('make all-pdf')
Ejemplo n.º 40
0
 def build_info(self):
     if self.run_generic_build("texinfo") > 0:
         return 1
     with cd(self.builddir_join("texinfo")):
         os.system("make info")
Ejemplo n.º 41
0
 def build_info(self):
     # type: () -> int
     if self.run_generic_build('texinfo') > 0:
         return 1
     with cd(self.builddir_join('texinfo')):
         return subprocess.call([self.makecmd, 'info'])
Ejemplo n.º 42
0
 def build_latexpdfja(self):
     if self.run_generic_build("latex") > 0:
         return 1
     with cd(self.builddir_join("latex")):
         os.system("make all-pdf-ja")
Ejemplo n.º 43
0
 def build_latexpdfja(self):
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         os.system('make all-pdf-ja')
Ejemplo n.º 44
0
 def setup_class(cls):
     """Run Sphinx against the dir adjacent to the testcase."""
     cls.docs_dir = join(cls.this_dir(), 'source', 'docs')
     with cd(cls.docs_dir):
         if sphinx_main(['.', '-b', 'text', '-E', '_build']):
             raise RuntimeError('Sphinx build exploded.')
Ejemplo n.º 45
0
 def build_latexpdfja(self):
     # type: () -> int
     if self.run_generic_build('latex') > 0:
         return 1
     with cd(self.builddir_join('latex')):
         return subprocess.call([self.makecmd, 'all-pdf-ja'])
Ejemplo n.º 46
0
 def setup_class(cls):
     cls.docs_dir = join(dirname(__file__), 'source', 'docs')
     with cd(cls.docs_dir):
         sphinx_main(['dummy', '-b', 'text', '-E', '.', '_build'])
Ejemplo n.º 47
0
def render_math(self, math):
    """Render the LaTeX math expression *math* using latex and dvipng.

    Return the filename relative to the built document and the "depth",
    that is, the distance of image bottom and baseline in pixels, if the
    option to use preview_latex is switched on.

    Error handling may seem strange, but follows a pattern: if LaTeX or
    dvipng aren't available, only a warning is generated (since that enables
    people on machines without these programs to at least build the rest
    of the docs successfully).  If the programs are there, however, they
    may not fail since that indicates a problem in the math source.
    """
    use_preview = self.builder.config.pngmath_use_preview
    latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble
    latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math

    shasum = "%s.png" % sha1(latex.encode('utf-8')).hexdigest()
    relfn = posixpath.join(self.builder.imgpath, 'math', shasum)
    outfn = path.join(self.builder.outdir, self.builder.imagedir, 'math', shasum)
    if path.isfile(outfn):
        depth = read_png_depth(outfn)
        return relfn, depth

    # if latex or dvipng has failed once, don't bother to try again
    if hasattr(self.builder, '_mathpng_warned_latex') or \
       hasattr(self.builder, '_mathpng_warned_dvipng'):
        return None, None

    # use only one tempdir per build -- the use of a directory is cleaner
    # than using temporary files, since we can clean up everything at once
    # just removing the whole directory (see cleanup_tempdir)
    if not hasattr(self.builder, '_mathpng_tempdir'):
        tempdir = self.builder._mathpng_tempdir = tempfile.mkdtemp()
    else:
        tempdir = self.builder._mathpng_tempdir

    tf = codecs.open(path.join(tempdir, 'math.tex'), 'w', 'utf-8')
    tf.write(latex)
    tf.close()

    # build latex command; old versions of latex don't have the
    # --output-directory option, so we have to manually chdir to the
    # temp dir to run it.
    ltx_args = [self.builder.config.pngmath_latex, '--interaction=nonstopmode']
    # add custom args from the config file
    ltx_args.extend(self.builder.config.pngmath_latex_args)
    ltx_args.append('math.tex')

    with cd(tempdir):
        try:
            p = Popen(ltx_args, stdout=PIPE, stderr=PIPE)
        except OSError as err:
            if err.errno != ENOENT:   # No such file or directory
                raise
            self.builder.warn('LaTeX command %r cannot be run (needed for math '
                              'display), check the pngmath_latex setting' %
                              self.builder.config.pngmath_latex)
            self.builder._mathpng_warned_latex = True
            return None, None

    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise MathExtError('latex exited with error', stderr, stdout)

    ensuredir(path.dirname(outfn))
    # use some standard dvipng arguments
    dvipng_args = [self.builder.config.pngmath_dvipng]
    dvipng_args += ['-o', outfn, '-T', 'tight', '-z9']
    # add custom ones from config value
    dvipng_args.extend(self.builder.config.pngmath_dvipng_args)
    if use_preview:
        dvipng_args.append('--depth')
    # last, the input file name
    dvipng_args.append(path.join(tempdir, 'math.dvi'))
    try:
        p = Popen(dvipng_args, stdout=PIPE, stderr=PIPE)
    except OSError as err:
        if err.errno != ENOENT:   # No such file or directory
            raise
        self.builder.warn('dvipng command %r cannot be run (needed for math '
                          'display), check the pngmath_dvipng setting' %
                          self.builder.config.pngmath_dvipng)
        self.builder._mathpng_warned_dvipng = True
        return None, None
    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise MathExtError('dvipng exited with error', stderr, stdout)
    depth = None
    if use_preview:
        for line in stdout.splitlines():
            m = depth_re.match(line)
            if m:
                depth = int(m.group(1))
                write_png_depth(outfn, depth)
                break

    return relfn, depth
Ejemplo n.º 48
0
    GAME_DIR = os.environ.get("EVGAMEDIR")

    if not (EV_ROOT and GAME_DIR):
        err = (
            "The EVDIR and EVGAMEDIR environment variables must be set to "
            "the absolute paths to the evennia/ repo and an initialized "
            "evennia gamedir respectively."
        )
        raise RuntimeError(err)

    print("Evennia root: {}, Game dir: {}".format(EV_ROOT, GAME_DIR))

    sys.path.insert(1, EV_ROOT)
    sys.path.insert(1, GAME_DIR)

    with cd(GAME_DIR):
        # set up Evennia so its sources can be parsed
        os.environ["DJANGO_SETTINGS_MODULE"] = "server.conf.settings"

        import django  # noqa

        django.setup()

        import evennia  # noqa

        evennia._init()

    from evennia.utils.ansi import strip_raw_ansi as ansi_clean


if _no_autodoc:
Ejemplo n.º 49
0
def render_math(self, math):
    """Render the LaTeX math expression *math* using latex and dvipng or
    dvisvgm.

    Return the filename relative to the built document and the "depth",
    that is, the distance of image bottom and baseline in pixels, if the
    option to use preview_latex is switched on.

    Error handling may seem strange, but follows a pattern: if LaTeX or dvipng
    (dvisvgm) aren't available, only a warning is generated (since that enables
    people on machines without these programs to at least build the rest of the
    docs successfully).  If the programs are there, however, they may not fail
    since that indicates a problem in the math source.
    """
    image_format = self.builder.config.imgmath_image_format
    if image_format not in ('png', 'svg'):
        raise MathExtError(
            'imgmath_image_format must be either "png" or "svg"')

    font_size = self.builder.config.imgmath_font_size
    use_preview = self.builder.config.imgmath_use_preview
    latex = DOC_HEAD + self.builder.config.imgmath_latex_preamble
    latex += (use_preview and DOC_BODY_PREVIEW
              or DOC_BODY) % (font_size, int(round(font_size * 1.2)), math)

    shasum = "%s.%s" % (sha1(latex.encode('utf-8')).hexdigest(), image_format)
    relfn = posixpath.join(self.builder.imgpath, 'math', shasum)
    outfn = path.join(self.builder.outdir, self.builder.imagedir, 'math',
                      shasum)
    if path.isfile(outfn):
        depth = read_png_depth(outfn)
        return relfn, depth

    # if latex or dvipng (dvisvgm) has failed once, don't bother to try again
    if hasattr(self.builder, '_imgmath_warned_latex') or \
       hasattr(self.builder, '_imgmath_warned_image_translator'):
        return None, None

    # use only one tempdir per build -- the use of a directory is cleaner
    # than using temporary files, since we can clean up everything at once
    # just removing the whole directory (see cleanup_tempdir)
    if not hasattr(self.builder, '_imgmath_tempdir'):
        tempdir = self.builder._imgmath_tempdir = tempfile.mkdtemp()
    else:
        tempdir = self.builder._imgmath_tempdir

    tf = codecs.open(path.join(tempdir, 'math.tex'), 'w', 'utf-8')
    tf.write(latex)
    tf.close()

    # build latex command; old versions of latex don't have the
    # --output-directory option, so we have to manually chdir to the
    # temp dir to run it.
    ltx_args = [self.builder.config.imgmath_latex, '--interaction=nonstopmode']
    # add custom args from the config file
    ltx_args.extend(self.builder.config.imgmath_latex_args)
    ltx_args.append('math.tex')

    with cd(tempdir):
        try:
            p = Popen(ltx_args, stdout=PIPE, stderr=PIPE)
        except OSError as err:
            if err.errno != ENOENT:  # No such file or directory
                raise
            self.builder.warn(
                'LaTeX command %r cannot be run (needed for math '
                'display), check the imgmath_latex setting' %
                self.builder.config.imgmath_latex)
            self.builder._imgmath_warned_latex = True
            return None, None

    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise MathExtError('latex exited with error', stderr, stdout)

    ensuredir(path.dirname(outfn))
    if image_format == 'png':
        image_translator = 'dvipng'
        image_translator_executable = self.builder.config.imgmath_dvipng
        # use some standard dvipng arguments
        image_translator_args = [self.builder.config.imgmath_dvipng]
        image_translator_args += ['-o', outfn, '-T', 'tight', '-z9']
        # add custom ones from config value
        image_translator_args.extend(self.builder.config.imgmath_dvipng_args)
        if use_preview:
            image_translator_args.append('--depth')
    elif image_format == 'svg':
        image_translator = 'dvisvgm'
        image_translator_executable = self.builder.config.imgmath_dvisvgm
        # use some standard dvisvgm arguments
        image_translator_args = [self.builder.config.imgmath_dvisvgm]
        image_translator_args += ['-o', outfn]
        # add custom ones from config value
        image_translator_args.extend(self.builder.config.imgmath_dvisvgm_args)
    else:
        raise MathExtError(
            'imgmath_image_format must be either "png" or "svg"')

    # last, the input file name
    image_translator_args.append(path.join(tempdir, 'math.dvi'))

    try:
        p = Popen(image_translator_args, stdout=PIPE, stderr=PIPE)
    except OSError as err:
        if err.errno != ENOENT:  # No such file or directory
            raise
        self.builder.warn(
            '%s command %r cannot be run (needed for math '
            'display), check the imgmath_%s setting' %
            (image_translator, image_translator_executable, image_translator))
        self.builder._imgmath_warned_image_translator = True
        return None, None

    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise MathExtError('%s exited with error' % image_translator, stderr,
                           stdout)
    depth = None
    if use_preview and image_format == 'png':  # depth is only useful for png
        for line in stdout.splitlines():
            m = depth_re.match(line)
            if m:
                depth = int(m.group(1))
                write_png_depth(outfn, depth)
                break

    return relfn, depth
Ejemplo n.º 50
0
def builder_specific_actions(exc,
                             builder,
                             output_path,
                             cmd_type,
                             page_name=None):
    if exc:
        _error(f"There was an error in building your {cmd_type}. "
               "Look above for the error message.")
    else:
        # Builder-specific options
        if builder == "html":
            path_output_rel = Path(op.relpath(output_path, Path()))
            if cmd_type == "page":
                path_page = path_output_rel.joinpath(f"{page_name}.html")
                # Write an index file if it doesn't exist so we get redirects
                path_index = path_output_rel.joinpath("index.html")
                if not path_index.exists():
                    path_index.write_text(
                        REDIRECT_TEXT.format(first_page=path_page.name))

                _message_box(
                    dedent(f"""
                        Page build finished.
                            Your page folder is: {path_page.parent}{os.sep}
                            Open your page at: {path_page}
                        """))

            elif cmd_type == "book":
                path_output_rel = Path(op.relpath(output_path, Path()))
                path_index = path_output_rel.joinpath("index.html")
                _message_box(f"""\
                Finished generating HTML for {cmd_type}.
                Your book's HTML pages are here:
                    {path_output_rel}{os.sep}
                You can look at your book by opening this file in a browser:
                    {path_index}
                Or paste this line directly into your browser bar:
                    file://{path_index.resolve()}\
                """)
        if builder == "pdfhtml":
            print(f"Finished generating HTML for {cmd_type}...")
            print(f"Converting {cmd_type} HTML into PDF...")
            path_pdf_output = output_path.parent.joinpath("pdf")
            path_pdf_output.mkdir(exist_ok=True)
            if cmd_type == "book":
                path_pdf_output = path_pdf_output.joinpath("book.pdf")
                html_to_pdf(output_path.joinpath("index.html"),
                            path_pdf_output)
            elif cmd_type == "page":
                path_pdf_output = path_pdf_output.joinpath(page_name + ".pdf")
                html_to_pdf(output_path.joinpath(page_name + ".html"),
                            path_pdf_output)
            path_pdf_output_rel = Path(op.relpath(path_pdf_output, Path()))
            _message_box(f"""\
            Finished generating PDF via HTML for {cmd_type}. Your PDF is here:
                {path_pdf_output_rel}\
            """)
        if builder == "pdflatex":
            print(f"Finished generating latex for {cmd_type}...")
            print(f"Converting {cmd_type} latex into PDF...")
            # Convert to PDF via tex and template built Makefile and make.bat
            if sys.platform == "win32":
                makecmd = os.environ.get("MAKE", "make.bat")
            else:
                makecmd = os.environ.get("MAKE", "make")
            try:
                with cd(output_path):
                    output = subprocess.run([makecmd, "all-pdf"])
                    if output.returncode != 0:
                        _error("Error: Failed to build pdf")
                        return output.returncode
                _message_box(f"""\
                A PDF of your {cmd_type} can be found at:
                    {output_path}
                """)
            except OSError:
                _error("Error: Failed to run: %s" % makecmd)
                return 1
Ejemplo n.º 51
0
 def setup_class(cls):
     cls.docs_dir = join(dirname(__file__), 'source', 'docs')
     with cd(cls.docs_dir):
         if sphinx_main(['dummy', '-b', 'text', '-E', '.', '_build']):
             raise RuntimeError('Sphinx build exploded.')
Ejemplo n.º 52
0
    def handle(self):
        output_directory = Path(self.args.output_directory)

        # We simulate pybabel and sphinx-build commands. Variable names are chosen to match upstream code.

        # For sphinx-build, the code path is:
        #
        # * bin/sphinx-build calls main() in sphinx, which calls build_main(), which calls main() in sphinx.cmdline
        # * main() calls Sphinx(…).build(…) in sphinx.application

        # sphinx-build -E -q …
        kwargs = {
            'confoverrides': {
                'source_suffix': ['.rst', '.md'],
                'source_parsers': {
                    '.md': CommonMarkParser,
                },
            },
            'freshenv': True,
            'parallel': 1,
        }
        if not self.args.verbose:
            kwargs.update(status=None)

        # For pybabel, the code path is:
        #
        # * bin/pybabel calls main() in babel.messages.frontend
        # * main() calls CommandLineInterface().run(sys.argv)
        # * CommandLineInterface() calls extract_messages(), which:
        #   1. Reads the input path and method map from command-line options
        #   2. Instantiates a catalog
        #   3. Calls extract_from_dir() in babel.messages.extract to extract messages
        #   4. extract_from_dir() calls check_and_call_extract_file() to find the method in the method map
        #   5. check_and_call_extract_file() calls extract_from_file() to open a file for extraction
        #   6. extract_from_file() calls extract() to extract messages
        #   7. Adds the messages to the catalog
        #   8. Writes a POT file

        # 1. Reads the input path and method map from command-line options
        arguments = [
            # pybabel extract -F babel_ocds_codelist.cfg . -o $(POT_DIR)/$(DOMAIN_PREFIX)codelists.pot
            ('codelists.pot', [
                ('codelists/*.csv', extract_codelist),
            ]),
            # pybabel extract -F babel_ocds_schema.cfg . -o $(POT_DIR)/$(DOMAIN_PREFIX)schema.pot
            ('schema.pot', [
                ('*-schema.json', extract_schema),
                ('extension.json', extract_extension_metadata),
            ]),
        ]

        for version in self.versions():
            if not version.download_url:
                logger.warning('No Download URL for {}=={}'.format(
                    version.id, version.version))

            outdir = output_directory / version.id / version.version

            outdir.mkdir(parents=True, exist_ok=True)

            # See the `files` method of `ExtensionVersion` for similar code.
            response = requests.get(version.download_url, allow_redirects=True)
            response.raise_for_status()
            with closing(ZipFile(BytesIO(response.content))) as zipfile:
                names = zipfile.namelist()
                start = len(names[0])

                for output_file, method_map in arguments:
                    # 2. Instantiates a catalog
                    catalog = Catalog()

                    # 3. Calls extract_from_dir() in babel.messages.extract to extract messages
                    for name in names[1:]:
                        filename = name[start:]

                        # 4. extract_from_dir() calls check_and_call_extract_file()
                        for pattern, method in method_map:
                            if not pathmatch(pattern, filename):
                                continue

                            # 5. check_and_call_extract_file() calls extract_from_file()
                            with zipfile.open(name) as fileobj:
                                # 6. extract_from_file() calls extract() to extract messages
                                for lineno, message, comments, context in extract(
                                        method, fileobj):
                                    # 7. Adds the messages to the catalog
                                    catalog.add(message,
                                                None, [(filename, lineno)],
                                                auto_comments=comments,
                                                context=context)

                            break

                    # 8. Writes a POT file
                    if catalog:
                        with open(outdir / output_file, 'wb') as outfile:
                            write_po(outfile, catalog)

                with TemporaryDirectory() as srcdir:
                    for info in zipfile.infolist()[1:]:
                        filename = info.filename[start:]
                        if filename[-1] != '/' and filename.startswith(
                                'docs/') or filename == 'README.md':
                            info.filename = filename
                            zipfile.extract(info, srcdir)

                    with cd(srcdir):
                        # Eliminates a warning, without change to output.
                        with open('contents.rst', 'w') as f:
                            f.write(
                                '.. toctree::\n   :glob:\n\n   docs/*\n   README'
                            )

                        # sphinx-build -b gettext $(DOCS_DIR) $(POT_DIR)
                        app = Sphinx('.', None, '.', '.', 'gettext', **kwargs)
                        app.build(True)

                        # https://stackoverflow.com/questions/15408348
                        content = subprocess.run(['msgcat', *glob('*.pot')],
                                                 check=True,
                                                 stdout=subprocess.PIPE).stdout

                with open(outdir / 'docs.pot', 'wb') as f:
                    f.write(content)
Ejemplo n.º 53
0
# -- API/Autodoc ---------------------------------------------------------------
# automatic creation of API documentation. This requires a valid Evennia setup

_no_autodoc = os.environ.get("NOAUTODOC")

ansi_clean = None

if not _no_autodoc:
    # we must set up Evennia and its paths for autodocs to work

    EV_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

    sys.path.insert(1, EV_ROOT)

    with cd(EV_ROOT):
        # set up Evennia so its sources can be parsed
        os.environ["DJANGO_SETTINGS_MODULE"] = "evennia.settings_default"

        import django  # noqa

        django.setup()

        import evennia  # noqa

        evennia._init()

    from evennia.utils.ansi import strip_raw_ansi as ansi_clean

if _no_autodoc:
    exclude_patterns = ["api/*"]
Ejemplo n.º 54
0
 def build_info(self):
     # type: () -> int
     if self.run_generic_build('texinfo') > 0:
         return 1
     with cd(self.builddir_join('texinfo')):
         os.system('%s info' % self.makecmd)
Ejemplo n.º 55
0
def render_math(self, math):
    # type: (nodes.NodeVisitor, unicode) -> Tuple[unicode, int]
    """Render the LaTeX math expression *math* using latex and dvipng.

    Return the filename relative to the built document and the "depth",
    that is, the distance of image bottom and baseline in pixels, if the
    option to use preview_latex is switched on.

    Error handling may seem strange, but follows a pattern: if LaTeX or
    dvipng aren't available, only a warning is generated (since that enables
    people on machines without these programs to at least build the rest
    of the docs successfully).  If the programs are there, however, they
    may not fail since that indicates a problem in the math source.
    """
    use_preview = self.builder.config.pngmath_use_preview
    latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble
    latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math

    shasum = "%s.png" % sha1(latex.encode('utf-8')).hexdigest()
    relfn = posixpath.join(self.builder.imgpath, 'math', shasum)
    outfn = path.join(self.builder.outdir, self.builder.imagedir, 'math',
                      shasum)
    if path.isfile(outfn):
        depth = read_png_depth(outfn)
        return relfn, depth

    # if latex or dvipng has failed once, don't bother to try again
    if hasattr(self.builder, '_mathpng_warned_latex') or \
       hasattr(self.builder, '_mathpng_warned_dvipng'):
        return None, None

    # use only one tempdir per build -- the use of a directory is cleaner
    # than using temporary files, since we can clean up everything at once
    # just removing the whole directory (see cleanup_tempdir)
    if not hasattr(self.builder, '_mathpng_tempdir'):
        tempdir = self.builder._mathpng_tempdir = tempfile.mkdtemp()
    else:
        tempdir = self.builder._mathpng_tempdir

    with codecs.open(path.join(tempdir, 'math.tex'), 'w',
                     'utf-8') as tf:  # type: ignore
        tf.write(latex)

    # build latex command; old versions of latex don't have the
    # --output-directory option, so we have to manually chdir to the
    # temp dir to run it.
    ltx_args = [self.builder.config.pngmath_latex, '--interaction=nonstopmode']
    # add custom args from the config file
    ltx_args.extend(self.builder.config.pngmath_latex_args)
    ltx_args.append('math.tex')

    with cd(tempdir):
        try:
            p = Popen(ltx_args, stdout=PIPE, stderr=PIPE)
        except OSError as err:
            if err.errno != ENOENT:  # No such file or directory
                raise
            logger.warning(
                'LaTeX command %r cannot be run (needed for math '
                'display), check the pngmath_latex setting',
                self.builder.config.pngmath_latex)
            self.builder._mathpng_warned_latex = True
            return None, None

    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise MathExtError('latex exited with error', stderr, stdout)

    ensuredir(path.dirname(outfn))
    # use some standard dvipng arguments
    dvipng_args = [self.builder.config.pngmath_dvipng]
    dvipng_args += ['-o', outfn, '-T', 'tight', '-z9']
    # add custom ones from config value
    dvipng_args.extend(self.builder.config.pngmath_dvipng_args)
    if use_preview:
        dvipng_args.append('--depth')
    # last, the input file name
    dvipng_args.append(path.join(tempdir, 'math.dvi'))
    try:
        p = Popen(dvipng_args, stdout=PIPE, stderr=PIPE)
    except OSError as err:
        if err.errno != ENOENT:  # No such file or directory
            raise
        logger.warning(
            'dvipng command %r cannot be run (needed for math '
            'display), check the pngmath_dvipng setting',
            self.builder.config.pngmath_dvipng)
        self.builder._mathpng_warned_dvipng = True
        return None, None
    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise MathExtError('dvipng exited with error', stderr, stdout)
    depth = None
    if use_preview:
        for line in stdout.splitlines():
            m = depth_re.match(line)
            if m:
                depth = int(m.group(1))
                write_png_depth(outfn, depth)
                break

    return relfn, depth
Ejemplo n.º 56
0
def builder_specific_actions(result,
                             builder,
                             output_path,
                             cmd_type,
                             page_name=None,
                             print_func=print):
    """Run post-sphinx-build actions.

    :param result: the result of the build execution; a status code or and exception
    """

    from sphinx.util.osutil import cd

    from ..pdf import html_to_pdf
    from ..sphinx import REDIRECT_TEXT

    if isinstance(result, Exception):
        msg = (f"There was an error in building your {cmd_type}. "
               "Look above for the cause.")
        # TODO ideally we probably only want the original traceback here
        raise RuntimeError(_message_box(msg, color="red",
                                        doprint=False)) from result
    elif result:
        msg = (
            f"Building your {cmd_type}, returns a non-zero exit code ({result}). "
            "Look above for the cause.")
        _message_box(msg, color="red", print_func=click.echo)
        sys.exit(result)

    # Builder-specific options
    if builder == "html":
        path_output_rel = Path(op.relpath(output_path, Path()))
        if cmd_type == "page":
            path_page = path_output_rel.joinpath(f"{page_name}.html")
            # Write an index file if it doesn't exist so we get redirects
            path_index = path_output_rel.joinpath("index.html")
            if not path_index.exists():
                path_index.write_text(
                    REDIRECT_TEXT.format(first_page=path_page.name))

            _message_box(
                dedent(f"""
                    Page build finished.
                        Your page folder is: {path_page.parent}{os.sep}
                        Open your page at: {path_page}
                    """))

        elif cmd_type == "book":
            path_output_rel = Path(op.relpath(output_path, Path()))
            path_index = path_output_rel.joinpath("index.html")
            _message_box(f"""\
            Finished generating HTML for {cmd_type}.
            Your book's HTML pages are here:
                {path_output_rel}{os.sep}
            You can look at your book by opening this file in a browser:
                {path_index}
            Or paste this line directly into your browser bar:
                file://{path_index.resolve()}\
            """)
    if builder == "pdfhtml":
        print_func(f"Finished generating HTML for {cmd_type}...")
        print_func(f"Converting {cmd_type} HTML into PDF...")
        path_pdf_output = output_path.parent.joinpath("pdf")
        path_pdf_output.mkdir(exist_ok=True)
        if cmd_type == "book":
            path_pdf_output = path_pdf_output.joinpath("book.pdf")
            html_to_pdf(output_path.joinpath("index.html"), path_pdf_output)
        elif cmd_type == "page":
            path_pdf_output = path_pdf_output.joinpath(page_name + ".pdf")
            html_to_pdf(output_path.joinpath(page_name + ".html"),
                        path_pdf_output)
        path_pdf_output_rel = Path(op.relpath(path_pdf_output, Path()))
        _message_box(f"""\
        Finished generating PDF via HTML for {cmd_type}. Your PDF is here:
            {path_pdf_output_rel}\
        """)
    if builder == "pdflatex":
        print_func(f"Finished generating latex for {cmd_type}...")
        print_func(f"Converting {cmd_type} latex into PDF...")
        # Convert to PDF via tex and template built Makefile and make.bat
        if sys.platform == "win32":
            makecmd = os.environ.get("MAKE", "make.bat")
        else:
            makecmd = os.environ.get("MAKE", "make")
        try:
            with cd(output_path):
                output = subprocess.run([makecmd, "all-pdf"])
                if output.returncode != 0:
                    _error("Error: Failed to build pdf")
                    return output.returncode
            _message_box(f"""\
            A PDF of your {cmd_type} can be found at:
                {output_path}
            """)
        except OSError:
            _error("Error: Failed to run: %s" % makecmd)
            return 1