Improve handling of exceptions.

This commit is contained in:
Georg Brandl 2008-03-18 19:17:56 +00:00
parent 4eaf9b5da5
commit d3c0de7d62
3 changed files with 66 additions and 20 deletions

View File

@ -12,11 +12,15 @@
import os
import sys
import getopt
import traceback
from os import path
from cStringIO import StringIO
from docutils.utils import SystemMessage
from sphinx.util import format_exception_cut_frames, save_traceback
from sphinx.application import Sphinx
from sphinx.util.console import nocolor
from sphinx.util.console import darkred, nocolor
__revision__ = '$Revision$'
__version__ = '0.1.' + __revision__[11:-2]
@ -27,8 +31,9 @@ def usage(argv, msg=None):
print >>sys.stderr, msg
print >>sys.stderr
print >>sys.stderr, """\
usage: %s [options] sourcedir outdir [filenames...]"
options: -b <builder> -- builder to use; default is html
Sphinx v%s
Usage: %s [options] sourcedir outdir [filenames...]"
Options: -b <builder> -- builder to use; default is html
-a -- write all files; default is to only write new and changed files
-E -- don't use a saved environment, always read all files
-d <path> -- path for the cached environment and doctree files
@ -37,10 +42,10 @@ options: -b <builder> -- builder to use; default is html
-N -- do not do colored output
-q -- no output on stdout, just warnings on stderr
-P -- run Pdb on exception
modi:
Modi:
* without -a and without filenames, write new and changed files.
* with -a, write all files.
* with filenames, write these.""" % (argv[0],)
* with filenames, write these.""" % (__version__, argv[0])
def main(argv=sys.argv):
@ -104,24 +109,43 @@ def main(argv=sys.argv):
elif opt == '-P':
use_pdb = True
try:
app = Sphinx(srcdir, outdir, doctreedir, buildername,
confoverrides, status, sys.stderr, freshenv)
if not app.builder:
return 1
try:
if all_files:
app.builder.build_all()
elif filenames:
app.builder.build_specific(filenames)
else:
app.builder.build_update()
except:
if not use_pdb:
raise
import pdb, traceback
except Exception, err:
if use_pdb:
import pdb
print >>sys.stderr, darkred('Exception occurred while building, '
'starting debugger:')
traceback.print_exc()
pdb.post_mortem(sys.exc_info()[2])
else:
if isinstance(err, SystemMessage):
print >>sys.stderr, darkred('reST markup error:')
print >>sys.stderr, str(err)
else:
print >>sys.stderr, darkred('Exception occurred:')
print >>sys.stderr, format_exception_cut_frames().rstrip()
tbpath = save_traceback()
print >>sys.stderr, darkred('The full traceback has been saved '
'in %s, if you want to report the '
'issue to the author.' % tbpath)
print >>sys.stderr, ('Please also report this if it was a user '
'error, so that a better error message '
'can be provided next time.')
print >>sys.stderr, 'Send reports to georg@python.org. Thanks!'
except:
# catches BaseExceptions in 2.5 -- SystemExit, KeyboardInterrupt
pass
if __name__ == '__main__':

View File

@ -56,6 +56,7 @@ class Builder(object):
self.warn = app.warn
self.info = app.info
self.config = app.config
1/0
# if None, this is set in load_env()
self.env = env
@ -240,11 +241,7 @@ class Builder(object):
self.env.set_warnfunc(warnings.append)
for docname in self.status_iterator(sorted(docnames),
'writing output... ', darkgreen):
try:
doctree = self.env.get_and_resolve_doctree(docname, self)
except Exception, err:
warnings.append('%s:: doctree not found!' % docname)
continue
self.write_doc(docname, doctree)
for warning in warnings:
if warning.strip():

View File

@ -12,6 +12,7 @@
import os
import sys
import fnmatch
import tempfile
import traceback
from os import path
@ -120,3 +121,27 @@ def rpartition(s, t):
if i != -1:
return s[:i], s[i+len(t):]
return '', s
def format_exception_cut_frames(x=1):
"""
Format an exception with traceback, but only the last x frames.
"""
typ, val, tb = sys.exc_info()
#res = ['Traceback (most recent call last):\n']
res = []
tbres = traceback.format_tb(tb)
res += tbres[-x:]
res += traceback.format_exception_only(typ, val)
return ''.join(res)
def save_traceback():
"""
Save the current exception's traceback in a temporary file.
"""
exc = traceback.format_exc()
fd, path = tempfile.mkstemp('.log', 'sphinx-err-')
os.write(fd, exc)
os.close(fd)
return path