示例#1
0
    def add_source_parser(self, *args, **kwargs):
        # type: (Any, bool) -> None
        logger.debug('[app] adding search source_parser: %r', args)
        if len(args) == 1:
            # new sytle arguments: (source_parser)
            suffix = None  # type: unicode
            parser = args[0]  # type: Type[Parser]
        else:
            # old style arguments: (suffix, source_parser)
            warnings.warn(
                'app.add_source_parser() does not support suffix argument. '
                'Use app.add_source_suffix() instead.',
                RemovedInSphinx30Warning)
            suffix = args[0]
            parser = args[1]

        if suffix:
            self.add_source_suffix(suffix, suffix)

        if len(parser.supported) == 0:
            warnings.warn(
                'Old source_parser has been detected. Please fill Parser.supported '
                'attribute: %s' % parser.__name__, RemovedInSphinx30Warning)

        # create a map from filetype to parser
        for filetype in parser.supported:
            if filetype in self.source_parsers and not kwargs.get('override'):
                raise ExtensionError(
                    __('source_parser for %r is already registered') %
                    filetype)
            else:
                self.source_parsers[filetype] = parser

        # also maps suffix to parser
        #
        # This rescues old styled parsers which does not have ``supported`` filetypes.
        if suffix:
            self.source_parsers[suffix] = parser
示例#2
0
 def add_node(self, node, **kwds):
     # type: (nodes.Node, Any) -> None
     logger.debug('[app] adding node: %r', (node, kwds))
     if not kwds.pop('override', False) and \
        hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__):
         logger.warning(
             'while setting up extension %s: node class %r is '
             'already registered, its visitors will be overridden',
             self._setting_up_extension,
             node.__name__,
             type='app',
             subtype='add_node')
     nodes._add_node_class_names([node.__name__])
     for key, val in iteritems(kwds):
         try:
             visit, depart = val
         except ValueError:
             raise ExtensionError('Value for key %r must be a '
                                  '(visit, depart) function tuple' % key)
         translator = self._translators.get(key)
         if translator is not None:
             pass
         elif key == 'html':
             from sphinx.writers.html import HTMLTranslator as translator  # type: ignore
         elif key == 'latex':
             from sphinx.writers.latex import LaTeXTranslator as translator  # type: ignore
         elif key == 'text':
             from sphinx.writers.text import TextTranslator as translator  # type: ignore
         elif key == 'man':
             from sphinx.writers.manpage import ManualPageTranslator as translator  # type: ignore  # NOQA
         elif key == 'texinfo':
             from sphinx.writers.texinfo import TexinfoTranslator as translator  # type: ignore  # NOQA
         else:
             # ignore invalid keys for compatibility
             continue
         setattr(translator, 'visit_' + node.__name__, visit)
         if depart:
             setattr(translator, 'depart_' + node.__name__, depart)
示例#3
0
 def add_node(self, node, **kwds):
     nodes._add_node_class_names([node.__name__])
     for key, val in kwds.iteritems():
         try:
             visit, depart = val
         except ValueError:
             raise ExtensionError('Value for key %r must be a '
                                  '(visit, depart) function tuple' % key)
         if key == 'html':
             from sphinx.writers.html import HTMLTranslator as translator
         elif key == 'latex':
             from sphinx.writers.latex import LaTeXTranslator as translator
         elif key == 'text':
             from sphinx.writers.text import TextTranslator as translator
         elif key == 'man':
             from sphinx.writers.manpage import ManualPageTranslator \
                 as translator
         else:
             # ignore invalid keys for compatibility
             continue
         setattr(translator, 'visit_'+node.__name__, visit)
         if depart:
             setattr(translator, 'depart_'+node.__name__, depart)
示例#4
0
def setup(app):
    try:
        mathbase_setup(app, (html_visit_math, None),
                       (html_visit_displaymath, None))
    except ExtensionError:
        raise ExtensionError(
            'sphinx.ext.imgmath: other math package is already loaded')

    app.add_config_value('imgmath_image_format', 'png', 'html')
    app.add_config_value('imgmath_dvipng', 'dvipng', 'html')
    app.add_config_value('imgmath_dvisvgm', 'dvisvgm', 'html')
    app.add_config_value('imgmath_latex', 'latex', 'html')
    app.add_config_value('imgmath_use_preview', False, 'html')
    app.add_config_value('imgmath_dvipng_args',
                         ['-gamma', '1.5', '-D', '110', '-bg', 'Transparent'],
                         'html')
    app.add_config_value('imgmath_dvisvgm_args', ['--no-fonts'], 'html')
    app.add_config_value('imgmath_latex_args', [], 'html')
    app.add_config_value('imgmath_latex_preamble', '', 'html')
    app.add_config_value('imgmath_add_tooltips', True, 'html')
    app.add_config_value('imgmath_font_size', 12, 'html')
    app.connect('build-finished', cleanup_tempdir)
    return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
示例#5
0
    def convert(self, _from, _to):
        # type: (str, str) -> bool
        """Converts the image to expected one."""
        try:
            if _from.lower().endswith('.gif'):
                # when target is GIF format, pick the first frame
                _from += '[0]'

            args = ([self.config.image_converter] +
                    self.config.image_converter_args + [_from, _to])
            logger.debug('Invoking %r ...', args)
            subprocess.run(args, stdout=PIPE, stderr=PIPE, check=True)
            return True
        except OSError:
            logger.warning(
                __('convert command %r cannot be run.'
                   'check the image_converter setting'),
                self.config.image_converter)
            return False
        except CalledProcessError as exc:
            raise ExtensionError(
                __('convert exited with error:\n'
                   '[stderr]\n%r\n[stdout]\n%r') % (exc.stderr, exc.stdout))
示例#6
0
def setup(app):
    # type: (Sphinx) -> Dict[unicode, Any]
    app.warn(
        'sphinx.ext.pngmath has been deprecated. Please use sphinx.ext.imgmath instead.'
    )
    try:
        mathbase_setup(app, (html_visit_math, None),
                       (html_visit_displaymath, None))
    except ExtensionError:
        raise ExtensionError(
            'sphinx.ext.pngmath: other math package is already loaded')

    app.add_config_value('pngmath_dvipng', 'dvipng', 'html')
    app.add_config_value('pngmath_latex', 'latex', 'html')
    app.add_config_value('pngmath_use_preview', False, 'html')
    app.add_config_value('pngmath_dvipng_args',
                         ['-gamma', '1.5', '-D', '110', '-bg', 'Transparent'],
                         'html')
    app.add_config_value('pngmath_latex_args', [], 'html')
    app.add_config_value('pngmath_latex_preamble', '', 'html')
    app.add_config_value('pngmath_add_tooltips', True, 'html')
    app.connect('build-finished', cleanup_tempdir)
    return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
示例#7
0
    def get_edit_url():
        """Return a URL for an "edit this page" link."""
        required_values = ["github_user", "github_repo", "github_version"]
        for val in required_values:
            if not context.get(val):
                raise ExtensionError(
                    "Missing required value for `edit this page` button. "
                    "Add %s to your `html_context` configuration" % val)

        github_user = context["github_user"]
        github_repo = context["github_repo"]
        github_version = context["github_version"]
        file_name = f"{pagename}{context['page_source_suffix']}"

        # Make sure that doc_path has a path separator only if it exists (to avoid //)
        doc_path = context.get("doc_path", "")
        if doc_path and not doc_path.endswith("/"):
            doc_path = f"{doc_path}/"

        # Build the URL for "edit this button"
        url_edit = (f"https://github.com/{github_user}/{github_repo}"
                    f"/edit/{github_version}/{doc_path}{file_name}")
        return url_edit
示例#8
0
    def output_rst(self, root, source_suffix):
        if not self.objects:
            raise ExtensionError("No API objects exist. Can't continue")
        for id, obj in self.objects.items():

            if not obj or not obj.top_level_object:
                continue

            rst = obj.render()
            if not rst:
                continue

            detail_dir = os.path.join(root, obj.pathname)
            ensuredir(detail_dir)
            path = os.path.join(detail_dir, '%s%s' % ('index', source_suffix))
            with open(path, 'wb') as detail_file:
                detail_file.write(rst.encode('utf-8'))

        # Render Top Index
        top_level_index = os.path.join(root, 'index.rst')
        with open(top_level_index, 'wb') as top_level_file:
            content = self.jinja_env.get_template('index.rst')
            top_level_file.write(content.render(pages=self.namespaces.values()).encode('utf-8'))
示例#9
0
def setup(app):
    try:
        mathbase_setup(app, (html_visit_math, None),
                       (html_visit_displaymath, None))
    except ExtensionError:
        raise ExtensionError(
            'sphinx.ext.mathjax: other math package is already loaded')

    # more information for mathjax secure url is here:
    # http://docs.mathjax.org/en/latest/start.html#secure-access-to-the-cdn
    app.add_config_value(
        'mathjax_path',
        'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?'
        'config=TeX-MML-AM_CHTML',
        #'config=TeX-AMS-MML_HTMLorMML',
        False)
    app.add_config_value('mathjax_css', None, 'html')
    app.add_config_value('mathjax_use_katex', False, 'html')
    app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html')
    app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html')
    app.connect('builder-inited', builder_inited)

    return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
示例#10
0
    def add_object_type(self, directivename, rolename, indextemplate='',
                        parse_node=None, ref_nodeclass=None, objname='',
                        doc_field_types=[], override=False):
        # type: (unicode, unicode, unicode, Callable, Type[nodes.Node], unicode, List, bool) -> None  # NOQA
        logger.debug('[app] adding object type: %r',
                     (directivename, rolename, indextemplate, parse_node,
                      ref_nodeclass, objname, doc_field_types))

        # create a subclass of GenericObject as the new directive
        directive = type(directivename,  # type: ignore
                         (GenericObject, object),
                         {'indextemplate': indextemplate,
                          'parse_node': staticmethod(parse_node),
                          'doc_field_types': doc_field_types})

        self.add_directive_to_domain('std', directivename, directive)
        self.add_role_to_domain('std', rolename, XRefRole(innernodeclass=ref_nodeclass))

        object_types = self.domain_object_types.setdefault('std', {})
        if directivename in object_types and not override:
            raise ExtensionError(__('The %r object_type is already registered') %
                                 directivename)
        object_types[directivename] = ObjType(objname or directivename, rolename)
示例#11
0
 def setup_extension(self, extension):
     """Import and setup a Sphinx extension module. No-op if called twice."""
     self.debug('[app] setting up extension: %r', extension)
     if extension in self._extensions:
         return
     try:
         mod = __import__(extension, None, None, ['setup'])
     except ImportError as err:
         raise ExtensionError('Could not import extension %s' % extension,
                              err)
     if not hasattr(mod, 'setup'):
         self.warn('extension %r has no setup() function; is it really '
                   'a Sphinx extension module?' % extension)
     else:
         try:
             mod.setup(self)
         except VersionRequirementError as err:
             # add the extension name to the version required
             raise VersionRequirementError(
                 'The %s extension used by this project needs at least '
                 'Sphinx v%s; it therefore cannot be built with this '
                 'version.' % (extension, err))
     self._extensions[extension] = mod
示例#12
0
    def import_object(self):
        """Import the object and set it as *self.object*.  In the call sequence, this
        is executed right after parse_name(), so it can use *self.fullname*, *self.objname*,
        and *self.modname*.

        Returns True if successful, False if an error occurred.
        """
        # change
        #xpath_query = './/compoundname[text()="%s"]/..' % self.fullname
        xpath_query = './compounddef/compoundname[text()="%s"]/..' % self.fullname
        match = get_doxygen_root().xpath(xpath_query)
        if len(match) != 1:
            # change
            #raise ExtensionError('[autodoc_doxygen] could not find class (fullname="%s"). I tried'
            raise ExtensionError(
                '[autodoc_doxygen] could not find module (fullname="%s"). I tried'
                'the following xpath: "%s"' % (self.fullname, xpath_query))

        self.object = match[0]
        if self.env.app.verbosity > 0:
            print("[debug] xpath(%s) match(%s)" %
                  (xpath_query, match[0].items()))
        return True
示例#13
0
    def convert(self, _from: str, _to: str) -> bool:
        """Converts the image to expected one."""
        try:
            # append an index 0 to source filename to pick up the first frame
            # (or first page) of image (ex. Animation GIF, PDF)
            _from += '[0]'

            args = ([self.config.image_converter] +
                    self.config.image_converter_args + [_from, _to])
            logger.debug('Invoking %r ...', args)
            subprocess.run(args, stdout=PIPE, stderr=PIPE, check=True)
            return True
        except OSError:
            logger.warning(
                __('convert command %r cannot be run, '
                   'check the image_converter setting'),
                self.config.image_converter)
            return False
        except CalledProcessError as exc:
            raise ExtensionError(
                __('convert exited with error:\n'
                   '[stderr]\n%r\n[stdout]\n%r') %
                (exc.stderr, exc.stdout)) from exc
示例#14
0
文件: registry.py 项目: vsajip/sphinx
    def add_object_type(self, directivename: str, rolename: str, indextemplate: str = '',
                        parse_node: Callable = None, ref_nodeclass: "Type[TextElement]" = None,
                        objname: str = '', doc_field_types: List = [], override: bool = False
                        ) -> None:
        logger.debug('[app] adding object type: %r',
                     (directivename, rolename, indextemplate, parse_node,
                      ref_nodeclass, objname, doc_field_types))

        # create a subclass of GenericObject as the new directive
        directive = type(directivename,
                         (GenericObject, object),
                         {'indextemplate': indextemplate,
                          'parse_node': staticmethod(parse_node),
                          'doc_field_types': doc_field_types})

        self.add_directive_to_domain('std', directivename, directive)
        self.add_role_to_domain('std', rolename, XRefRole(innernodeclass=ref_nodeclass))

        object_types = self.domain_object_types.setdefault('std', {})
        if directivename in object_types and not override:
            raise ExtensionError(__('The %r object_type is already registered') %
                                 directivename)
        object_types[directivename] = ObjType(objname or directivename, rolename)
    def convert(self, _from, _to):
        # type: (unicode, unicode) -> bool
        """Converts the image from SVG to PDF via Inkscape."""
        try:
            args = ([self.config.inkscape_converter_bin] +
                    self.config.inkscape_converter_args)
            if self._inkscape_version.startswith('1.'):
                args += ['--export-filename=' + _to, _from]
            else:
                args += ['--export-pdf=' + _to, _from]
            logger.debug('Invoking %r ...', args)
            p = subprocess.Popen(args,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
        except OSError as err:
            if err.errno != ENOENT:  # No such file or directory
                raise
            logger.warning(
                __('Inkscape command %r cannot be run. '
                   'Check the inkscape_converter_bin setting'),
                self.config.inkscape_converter_bin)
            return False

        try:
            stdout, stderr = p.communicate()
        except (OSError, IOError) as err:
            if err.errno not in (EPIPE, EINVAL):
                raise
            stdout, stderr = p.stdout.read(), p.stderr.read()
            p.wait()
        if p.returncode != 0:
            raise ExtensionError(
                __('Inkscape exited with error:\n'
                   '[stderr]\n%s\n[stdout]\n%s') % (stderr, stdout))

        return True
示例#16
0
    def highlight_block(self, source, lang, opts, location, *args, **kwargs):
        """Preserves nxt_ directives, highlights syntax, replaces directives.
        """

        ph_groups = re.findall(':nxt_ph:' + NXT_HINT_REGEX, source)
        hint_groups = re.findall(':nxt_hint:' + NXT_HINT_REGEX, source)

        for i in range(len(ph_groups)):
            source = re.sub(':nxt_ph:' + NXT_HINT_REGEX,
                            'nxt_ph_' + str(i), source, count=1)

        for i in range(len(hint_groups)):
            source = re.sub(':nxt_hint:' + NXT_HINT_REGEX,
                            'nxt_hint_' + str(i), source, count=1)

        highlighted = self.highlighter.highlight_block(
            source, lang, opts, location, *args, **kwargs)

        for i, group in enumerate(ph_groups):
            highlighted = highlighted.replace(
                'nxt_ph_' + str(i),
                '<span class=nxt_ph title="{0}">{1}</span>'.format(group[1],
                                                                   group[0]),
                1)

        for i, group in enumerate(hint_groups):
            highlighted = highlighted.replace(
                'nxt_hint_' + str(i),
                '<span class=nxt_hint title="{0}">{1}</span>'.format(group[1],
                                                                     group[0]),
                1)

        if ':nxt_ph:' in highlighted or ':nxt_hint:' in highlighted:
            raise ExtensionError(__('Could not lex nxt_* directive at {0}. ').
                                 format(location))

        return highlighted
示例#17
0
def install_mathjax(app: Sphinx, pagename: str, templatename: str,
                    context: Dict, event_arg: Any) -> None:
    if app.builder.format != 'html' or app.builder.math_renderer_name != 'mathjax':  # type: ignore  # NOQA
        return
    if not app.config.mathjax_path:
        raise ExtensionError('mathjax_path config value must be set for the '
                             'mathjax extension to work')

    domain = cast(MathDomain, app.env.get_domain('math'))
    if app.registry.html_assets_policy == 'always' or domain.has_equations(
            pagename):
        # Enable mathjax only if equations exists
        if app.config.mathjax2_config:
            if app.config.mathjax_path == MATHJAX_URL:
                logger.warning(
                    'mathjax_config/mathjax2_config does not work '
                    'for the current MathJax version, use mathjax3_config instead'
                )
            body = 'MathJax.Hub.Config(%s)' % json.dumps(
                app.config.mathjax2_config)
            app.add_js_file(None, type='text/x-mathjax-config', body=body)
        if app.config.mathjax3_config:
            body = 'window.MathJax = %s' % json.dumps(
                app.config.mathjax3_config)
            app.add_js_file(None, body=body)

        options = {}
        if app.config.mathjax_options:
            options.update(app.config.mathjax_options)
        if 'async' not in options and 'defer' not in options:
            if app.config.mathjax3_config:
                # Load MathJax v3 via "defer" method
                options['defer'] = 'defer'
            else:
                # Load other MathJax via "async" method
                options['async'] = 'async'
        app.add_js_file(app.config.mathjax_path, **options)
示例#18
0
def load_glossary_csv(app, env, docnames):
    entries = []
    with open(_glossary_file_name(app), newline='') as csv_file:
        csv_reader = csv.reader(csv_file, delimiter=',', quotechar='"')
        for i, line in enumerate(csv_reader):
            entries.append({
                'key': line[0],
                'number': line[1],
                'name': line[2],
                'definition': line[3],
                'index': i,
            })

    index = {}
    for i, entry in enumerate(entries):
        if not entry['key'] in index:
            index[entry['key']] = {}
        numbered = index[entry['key']]
        if entry['number'] in numbered:
            raise ExtensionError("Duplicate entry for glossary: " + entry['key'])
        numbered[entry['number']] = i

    env.glossary_entries = entries
    env.glossary_entries_index = index
示例#19
0
    def run(self):
        env = self.state.document.settings.env
        qapifile = env.config.qapidoc_srctree + '/' + self.arguments[0]
        qapidir = os.path.dirname(qapifile)

        try:
            schema = QAPISchema(qapifile)

            # First tell Sphinx about all the schema files that the
            # output documentation depends on (including 'qapifile' itself)
            schema.visit(QAPISchemaGenDepVisitor(env, qapidir))

            vis = QAPISchemaGenRSTVisitor(self)
            vis.visit_begin(schema)
            for doc in schema.docs:
                if doc.symbol:
                    vis.symbol(doc, schema.lookup_entity(doc.symbol))
                else:
                    vis.freeform(doc)
            return vis.get_document_nodes()
        except QAPIError as err:
            # Launder QAPI parse errors into Sphinx extension errors
            # so they are displayed nicely to the user
            raise ExtensionError(str(err))
示例#20
0
def builder_inited(app):
    if not (app.config.katex_js_path and app.config.katex_css_path
            and app.config.katex_autorender_path):
        raise ExtensionError('KaTeX paths not set')
    # Sphinx 1.8 renamed `add_stylesheet` to `add_css_file`
    # and `add_javascript` to `add_js_file`.
    # Sphinx 4.0 finally removed `add_stylesheet` and `add_javascript`.
    old_css_add = getattr(app, 'add_stylesheet', None)
    old_js_add = getattr(app, 'add_javascript', None)
    add_css = getattr(app, 'add_css_file', old_css_add)
    add_js = getattr(app, 'add_js_file', old_js_add)
    add_css(app.config.katex_css_path)
    # Ensure the static path is setup to hold KaTeX CSS and autorender files
    setup_static_path(app)
    if not app.config.katex_prerender:
        add_js(app.config.katex_js_path)
        # Automatic math rendering and custom CSS
        # https://github.com/Khan/KaTeX/blob/master/contrib/auto-render/README.md
        add_js(app.config.katex_autorender_path)
        write_katex_autorenderer_file(app, filename_autorenderer)
        add_js(filename_autorenderer)
    # sphinxcontrib.katex custom CSS
    copy_katex_css_file(app, filename_css)
    add_css(filename_css)
示例#21
0
def create_graph(path: Path) -> Dict[str, str]:
    """
    Convert a file containing a whitespace delimited edge list (key value pairs) to a dict. Throws error on duplicate keys.
    """
    graph_edges = {}
    broken = False
    with open(path, "r") as file:
        for line_num, line in enumerate(file, start=1):
            line = line.strip()
            if len(line) == 0 or line.startswith("#"):
                continue
            match = RE_OBJ.fullmatch(line)

            if match == None:
                logger.error(
                    red(f"rediraffe: line {line_num} of the redirects is invalid!")
                )
                broken = True
                continue

            edge_from = match.group(2) or match.group(3)
            edge_to = match.group(5) or match.group(6)
            if edge_from in graph_edges:
                # Duplicate vertices not allowed / Vertices can only have 1 outgoing edge
                logger.error(
                    red(
                        f"rediraffe: {edge_from} is redirected multiple times in the rediraffe_redirects file!"
                    )
                )
                broken = True
            graph_edges[edge_from] = edge_to
    if broken:
        err_msg = f"rediraffe: Error(s) in parsing the redirects file."
        logger.error(err_msg)
        raise ExtensionError(err_msg)
    return graph_edges
示例#22
0
    def emit(
        self,
        name: str,
        *args: Any,
        allowed_exceptions: Tuple["Type[Exception]", ...] = ()
    ) -> List:
        """Emit a Sphinx event."""
        try:
            logger.debug('[app] emitting event: %r%s', name, repr(args)[:100])
        except Exception:
            # not every object likes to be repr()'d (think
            # random stuff coming via autodoc)
            pass

        results = []
        listeners = sorted(self.listeners[name], key=attrgetter("priority"))
        for listener in listeners:
            try:
                if self.app is None:
                    # for compatibility; RemovedInSphinx40Warning
                    results.append(listener.handler(*args))
                else:
                    results.append(listener.handler(self.app, *args))
            except allowed_exceptions:
                # pass through the errors specified as *allowed_exceptions*
                raise
            except SphinxError:
                raise
            except Exception as exc:
                modname = safe_getattr(listener.handler, '__module__', None)
                raise ExtensionError(
                    __("Handler %r for event %r threw an exception") %
                    (listener.handler, name),
                    exc,
                    modname=modname) from exc
        return results
    def convert(self, _from, _to):
        # type: (unicode, unicode) -> bool
        """Converts the image to expected one."""
        try:
            # append an index 0 to source filename to pick up the first frame
            # (or first page) of image (ex. Animation GIF, PDF)
            _from += '[0]'

            args = ([self.config.image_converter] +
                    self.config.image_converter_args + [_from, _to])
            logger.debug('Invoking %r ...', args)
            p = subprocess.Popen(args,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
        except OSError as err:
            if err.errno != ENOENT:  # No such file or directory
                raise
            logger.warning(
                __('convert command %r cannot be run.'
                   'check the image_converter setting'),
                self.config.image_converter)
            return False

        try:
            stdout, stderr = p.communicate()
        except (OSError, IOError) as err:
            if err.errno not in (EPIPE, EINVAL):
                raise
            stdout, stderr = p.stdout.read(), p.stderr.read()
            p.wait()
        if p.returncode != 0:
            raise ExtensionError(
                __('convert exited with error:\n'
                   '[stderr]\n%s\n[stdout]\n%s') % (stderr, stdout))

        return True
示例#24
0
文件: registry.py 项目: rkapl/sphinx
    def add_source_parser(self, suffix, parser):
        # type: (unicode, Type[Parser]) -> None
        logger.debug('[app] adding search source_parser: %r, %r', suffix,
                     parser)
        self.add_source_suffix(suffix, suffix)

        if len(parser.supported) == 0:
            warnings.warn(
                'Old source_parser has been detected. Please fill Parser.supported '
                'attribute: %s' % parser.__name__, RemovedInSphinx30Warning)

        # create a map from filetype to parser
        for filetype in parser.supported:
            if filetype in self.source_parsers:
                raise ExtensionError(
                    __('source_parser for %r is already registered') %
                    filetype)
            else:
                self.source_parsers[filetype] = parser

        # also maps suffix to parser
        #
        # This allows parsers not having ``supported`` filetypes.
        self.source_parsers[suffix] = parser
示例#25
0
def update_config(app, env):
    theme_options = app.config["html_theme_options"]

    # DEPRECATE after v0.9
    if theme_options.get("search_bar_position") == "navbar":
        logger.warn(
            (
                "Deprecated config `search_bar_position` used."
                "Use `search-field.html` in `navbar_end` template list instead."
            )
        )

    # Validate icon links
    if not isinstance(theme_options.get("icon_links", []), list):
        raise ExtensionError(
            (
                "`icon_links` must be a list of dictionaries, you provided "
                f"type {type(theme_options.get('icon_links'))}."
            )
        )

    # Update the anchor link (it's a tuple, so need to overwrite the whole thing)
    icon_default = app.config.values["html_permalinks_icon"]
    app.config.values["html_permalinks_icon"] = ("#", *icon_default[1:])
示例#26
0
 def __init__(self, env: "BuildEnvironment"):
     # set up referencing style
     style = sphinxcontrib.bibtex.plugin.find_plugin(
         'sphinxcontrib.bibtex.style.referencing',
         env.app.config.bibtex_reference_style)
     self.reference_style = style()
     # set up object types and roles for referencing style
     role_names = self.reference_style.role_names()
     self.object_types = dict(citation=ObjType(_('citation'),
                                               *role_names,
                                               searchprio=-1), )
     self.roles = dict((name, CiteRole()) for name in role_names)
     # initialize the domain
     super().__init__(env)
     # connect env-updated
     env.app.connect('env-updated', env_updated)
     # check config
     if env.app.config.bibtex_bibfiles is None:
         raise ExtensionError(
             "You must configure the bibtex_bibfiles setting")
     # update bib file information in the cache
     for bibfile in env.app.config.bibtex_bibfiles:
         process_bibfile(self.bibfiles,
                         normpath_filename(env, "/" + bibfile),
                         env.app.config.bibtex_encoding)
     # parse bibliography headers
     for directive in ("bibliography", "footbibliography"):
         header = getattr(env.app.config, "bibtex_%s_header" % directive)
         if header:
             parser = docutils.parsers.rst.Parser()
             settings = docutils.frontend.OptionParser(components=(
                 docutils.parsers.rst.Parser, )).get_default_values()
             document = docutils.utils.new_document("%s_header" % directive,
                                                    settings)
             parser.parse(header, document)
             self.data["%s_header" % directive] = document[0]
示例#27
0
    def convert(self, _from, _to):
        # type: (str, str) -> bool
        """Converts the image to expected one."""
        try:
            if _from.lower().endswith('.gif'):
                # when target is GIF format, pick the first frame
                _from += '[0]'

            args = ([self.config.image_converter] +
                    self.config.image_converter_args + [_from, _to])
            logger.debug('Invoking %r ...', args)
            p = subprocess.Popen(args,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
        except OSError as err:
            if err.errno != ENOENT:  # No such file or directory
                raise
            logger.warning(
                __('convert command %r cannot be run.'
                   'check the image_converter setting'),
                self.config.image_converter)
            return False

        try:
            stdout, stderr = p.communicate()
        except (OSError, IOError) as err:
            if err.errno not in (EPIPE, EINVAL):
                raise
            stdout, stderr = p.stdout.read(), p.stderr.read()
            p.wait()
        if p.returncode != 0:
            raise ExtensionError(
                __('convert exited with error:\n'
                   '[stderr]\n%s\n[stdout]\n%s') % (stderr, stdout))

        return True
示例#28
0
 def add_role_to_domain(self, domain, name, role):
     self.debug('[app] adding role to domain: %r', (domain, name, role))
     if domain not in self.domains:
         raise ExtensionError('domain %s not yet registered' % domain)
     self.domains[domain].roles[name] = role
示例#29
0
 def add_index_to_domain(self, domain, index):
     self.debug('[app] adding index to domain: %r', (domain, index))
     if domain not in self.domains:
         raise ExtensionError('domain %s not yet registered' % domain)
     self.domains[domain].indices.append(index)
示例#30
0
 def add_domain(self, domain):
     self.debug('[app] adding domain: %r', domain)
     if domain.name in self.domains:
         raise ExtensionError('domain %s already registered' % domain.name)
     self.domains[domain.name] = domain