Merge pull request #2950 from tk0miya/2695_errhandling_on_setup_command

2695 errhandling on setup command
This commit is contained in:
Takeshi KOMIYA 2016-09-15 02:28:19 +09:00 committed by GitHub
commit cd515d568d
3 changed files with 69 additions and 73 deletions

View File

@ -115,6 +115,8 @@ Features added
* Add document about kindlegen and fix document structure for it.
* #2474: Add ``intersphinx_timeout`` option to ``sphinx.ext.intersphinx``
* #2926: EPUB3 builder supports vertical mode (``epub3_writing_mode`` option)
* #2695: ``build_sphinx`` subcommand for setuptools handles exceptions as same
as ``sphinx-build`` does
Bugs fixed
----------

View File

@ -55,6 +55,56 @@ class MyFormatter(optparse.IndentedHelpFormatter):
return "\n".join(result)
def handle_exception(app, opts, exception, stderr=sys.stderr):
if opts.pdb:
import pdb
print(red('Exception occurred while building, starting debugger:'),
file=stderr)
traceback.print_exc()
pdb.post_mortem(sys.exc_info()[2])
else:
print(file=stderr)
if opts.verbosity or opts.traceback:
traceback.print_exc(None, stderr)
print(file=stderr)
if isinstance(exception, KeyboardInterrupt):
print('interrupted!', file=stderr)
elif isinstance(exception, SystemMessage):
print(red('reST markup error:'), file=stderr)
print(terminal_safe(exception.args[0]), file=stderr)
elif isinstance(exception, SphinxError):
print(red('%s:' % exception.category), file=stderr)
print(terminal_safe(text_type(exception)), file=stderr)
elif isinstance(exception, UnicodeError):
print(red('Encoding error:'), file=stderr)
print(terminal_safe(text_type(exception)), file=stderr)
tbpath = save_traceback(app)
print(red('The full traceback has been saved in %s, if you want '
'to report the issue to the developers.' % tbpath),
file=stderr)
elif isinstance(exception, RuntimeError) and 'recursion depth' in str(exception):
print(red('Recursion error:'), file=stderr)
print(terminal_safe(text_type(exception)), file=stderr)
print(file=stderr)
print('This can happen with very large or deeply nested source '
'files. You can carefully increase the default Python '
'recursion limit of 1000 in conf.py with e.g.:', file=stderr)
print(' import sys; sys.setrecursionlimit(1500)', file=stderr)
else:
print(red('Exception occurred:'), file=stderr)
print(format_exception_cut_frames().rstrip(), file=stderr)
tbpath = save_traceback(app)
print(red('The full traceback has been saved in %s, if you '
'want to report the issue to the developers.' % tbpath),
file=stderr)
print('Please also report this if it was a user error, so '
'that a better error message can be provided next time.',
file=stderr)
print('A bug report can be filed in the tracker at '
'<https://github.com/sphinx-doc/sphinx/issues>. Thanks!',
file=stderr)
def main(argv):
if not color_terminal():
nocolor()
@ -243,52 +293,6 @@ def main(argv):
opts.warningiserror, opts.tags, opts.verbosity, opts.jobs)
app.build(opts.force_all, filenames)
return app.statuscode
except (Exception, KeyboardInterrupt) as err:
if opts.pdb:
import pdb
print(red('Exception occurred while building, starting debugger:'),
file=error)
traceback.print_exc()
pdb.post_mortem(sys.exc_info()[2])
else:
print(file=error)
if opts.verbosity or opts.traceback:
traceback.print_exc(None, error)
print(file=error)
if isinstance(err, KeyboardInterrupt):
print('interrupted!', file=error)
elif isinstance(err, SystemMessage):
print(red('reST markup error:'), file=error)
print(terminal_safe(err.args[0]), file=error)
elif isinstance(err, SphinxError):
print(red('%s:' % err.category), file=error)
print(terminal_safe(text_type(err)), file=error)
elif isinstance(err, UnicodeError):
print(red('Encoding error:'), file=error)
print(terminal_safe(text_type(err)), file=error)
tbpath = save_traceback(app)
print(red('The full traceback has been saved in %s, if you want '
'to report the issue to the developers.' % tbpath),
file=error)
elif isinstance(err, RuntimeError) and 'recursion depth' in str(err):
print(red('Recursion error:'), file=error)
print(terminal_safe(text_type(err)), file=error)
print(file=error)
print('This can happen with very large or deeply nested source '
'files. You can carefully increase the default Python '
'recursion limit of 1000 in conf.py with e.g.:', file=error)
print(' import sys; sys.setrecursionlimit(1500)', file=error)
else:
print(red('Exception occurred:'), file=error)
print(format_exception_cut_frames().rstrip(), file=error)
tbpath = save_traceback(app)
print(red('The full traceback has been saved in %s, if you '
'want to report the issue to the developers.' % tbpath),
file=error)
print('Please also report this if it was a user error, so '
'that a better error message can be provided next time.',
file=error)
print('A bug report can be filed in the tracker at '
'<https://github.com/sphinx-doc/sphinx/issues>. Thanks!',
file=error)
return 1
except (Exception, KeyboardInterrupt) as exc:
handle_exception(app, opts, exc, error)
return 1

View File

@ -15,15 +15,14 @@ from __future__ import print_function
import sys
import os
import traceback
from six import StringIO, string_types
from distutils.cmd import Command
from distutils.errors import DistutilsOptionError, DistutilsExecError
from six import StringIO, string_types
from sphinx.application import Sphinx
from sphinx.util.console import darkred, nocolor, color_terminal
from sphinx.cmdline import handle_exception
from sphinx.util.console import nocolor, color_terminal
from sphinx.util.osutil import abspath
@ -99,6 +98,8 @@ class BuildDoc(Command):
self.config_dir = None
self.link_index = False
self.copyright = ''
self.verbosity = 0
self.traceback = False
def _guess_source_dir(self):
for guess in ('doc', 'docs'):
@ -162,32 +163,21 @@ class BuildDoc(Command):
confoverrides['today'] = self.today
if self.copyright:
confoverrides['copyright'] = self.copyright
app = Sphinx(self.source_dir, self.config_dir,
self.builder_target_dir, self.doctree_dir,
self.builder, confoverrides, status_stream,
freshenv=self.fresh_env,
warningiserror=self.warning_is_error)
try:
app = Sphinx(self.source_dir, self.config_dir,
self.builder_target_dir, self.doctree_dir,
self.builder, confoverrides, status_stream,
freshenv=self.fresh_env,
warningiserror=self.warning_is_error)
app.build(force_all=self.all_files)
if app.statuscode:
raise DistutilsExecError(
'caused by %s builder.' % app.builder.name)
except Exception as err:
if self.pdb:
import pdb
print(darkred('Exception occurred while building, starting debugger:'),
file=sys.stderr)
traceback.print_exc()
pdb.post_mortem(sys.exc_info()[2])
else:
from docutils.utils import SystemMessage
if isinstance(err, SystemMessage):
print(darkred('reST markup error:'), file=sys.stderr)
print(err.args[0].encode('ascii', 'backslashreplace'),
file=sys.stderr)
else:
raise
except Exception as exc:
handle_exception(app, self, exc, sys.stderr)
if not self.pdb:
raise SystemExit(1)
if self.link_index:
src = app.config.master_doc + app.builder.out_suffix