diff options
Diffstat (limited to 'sphinx/ext/graphviz.py')
-rw-r--r-- | sphinx/ext/graphviz.py | 85 |
1 files changed, 41 insertions, 44 deletions
diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 028560b1..71e7ba65 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -15,14 +15,14 @@ import codecs import posixpath from os import path from subprocess import Popen, PIPE -try: - from hashlib import sha1 as sha -except ImportError: - from sha import sha +from hashlib import sha1 +from six import text_type from docutils import nodes from docutils.parsers.rst import directives +from docutils.statemachine import ViewList +import sphinx from sphinx.errors import SphinxError from sphinx.locale import _ from sphinx.util.osutil import ensuredir, ENOENT, EPIPE, EINVAL @@ -40,6 +40,20 @@ class graphviz(nodes.General, nodes.Element): pass +def figure_wrapper(directive, node, caption): + figure_node = nodes.figure('', node) + + parsed = nodes.Element() + directive.state.nested_parse(ViewList([caption], source=''), + directive.content_offset, parsed) + caption_node = nodes.caption(parsed[0].rawsource, '', + *parsed[0].children) + caption_node.source = parsed[0].source + caption_node.line = parsed[0].line + figure_node += caption_node + return figure_node + + class Graphviz(Directive): """ Directive to insert arbitrary dot markup. @@ -85,9 +99,12 @@ class Graphviz(Directive): node['options'] = [] if 'alt' in self.options: node['alt'] = self.options['alt'] - if 'caption' in self.options: - node['caption'] = self.options['caption'] node['inline'] = 'inline' in self.options + + caption = self.options.get('caption') + if caption and not node['inline']: + node = figure_wrapper(self, node, caption) + return [node] @@ -112,9 +129,12 @@ class GraphvizSimple(Directive): node['options'] = [] if 'alt' in self.options: node['alt'] = self.options['alt'] - if 'caption' in self.options: - node['caption'] = self.options['caption'] node['inline'] = 'inline' in self.options + + caption = self.options.get('caption') + if caption and not node['inline']: + node = figure_wrapper(self, node, caption) + return [node] @@ -125,15 +145,9 @@ def render_dot(self, code, options, format, prefix='graphviz'): str(self.builder.config.graphviz_dot_args) ).encode('utf-8') - fname = '%s-%s.%s' % (prefix, sha(hashkey).hexdigest(), format) - if hasattr(self.builder, 'imgpath'): - # HTML - relfn = posixpath.join(self.builder.imgpath, fname) - outfn = path.join(self.builder.outdir, '_images', fname) - else: - # LaTeX - relfn = fname - outfn = path.join(self.builder.outdir, fname) + fname = '%s-%s.%s' % (prefix, sha1(hashkey).hexdigest(), format) + relfn = posixpath.join(self.builder.imgpath, fname) + outfn = path.join(self.builder.outdir, self.builder.imagedir, fname) if path.isfile(outfn): return relfn, outfn @@ -145,7 +159,7 @@ def render_dot(self, code, options, format, prefix='graphviz'): ensuredir(path.dirname(outfn)) # graphviz expects UTF-8 by default - if isinstance(code, unicode): + if isinstance(code, text_type): code = code.encode('utf-8') dot_args = [self.builder.config.graphviz_dot] @@ -156,7 +170,7 @@ def render_dot(self, code, options, format, prefix='graphviz'): dot_args.extend(['-Tcmapx', '-o%s.map' % outfn]) try: p = Popen(dot_args, stdout=PIPE, stdin=PIPE, stderr=PIPE) - except OSError, err: + except OSError as err: if err.errno != ENOENT: # No such file or directory raise self.builder.warn('dot command %r cannot be run (needed for graphviz ' @@ -168,7 +182,7 @@ def render_dot(self, code, options, format, prefix='graphviz'): # Graphviz may close standard input when an error occurs, # resulting in a broken pipe on communicate() stdout, stderr = p.communicate(code) - except (OSError, IOError), err: + except (OSError, IOError) as err: if err.errno not in (EPIPE, EINVAL): raise # in this case, read the standard output and standard error streams @@ -192,7 +206,7 @@ def render_dot_html(self, node, code, options, prefix='graphviz', raise GraphvizError("graphviz_output_format must be one of 'png', " "'svg', but is %r" % format) fname, outfn = render_dot(self, code, options, format, prefix) - except GraphvizError, exc: + except GraphvizError as exc: self.builder.warn('dot code %r: ' % code + str(exc)) raise nodes.SkipNode @@ -228,9 +242,6 @@ def render_dot_html(self, node, code, options, prefix='graphviz', self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' % (fname, alt, mapname, imgcss)) self.body.extend([item.decode('utf-8') for item in imgmap]) - if node.get('caption') and not inline: - self.body.append('</p>\n<p class="caption">') - self.body.append(self.encode(node['caption'])) self.body.append('</%s>\n' % wrapper) raise nodes.SkipNode @@ -243,7 +254,7 @@ def html_visit_graphviz(self, node): def render_dot_latex(self, node, code, options, prefix='graphviz'): try: fname, outfn = render_dot(self, code, options, 'pdf', prefix) - except GraphvizError, exc: + except GraphvizError as exc: self.builder.warn('dot code %r: ' % code + str(exc)) raise nodes.SkipNode @@ -254,18 +265,8 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'): para_separator = '\n' if fname is not None: - caption = node.get('caption') - # XXX add ids from previous target node - if caption and not inline: - self.body.append('\n\\begin{figure}[h!]') - self.body.append('\n\\begin{center}') - self.body.append('\n\\caption{%s}' % self.encode(caption)) - self.body.append('\n\\includegraphics{%s}' % fname) - self.body.append('\n\\end{center}') - self.body.append('\n\\end{figure}\n') - else: - self.body.append('%s\\includegraphics{%s}%s' % - (para_separator, fname, para_separator)) + self.body.append('%s\\includegraphics{%s}%s' % + (para_separator, fname, para_separator)) raise nodes.SkipNode @@ -276,16 +277,11 @@ def latex_visit_graphviz(self, node): def render_dot_texinfo(self, node, code, options, prefix='graphviz'): try: fname, outfn = render_dot(self, code, options, 'png', prefix) - except GraphvizError, exc: + except GraphvizError as exc: self.builder.warn('dot code %r: ' % code + str(exc)) raise nodes.SkipNode if fname is not None: - self.body.append('\n\n@float\n') - caption = node.get('caption') - if caption: - self.body.append('@caption{%s}\n' % self.escape_arg(caption)) - self.body.append('@image{%s,,,[graphviz],png}\n' - '@end float\n\n' % fname[:-4]) + self.body.append('@image{%s,,,[graphviz],png}\n' % fname[:-4]) raise nodes.SkipNode def texinfo_visit_graphviz(self, node): @@ -321,3 +317,4 @@ def setup(app): app.add_config_value('graphviz_dot', 'dot', 'html') app.add_config_value('graphviz_dot_args', [], 'html') app.add_config_value('graphviz_output_format', 'png', 'html') + return {'version': sphinx.__version__, 'parallel_read_safe': True} |