blob: 9e2569533635978066970f3b18c1a6a0ef287616 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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)
|