merge with 0.5

This commit is contained in:
Georg Brandl 2009-02-12 12:53:48 +01:00
commit c09bf1ad85
7 changed files with 73 additions and 34 deletions

View File

@ -120,6 +120,14 @@ New features added
Release 0.5.2 (in development) Release 0.5.2 (in development)
============================== ==============================
* Use a new RFC base URL, since rfc.org seems down.
* Fix a crash in the todolist directive when no todo items are
defined.
* Don't call LaTeX or dvipng over and over again if it was not
found once, and use text-only latex as a substitute in that case.
* Fix problems with footnotes in the LaTeX output. * Fix problems with footnotes in the LaTeX output.
* Prevent double hyphens becoming en-dashes in literal code in * Prevent double hyphens becoming en-dashes in literal code in

View File

@ -18,14 +18,8 @@ from cStringIO import StringIO
from docutils import nodes from docutils import nodes
from docutils.parsers.rst import directives, roles from docutils.parsers.rst import directives, roles
import sphinx # create the error classes before importing the rest of Sphinx, so that
from sphinx.roles import xfileref_role, innernodetypes # they can be imported in a circular fashion
from sphinx.config import Config
from sphinx.builders import BUILTIN_BUILDERS
from sphinx.directives import desc_directive, target_directive, additional_xref_types
from sphinx.environment import SphinxStandaloneReader
from sphinx.util.console import bold
class SphinxError(Exception): class SphinxError(Exception):
""" """
@ -55,6 +49,15 @@ class ExtensionError(SphinxError):
return parent_str return parent_str
import sphinx
from sphinx.roles import xfileref_role, innernodetypes
from sphinx.config import Config
from sphinx.builders import BUILTIN_BUILDERS
from sphinx.directives import desc_directive, target_directive, additional_xref_types
from sphinx.environment import SphinxStandaloneReader
from sphinx.util.console import bold
# List of all known core events. Maps name to arguments description. # List of all known core events. Maps name to arguments description.
events = { events = {
'builder-inited': '', 'builder-inited': '',

View File

@ -26,6 +26,7 @@ from sphinx.util import SEP, os_path, relative_uri, ensuredir, \
movefile, ustrftime movefile, ustrftime
from sphinx.search import js_index from sphinx.search import js_index
from sphinx.builders import Builder, ENV_PICKLE_FILENAME from sphinx.builders import Builder, ENV_PICKLE_FILENAME
from sphinx.application import SphinxError
from sphinx.highlighting import PygmentsBridge from sphinx.highlighting import PygmentsBridge
from sphinx.util.console import bold from sphinx.util.console import bold
from sphinx.writers.html import HTMLWriter, HTMLTranslator, SmartyPantsHTMLTranslator from sphinx.writers.html import HTMLWriter, HTMLTranslator, SmartyPantsHTMLTranslator
@ -631,7 +632,6 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
def init(self): def init(self):
if json is None: if json is None:
from sphinx.application import SphinxError
raise SphinxError('The module simplejson (or json in Python >= 2.6) ' raise SphinxError('The module simplejson (or json in Python >= 2.6) '
'is not available. The JSONHTMLBuilder builder ' 'is not available. The JSONHTMLBuilder builder '
'will not work.') 'will not work.')

View File

@ -46,12 +46,13 @@ from sphinx import addnodes
from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \ from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
docname_join, FilenameUniqDict, url_re docname_join, FilenameUniqDict, url_re
from sphinx.directives import additional_xref_types from sphinx.directives import additional_xref_types
from sphinx.application import SphinxError
default_settings = { default_settings = {
'embed_stylesheet': False, 'embed_stylesheet': False,
'cloak_email_addresses': True, 'cloak_email_addresses': True,
'pep_base_url': 'http://www.python.org/dev/peps/', 'pep_base_url': 'http://www.python.org/dev/peps/',
'rfc_base_url': 'http://rfc.net/', 'rfc_base_url': 'http://tools.ietf.org/html/',
'input_encoding': 'utf-8', 'input_encoding': 'utf-8',
'doctitle_xform': False, 'doctitle_xform': False,
'sectsubtitle_xform': False, 'sectsubtitle_xform': False,
@ -545,7 +546,6 @@ class BuildEnvironment:
pub.publish() pub.publish()
doctree = pub.document doctree = pub.document
except UnicodeError, err: except UnicodeError, err:
from sphinx.application import SphinxError
raise SphinxError(str(err)) raise SphinxError(str(err))
self.filter_messages(doctree) self.filter_messages(doctree)
self.process_dependencies(docname, doctree) self.process_dependencies(docname, doctree)

View File

@ -82,6 +82,11 @@ def render_math(self, math):
depth = read_png_depth(outfn) depth = read_png_depth(outfn)
return relfn, depth 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
latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble latex = DOC_HEAD + self.builder.config.pngmath_latex_preamble
latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math latex += (use_preview and DOC_BODY_PREVIEW or DOC_BODY) % math
if isinstance(latex, unicode): if isinstance(latex, unicode):
@ -116,12 +121,11 @@ def render_math(self, math):
except OSError, err: except OSError, err:
if err.errno != 2: # No such file or directory if err.errno != 2: # No such file or directory
raise raise
if not hasattr(self.builder, '_mathpng_warned_latex'): self.builder.warn('LaTeX command %r cannot be run (needed for math '
self.builder.warn('LaTeX command %r cannot be run (needed for math ' 'display), check the pngmath_latex setting' %
'display), check the pngmath_latex setting' % self.builder.config.pngmath_latex)
self.builder.config.pngmath_latex) self.builder._mathpng_warned_latex = True
self.builder._mathpng_warned_latex = True return None, None
return relfn, None
finally: finally:
chdir(curdir) chdir(curdir)
@ -145,12 +149,11 @@ def render_math(self, math):
except OSError, err: except OSError, err:
if err.errno != 2: # No such file or directory if err.errno != 2: # No such file or directory
raise raise
if not hasattr(self.builder, '_mathpng_warned_dvipng'): self.builder.warn('dvipng command %r cannot be run (needed for math '
self.builder.warn('dvipng command %r cannot be run (needed for math ' 'display), check the pngmath_dvipng setting' %
'display), check the pngmath_dvipng setting' % self.builder.config.pngmath_dvipng)
self.builder.config.pngmath_dvipng) self.builder._mathpng_warned_dvipng = True
self.builder._mathpng_warned_dvipng = True return None, None
return relfn, None
stdout, stderr = p.communicate() stdout, stderr = p.communicate()
if p.returncode != 0: if p.returncode != 0:
raise MathExtError('dvipng exited with error:\n[stderr]\n%s\n[stdout]\n%s' raise MathExtError('dvipng exited with error:\n[stderr]\n%s\n[stdout]\n%s'
@ -185,9 +188,15 @@ def html_visit_math(self, node):
sm.walkabout(self) sm.walkabout(self)
self.builder.warn('display latex %r: ' % node['latex'] + str(exc)) self.builder.warn('display latex %r: ' % node['latex'] + str(exc))
raise nodes.SkipNode raise nodes.SkipNode
self.body.append('<img class="math" src="%s" alt="%s" %s/>' % if fname is None:
(fname, self.encode(node['latex']).strip(), # something failed -- use text-only as a bad substitute
depth and 'style="vertical-align: %dpx" ' % (-depth) or '')) self.body.append('<span class="math">%s</span>' %
self.encode(node['latex']).strip())
else:
self.body.append(
'<img class="math" src="%s" alt="%s" %s/>' %
(fname, self.encode(node['latex']).strip(),
depth and 'style="vertical-align: %dpx" ' % (-depth) or ''))
raise nodes.SkipNode raise nodes.SkipNode
def html_visit_displaymath(self, node): def html_visit_displaymath(self, node):
@ -207,8 +216,13 @@ def html_visit_displaymath(self, node):
self.body.append('<p>') self.body.append('<p>')
if node['number']: if node['number']:
self.body.append('<span class="eqno">(%s)</span>' % node['number']) self.body.append('<span class="eqno">(%s)</span>' % node['number'])
self.body.append('<img src="%s" alt="%s" />\n</div>' % if fname is None:
(fname, self.encode(node['latex']).strip())) # something failed -- use text-only as a bad substitute
self.body.append('<span class="math">%s</span>' %
self.encode(node['latex']).strip())
else:
self.body.append('<img src="%s" alt="%s" />\n</div>' %
(fname, self.encode(node['latex']).strip()))
self.body.append('</p>') self.body.append('</p>')
raise nodes.SkipNode raise nodes.SkipNode

View File

@ -61,6 +61,9 @@ def process_todo_nodes(app, doctree, fromdocname):
# Augment each todo with a backlink to the original location. # Augment each todo with a backlink to the original location.
env = app.builder.env env = app.builder.env
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
for node in doctree.traverse(todolist): for node in doctree.traverse(todolist):
if not app.config['todo_include_todos']: if not app.config['todo_include_todos']:
node.replace_self([]) node.replace_self([])

View File

@ -22,6 +22,7 @@ from docutils.writers.latex2e import Babel
from sphinx import addnodes from sphinx import addnodes
from sphinx import highlighting from sphinx import highlighting
from sphinx.locale import admonitionlabels, versionlabels from sphinx.locale import admonitionlabels, versionlabels
from sphinx.application import SphinxError
from sphinx.util import ustrftime from sphinx.util import ustrftime
from sphinx.util.texescape import tex_escape_map from sphinx.util.texescape import tex_escape_map
from sphinx.util.smartypants import educateQuotesLatex from sphinx.util.smartypants import educateQuotesLatex
@ -65,6 +66,9 @@ FOOTER = r'''
class collected_footnote(nodes.footnote): class collected_footnote(nodes.footnote):
"""Footnotes that are collected are assigned this class.""" """Footnotes that are collected are assigned this class."""
class UnsupportedError(SphinxError):
category = 'Markup is unsupported in LaTeX'
class LaTeXWriter(writers.Writer): class LaTeXWriter(writers.Writer):
@ -210,6 +214,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.highlightlinenothreshold = sys.maxint self.highlightlinenothreshold = sys.maxint
self.written_ids = set() self.written_ids = set()
self.footnotestack = [] self.footnotestack = []
self.curfilestack = []
if self.elements['docclass'] == 'manual': if self.elements['docclass'] == 'manual':
if builder.config.latex_use_parts: if builder.config.latex_use_parts:
self.top_sectionlevel = 0 self.top_sectionlevel = 0
@ -234,6 +239,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_document(self, node): def visit_document(self, node):
self.footnotestack.append(self.collect_footnotes(node)) self.footnotestack.append(self.collect_footnotes(node))
self.curfilestack.append(node['file'])
if self.first_document == 1: if self.first_document == 1:
# the first document is all the regular content ... # the first document is all the regular content ...
self.body.append(BEGIN_DOC % self.elements) self.body.append(BEGIN_DOC % self.elements)
@ -268,6 +274,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
self.footnotestack.append(self.collect_footnotes(node)) self.footnotestack.append(self.collect_footnotes(node))
# also add a document target # also add a document target
self.body.append('\\hypertarget{--doc-%s}{}' % node['docname']) self.body.append('\\hypertarget{--doc-%s}{}' % node['docname'])
self.curfilestack.append(node['file'])
def collect_footnotes(self, node): def collect_footnotes(self, node):
fnotes = {} fnotes = {}
@ -287,6 +294,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def depart_start_of_file(self, node): def depart_start_of_file(self, node):
self.footnotestack.pop() self.footnotestack.pop()
self.curfilestack.pop()
def visit_highlightlang(self, node): def visit_highlightlang(self, node):
self.highlightlang = node['lang'] self.highlightlang = node['lang']
@ -366,9 +374,10 @@ class LaTeXTranslator(nodes.NodeVisitor):
try: try:
self.body.append(r'\%s{' % self.sectionnames[self.sectionlevel]) self.body.append(r'\%s{' % self.sectionnames[self.sectionlevel])
except IndexError: except IndexError:
from sphinx.application import SphinxError raise UnsupportedError(
raise SphinxError('too many nesting section levels for LaTeX, ' '%s:%s: too many nesting section levels for '
'at heading: %s' % node.astext()) 'LaTeX, at heading: %s' % (self.curfilestack[-1],
node.line or '', node.astext()))
self.context.append('}\n') self.context.append('}\n')
elif isinstance(parent, (nodes.topic, nodes.sidebar)): elif isinstance(parent, (nodes.topic, nodes.sidebar)):
self.body.append(r'\textbf{') self.body.append(r'\textbf{')
@ -570,7 +579,8 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_table(self, node): def visit_table(self, node):
if self.table: if self.table:
raise NotImplementedError('Nested tables are not supported.') raise UnsupportedError('%s:%s: nested tables are not yet implemented.' %
(self.curfilestack[-1], node.line or ''))
self.table = Table() self.table = Table()
self.tablebody = [] self.tablebody = []
# Redirect body output until table is finished. # Redirect body output until table is finished.
@ -636,8 +646,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_entry(self, node): def visit_entry(self, node):
if node.has_key('morerows') or node.has_key('morecols'): if node.has_key('morerows') or node.has_key('morecols'):
raise NotImplementedError('Column or row spanning cells are ' raise UnsupportedError('%s:%s: column or row spanning cells are '
'not implemented.') 'not yet implemented.' %
(self.curfilestack[-1], node.line or ''))
if self.table.col > 0: if self.table.col > 0:
self.body.append(' & ') self.body.append(' & ')
self.table.col += 1 self.table.col += 1