summaryrefslogtreecommitdiffstats
path: root/sphinx/util/exceptions.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/util/exceptions.py')
-rw-r--r--sphinx/util/exceptions.py67
1 files changed, 67 insertions, 0 deletions
diff --git a/sphinx/util/exceptions.py b/sphinx/util/exceptions.py
new file mode 100644
index 0000000..9e25695
--- /dev/null
+++ b/sphinx/util/exceptions.py
@@ -0,0 +1,67 @@
+from __future__ import annotations
+
+import sys
+import traceback
+from tempfile import NamedTemporaryFile
+from typing import TYPE_CHECKING
+
+from sphinx.errors import SphinxParallelError
+from sphinx.util.console import strip_colors
+
+if TYPE_CHECKING:
+ from sphinx.application import Sphinx
+
+
+def save_traceback(app: Sphinx | None, exc: BaseException) -> str:
+ """Save the given exception's traceback in a temporary file."""
+ import platform
+
+ import docutils
+ import jinja2
+ import pygments
+
+ import sphinx
+
+ if isinstance(exc, SphinxParallelError):
+ exc_format = '(Error in parallel process)\n' + exc.traceback
+ else:
+ exc_format = traceback.format_exc()
+
+ if app is None:
+ last_msgs = exts_list = ''
+ else:
+ extensions = app.extensions.values()
+ last_msgs = '\n'.join(f'# {strip_colors(s).strip()}' for s in app.messagelog)
+ exts_list = '\n'.join(f'# {ext.name} ({ext.version})' for ext in extensions
+ if ext.version != 'builtin')
+
+ with NamedTemporaryFile('w', suffix='.log', prefix='sphinx-err-', delete=False) as f:
+ f.write(f"""\
+# Platform: {sys.platform}; ({platform.platform()})
+# Sphinx version: {sphinx.__display_version__}
+# Python version: {platform.python_version()} ({platform.python_implementation()})
+# Docutils version: {docutils.__version__}
+# Jinja2 version: {jinja2.__version__}
+# Pygments version: {pygments.__version__}
+
+# Last messages:
+{last_msgs}
+
+# Loaded extensions:
+{exts_list}
+
+# Traceback:
+{exc_format}
+""")
+ return f.name
+
+
+def format_exception_cut_frames(x: int = 1) -> str:
+ """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: list[str] = []
+ tbres = traceback.format_tb(tb)
+ res += tbres[-x:]
+ res += traceback.format_exception_only(typ, val)
+ return ''.join(res)