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
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)
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)
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}
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))
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}
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
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'))
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}
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)
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
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
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
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
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
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)
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
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))
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)
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
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
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
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:])
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]
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
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
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)
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