Georg Brandl avatar Georg Brandl committed 0fb98f9

Use better error messages for unsupported markup in LaTeX documents.

Comments (0)

Files changed (4)

sphinx/application.py

 from docutils import nodes
 from docutils.parsers.rst import directives, roles
 
-import sphinx
-from sphinx.roles import xfileref_role, innernodetypes
-from sphinx.config import Config
-from sphinx.builder import builtin_builders, StandaloneHTMLBuilder
-from sphinx.directives import desc_directive, target_directive, additional_xref_types
-from sphinx.environment import SphinxStandaloneReader
-from sphinx.util.console import bold
-
+# create the error classes before importing the rest of Sphinx, so that
+# they can be imported in a circular fashion
 
 class SphinxError(Exception):
     """
         return parent_str
 
 
+import sphinx
+from sphinx.roles import xfileref_role, innernodetypes
+from sphinx.config import Config
+from sphinx.builder import builtin_builders, StandaloneHTMLBuilder
+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.
 events = {
     'builder-inited': '',

sphinx/builder.py

 from sphinx.highlighting import PygmentsBridge
 from sphinx.util.console import bold, purple, darkgreen
 from sphinx.search import js_index
+from sphinx.application import SphinxError
 
 try:
     import json
 
     def init(self):
         if json is None:
-            from sphinx.application import SphinxError
             raise SphinxError('The module simplejson (or json in Python >= 2.6) '
                               'is not available. The JSONHTMLBuilder builder '
                               'will not work.')
                         self.warn('%s: toctree contains ref to nonexisting file %r' %
                                   (docname, includefile))
                     else:
-                        sof = addnodes.start_of_file()
+                        sof = addnodes.start_of_file(file=includefile)
                         sof.children = subtree.children
                         newnodes.append(sof)
                 toctreenode.parent.replace(toctreenode, newnodes)
             tree = new_tree
         largetree = process_tree(indexfile, tree)
         largetree.extend(appendices)
+        largetree['file'] = indexfile
         self.info()
         self.info("resolving references...")
         self.env.resolve_references(largetree, indexfile, self)

sphinx/environment.py

 from sphinx import addnodes
 from sphinx.util import movefile, get_matching_docs, SEP, ustrftime
 from sphinx.directives import additional_xref_types
+from sphinx.application import SphinxError
 
 default_settings = {
     'embed_stylesheet': False,
             pub.publish()
             doctree = pub.document
         except UnicodeError, err:
-            from sphinx.application import SphinxError
             raise SphinxError(err.message)
         self.filter_messages(doctree)
         self.process_dependencies(docname, doctree)

sphinx/latexwriter.py

 from sphinx import addnodes
 from sphinx import highlighting
 from sphinx.locale import admonitionlabels, versionlabels
+from sphinx.application import SphinxError
 from sphinx.util import ustrftime
 from sphinx.util.texescape import tex_escape_map
 from sphinx.util.smartypants import educateQuotesLatex
 class collected_footnote(nodes.footnote):
     """Footnotes that are collected are assigned this class."""
 
+class UnsupportedError(SphinxError):
+    category = 'Markup is unsupported in LaTeX'
+
 
 class LaTeXWriter(writers.Writer):
 
         self.highlightlinenothreshold = sys.maxint
         self.written_ids = set()
         self.footnotestack = []
+        self.curfilestack = []
         if self.elements['docclass'] == 'manual':
             if builder.config.latex_use_parts:
                 self.top_sectionlevel = 0
 
     def visit_document(self, node):
         self.footnotestack.append(self.collect_footnotes(node))
+        self.curfilestack.append(node['file'])
         if self.first_document == 1:
             # the first document is all the regular content ...
             self.body.append(BEGIN_DOC % self.elements)
         self.body.append('\n\\resetcurrentobjects\n')
         # and also, new footnotes
         self.footnotestack.append(self.collect_footnotes(node))
+        self.curfilestack.append(node['file'])
 
     def collect_footnotes(self, node):
         fnotes = {}
 
     def depart_start_of_file(self, node):
         self.footnotestack.pop()
+        self.curfilestack.pop()
 
     def visit_highlightlang(self, node):
         self.highlightlang = node['lang']
             try:
                 self.body.append(r'\%s{' % self.sectionnames[self.sectionlevel])
             except IndexError:
-                from sphinx.application import SphinxError
-                raise SphinxError('too many nesting section levels for LaTeX, '
-                                  'at heading: %s' % node.astext())
+                raise UnsupportedError(
+                    '%s:%s: too many nesting section levels for '
+                    'LaTeX, at heading: %s' % (self.curfilestack[-1],
+                                               node.line or '', node.astext()))
             self.context.append('}\n')
         elif isinstance(parent, (nodes.topic, nodes.sidebar)):
             self.body.append(r'\textbf{')
 
     def visit_table(self, node):
         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.tablebody = []
         # Redirect body output until table is finished.
 
     def visit_entry(self, node):
         if node.has_key('morerows') or node.has_key('morecols'):
-            raise NotImplementedError('Column or row spanning cells are '
-                                      'not implemented.')
+            raise UnsupportedError('%s:%s: column or row spanning cells are '
+                                   'not yet implemented.' %
+                                   (self.curfilestack[-1], node.line or ''))
         if self.table.col > 0:
             self.body.append(' & ')
         self.table.col += 1
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.