Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.

Commit 9384bfd

Browse files
committed
Customize the stack trace to place function argument values on separate lines
1 parent 0201a83 commit 9384bfd

File tree

1 file changed

+54
-13
lines changed

1 file changed

+54
-13
lines changed

jupyter_dash/jupyter_app.py

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import io
99
import re
1010
import sys
11+
import inspect
1112

1213
from IPython.display import IFrame, display
1314
from IPython.core.ultratb import FormattedTB
@@ -299,28 +300,39 @@ def _wrap_errors(_):
299300
self._traceback = sys.exc_info()[2]
300301

301302
# Compute number of stack frames to skip to get down to callback
302-
tb = get_current_traceback()
303+
tb_werkzeug = get_current_traceback()
303304
skip = 0
304305
if dev_tools_prune_errors:
305-
for i, line in enumerate(tb.plaintext.splitlines()):
306+
for i, line in enumerate(tb_werkzeug.plaintext.splitlines()):
306307
if "%% callback invoked %%" in line:
307308
skip = int((i + 1) / 2)
308309
break
309310

310-
# Use IPython traceback formatting to build colored ANSI traceback string
311-
ostream = io.StringIO()
312-
ipytb = FormattedTB(
313-
tb_offset=skip,
314-
mode="Verbose",
315-
color_scheme="Linux",
316-
include_vars=True,
317-
ostream=ostream
318-
)
319-
ipytb()
311+
# Customized formatargvalues function so we can place function parameters
312+
# on separate lines
313+
original_formatargvalues = inspect.formatargvalues
314+
inspect.formatargvalues = custom_formatargvalues
315+
try:
316+
# Use IPython traceback formatting to build colored ANSI traceback
317+
# string
318+
ostream = io.StringIO()
319+
ipytb = FormattedTB(
320+
tb_offset=skip,
321+
mode="Verbose",
322+
color_scheme="Linux",
323+
include_vars=True,
324+
ostream=ostream
325+
)
326+
ipytb()
327+
finally:
328+
# Restore formatargvalues
329+
inspect.formatargvalues = original_formatargvalues
320330

321331
# Print colored ANSI representation if requested
332+
ansi_stacktrace = ostream.getvalue()
333+
322334
if inline_exceptions:
323-
print(ostream.getvalue())
335+
print(ansi_stacktrace)
324336

325337
# Use ansi2html to convert the colored ANSI string to HTML
326338
conv = Ansi2HTMLConverter(scheme="ansi2html", dark_bg=False)
@@ -346,3 +358,32 @@ def _terminate_server_for_port(cls, host, port):
346358
response = requests.get(shutdown_url)
347359
except Exception as e:
348360
pass
361+
362+
363+
def custom_formatargvalues(
364+
args, varargs, varkw, locals,
365+
formatarg=str,
366+
formatvarargs=lambda name: '*' + name,
367+
formatvarkw=lambda name: '**' + name,
368+
formatvalue=lambda value: '=' + repr(value)):
369+
370+
"""Copied from inspect.formatargvalues, modified to place function
371+
arguments on separate lines"""
372+
def convert(name, locals=locals,
373+
formatarg=formatarg, formatvalue=formatvalue):
374+
return formatarg(name) + formatvalue(locals[name])
375+
specs = []
376+
for i in range(len(args)):
377+
specs.append(convert(args[i]))
378+
if varargs:
379+
specs.append(formatvarargs(varargs) + formatvalue(locals[varargs]))
380+
if varkw:
381+
specs.append(formatvarkw(varkw) + formatvalue(locals[varkw]))
382+
383+
result = '(' + ', '.join(specs) + ')'
384+
385+
if len(result) < 40:
386+
return result
387+
else:
388+
# Put each arg on a separate line
389+
return '(\n ' + ',\n '.join(specs) + '\n)'

0 commit comments

Comments
 (0)