diff -r be27ed110b50 -r d8ac696cc51f buildframework/helium/external/python/lib/common/Sphinx-0.5.1-py2.5.egg/sphinx/ext/pngmath.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/buildframework/helium/external/python/lib/common/Sphinx-0.5.1-py2.5.egg/sphinx/ext/pngmath.py Wed Dec 23 19:29:07 2009 +0200 @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +""" + sphinx.ext.pngmath + ~~~~~~~~~~~~~~~~~~ + + Render math in HTML via dvipng. + + :copyright: 2008 by Georg Brandl. + :license: BSD. +""" + +import re +import shutil +import tempfile +import posixpath +from os import path, getcwd, chdir +from subprocess import Popen, PIPE +try: + from hashlib import sha1 as sha +except ImportError: + from sha import sha + +from docutils import nodes + +from sphinx.util import ensuredir +from sphinx.util.png import read_png_depth, write_png_depth +from sphinx.application import SphinxError +from sphinx.ext.mathbase import setup as mathbase_setup, wrap_displaymath + +class MathExtError(SphinxError): + category = 'Math extension error' + + +DOC_HEAD = r''' +\documentclass[12pt]{article} +\usepackage[utf8]{inputenc} +\usepackage{amsmath} +\usepackage{amsthm} +\usepackage{amssymb} +\usepackage{amsfonts} +\usepackage{bm} +\pagestyle{empty} +''' + +DOC_BODY = r''' +\begin{document} +%s +\end{document} +''' + +DOC_BODY_PREVIEW = r''' +\usepackage[active]{preview} +\begin{document} +\begin{preview} +%s +\end{preview} +\end{document} +''' + +depth_re = re.compile(r'\[\d+ depth=(-?\d+)\]') + +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 + + shasum = "%s.png" % sha(math.encode('utf-8')).hexdigest() + relfn = posixpath.join(self.builder.imgpath, 'math', shasum) + outfn = path.join(self.builder.outdir, '_images', 'math', shasum) + if path.isfile(outfn): + depth = read_png_depth(outfn) + return relfn, depth + + latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble + latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math + if isinstance(latex, unicode): + latex = latex.encode('utf-8') + + # 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 = open(path.join(tempdir, 'math.tex'), 'w') + 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') + + curdir = getcwd() + chdir(tempdir) + + try: + try: + p = Popen(ltx_args, stdout=PIPE, stderr=PIPE) + except OSError, err: + if err.errno != 2: # No such file or directory + raise + if not hasattr(self.builder, '_mathpng_warned_latex'): + 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 relfn, None + finally: + chdir(curdir) + + stdout, stderr = p.communicate() + if p.returncode != 0: + raise MathExtError('latex exited with error:\n[stderr]\n%s\n[stdout]\n%s' + % (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, err: + if err.errno != 2: # No such file or directory + raise + if not hasattr(self.builder, '_mathpng_warned_dvipng'): + 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 relfn, None + stdout, stderr = p.communicate() + if p.returncode != 0: + raise MathExtError('dvipng exited with error:\n[stderr]\n%s\n[stdout]\n%s' + % (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 + +def cleanup_tempdir(app, exc): + if exc: + return + if not hasattr(app.builder, '_mathpng_tempdir'): + return + try: + shutil.rmtree(app.builder._mathpng_tempdir) + except Exception: + pass + +def html_visit_math(self, node): + try: + fname, depth = render_math(self, '$'+node['latex']+'$') + except MathExtError, exc: + sm = nodes.system_message(str(exc), type='WARNING', level=2, + backrefs=[], source=node['latex']) + sm.walkabout(self) + self.builder.warn('display latex %r: ' % node['latex'] + str(exc)) + raise nodes.SkipNode + self.body.append('%s' % + (fname, self.encode(node['latex']).strip(), + depth and 'style="vertical-align: %dpx" ' % (-depth) or '')) + raise nodes.SkipNode + +def html_visit_displaymath(self, node): + if node['nowrap']: + latex = node['latex'] + else: + latex = wrap_displaymath(node['latex'], None) + try: + fname, depth = render_math(self, latex) + except MathExtError, exc: + sm = nodes.system_message(str(exc), type='WARNING', level=2, + backrefs=[], source=node['latex']) + sm.walkabout(self) + self.builder.warn('inline latex %r: ' % node['latex'] + str(exc)) + raise nodes.SkipNode + self.body.append(self.starttag(node, 'div', CLASS='math')) + self.body.append('

') + if node['number']: + self.body.append('(%s)' % node['number']) + self.body.append('%s\n' % + (fname, self.encode(node['latex']).strip())) + self.body.append('

') + raise nodes.SkipNode + + +def setup(app): + mathbase_setup(app, (html_visit_math, None), (html_visit_displaymath, None)) + app.add_config_value('pngmath_dvipng', 'dvipng', False) + app.add_config_value('pngmath_latex', 'latex', False) + app.add_config_value('pngmath_use_preview', False, False) + app.add_config_value('pngmath_dvipng_args', ['-gamma 1.5', '-D 110'], False) + app.add_config_value('pngmath_latex_args', [], False) + app.add_config_value('pngmath_latex_preamble', '', False) + app.connect('build-finished', cleanup_tempdir)