Skip to content

Commit

Permalink
Add new print_traceback configuration option
Browse files Browse the repository at this point in the history
Allow the full traceback to be printed when Sphinx encounters an
internal fatal error.
  • Loading branch information
kdeldycke committed Dec 3, 2024
1 parent df3d94f commit 6494db7
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 13 deletions.
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ Deprecated
Features added
--------------

* #13163: Add the :confval:`print_traceback` configuration option
to control whether tracebacks are printed in full when Sphinx
encounters an internal error.
Patch by Kevin Deldycke.

Bugs fixed
----------

Expand Down
15 changes: 15 additions & 0 deletions doc/usage/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,21 @@ General configuration
(or, if translation is enabled with :confval:`language`,
an equivalent format for the selected locale).

.. confval:: print_traceback
:type: :code-py:`bool`
:default: :code-py:`True`

If :code-py:`False`, the full traceback will not be printed when Sphinx
encounters an internal fatal error. It will instead print a short message
and exit.

.. note::

Whatever the setting is set to, the traceback is always saved in a
temporary file named ``sphinx-err-xxxxxxxx.log``.

.. versionadded:: 8.2.0


Options for figure numbering
----------------------------
Expand Down
12 changes: 8 additions & 4 deletions sphinx/_cli/util/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def error_info(messages: str, extensions: str, traceback: str) -> str:
"""


def save_traceback(app: Sphinx | None, exc: BaseException) -> str:
def save_traceback(app: Sphinx | None, exc: BaseException) -> tuple[str, str]:
"""Save the given exception's traceback in a temporary file."""
if isinstance(exc, SphinxParallelError):
exc_format = '(Error in parallel process)\n' + exc.traceback
Expand All @@ -78,12 +78,14 @@ def save_traceback(app: Sphinx | None, exc: BaseException) -> str:
if ext.version != 'builtin'
)

output = error_info(last_msgs, exts_list, exc_format)

with tempfile.NamedTemporaryFile(
suffix='.log', prefix='sphinx-err-', delete=False
) as f:
f.write(error_info(last_msgs, exts_list, exc_format).encode('utf-8'))
f.write(output.encode('utf-8'))

return f.name
return f.name, output


def handle_exception(
Expand Down Expand Up @@ -164,7 +166,9 @@ def print_red(*values: str) -> None:

print_red(__('Exception occurred:'))
print_err(formatted_tb)
traceback_info_path = save_traceback(app, exception)
traceback_info_path, traceback_output = save_traceback(app, exception)
if not app or app.config.print_traceback:
print_err(traceback_output)
print_err(__('The full traceback has been saved in:'))
print_err(traceback_info_path)
print_err()
Expand Down
8 changes: 6 additions & 2 deletions sphinx/cmd/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ def handle_exception(
elif isinstance(exception, UnicodeError):
print(red(__('Encoding error:')), file=stderr)
print(terminal_safe(str(exception)), file=stderr)
tbpath = save_traceback(app, exception)
tbpath, tboutput = save_traceback(app, exception)
if not app or app.config.print_traceback:
print(tboutput)
print(
red(
__(
Expand Down Expand Up @@ -102,7 +104,9 @@ def handle_exception(
else:
print(red(__('Exception occurred:')), file=stderr)
print(format_exception_cut_frames().rstrip(), file=stderr)
tbpath = save_traceback(app, exception)
tbpath, tboutput = save_traceback(app, exception)
if not app or app.config.print_traceback:
print(tboutput)
print(
red(
__(
Expand Down
1 change: 1 addition & 0 deletions sphinx/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ class Config:
'today': _Opt('', 'env', ()),
# the real default is locale-dependent
'today_fmt': _Opt(None, 'env', frozenset((str,))),
'print_traceback': _Opt(True, 'env', ()),

'language': _Opt('en', 'env', frozenset((str,))),
'locale_dirs': _Opt(['locales'], 'env', ()),
Expand Down
16 changes: 9 additions & 7 deletions sphinx/util/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from sphinx.application import Sphinx


def save_traceback(app: Sphinx | None, exc: BaseException) -> str:
def save_traceback(app: Sphinx | None, exc: BaseException) -> tuple[str, str]:
"""Save the given exception's traceback in a temporary file."""
import platform

Expand Down Expand Up @@ -40,10 +40,7 @@ def save_traceback(app: Sphinx | None, exc: BaseException) -> str:
if ext.version != 'builtin'
)

with NamedTemporaryFile(
'w', encoding='utf-8', suffix='.log', prefix='sphinx-err-', delete=False
) as f:
f.write(f"""\
output = f"""\
# Platform: {sys.platform}; ({platform.platform()})
# Sphinx version: {sphinx.__display_version__}
# Python version: {platform.python_version()} ({platform.python_implementation()})
Expand All @@ -59,8 +56,13 @@ def save_traceback(app: Sphinx | None, exc: BaseException) -> str:
# Traceback:
{exc_format}
""")
return f.name
"""

with NamedTemporaryFile(
'w', encoding='utf-8', suffix='.log', prefix='sphinx-err-', delete=False
) as f:
f.write(output)
return f.name, output


def format_exception_cut_frames(x: int = 1) -> str:
Expand Down

0 comments on commit 6494db7

Please sign in to comment.