19
19
import flask
20
20
from flask import Flask , Response
21
21
from flask_compress import Compress
22
+ from werkzeug .debug .tbtools import get_current_traceback
22
23
23
24
import plotly
24
25
import dash_renderer
@@ -1168,7 +1169,8 @@ def callback(self, output, inputs=[], state=[]):
1168
1169
def wrap_func (func ):
1169
1170
@wraps (func )
1170
1171
def add_context (* args , ** kwargs ):
1171
- output_value = func (* args , ** kwargs )
1172
+ # don't touch the comment on the next line - used by debugger
1173
+ output_value = func (* args , ** kwargs ) # %% callback invoked %%
1172
1174
if multi :
1173
1175
if not isinstance (output_value , (list , tuple )):
1174
1176
raise exceptions .InvalidCallbackReturnValue (
@@ -1390,7 +1392,8 @@ def _setup_dev_tools(self, **kwargs):
1390
1392
'props_check' ,
1391
1393
'serve_dev_bundles' ,
1392
1394
'hot_reload' ,
1393
- 'silence_routes_logging'
1395
+ 'silence_routes_logging' ,
1396
+ 'prune_errors'
1394
1397
):
1395
1398
dev_tools [attr ] = get_combined_config (
1396
1399
attr , kwargs .get (attr , None ), default = debug
@@ -1419,7 +1422,8 @@ def enable_dev_tools(
1419
1422
dev_tools_hot_reload_interval = None ,
1420
1423
dev_tools_hot_reload_watch_interval = None ,
1421
1424
dev_tools_hot_reload_max_retry = None ,
1422
- dev_tools_silence_routes_logging = None ):
1425
+ dev_tools_silence_routes_logging = None ,
1426
+ dev_tools_prune_errors = None ):
1423
1427
"""
1424
1428
Activate the dev tools, called by `run_server`. If your application is
1425
1429
served by wsgi and you want to activate the dev tools, you can call
@@ -1483,6 +1487,11 @@ def enable_dev_tools(
1483
1487
env: ``DASH_SILENCE_ROUTES_LOGGING``
1484
1488
:type dev_tools_silence_routes_logging: bool
1485
1489
1490
+ :param dev_tools_prune_errors: Reduce tracebacks to just user code,
1491
+ stripping out Flask and Dash pieces. `True` by default, set to
1492
+ `False` to see the complete traceback.
1493
+ :type dev_tools_prune_errors: bool
1494
+
1486
1495
:return: debug
1487
1496
"""
1488
1497
if debug is None :
@@ -1497,7 +1506,8 @@ def enable_dev_tools(
1497
1506
hot_reload_interval = dev_tools_hot_reload_interval ,
1498
1507
hot_reload_watch_interval = dev_tools_hot_reload_watch_interval ,
1499
1508
hot_reload_max_retry = dev_tools_hot_reload_max_retry ,
1500
- silence_routes_logging = dev_tools_silence_routes_logging
1509
+ silence_routes_logging = dev_tools_silence_routes_logging ,
1510
+ prune_errors = dev_tools_prune_errors
1501
1511
)
1502
1512
1503
1513
if dev_tools .silence_routes_logging :
@@ -1527,6 +1537,21 @@ def enable_dev_tools(
1527
1537
_reload .watch_thread .daemon = True
1528
1538
_reload .watch_thread .start ()
1529
1539
1540
+ if debug and dev_tools .prune_errors :
1541
+ @self .server .errorhandler (Exception )
1542
+ def _wrap_errors (_ ):
1543
+ # find the callback invocation, if the error is from a callback
1544
+ # and skip the traceback up to that point
1545
+ # if the error didn't come from inside a callback, we won't
1546
+ # skip anything.
1547
+ tb = get_current_traceback ()
1548
+ skip = 0
1549
+ for i , line in enumerate (tb .plaintext .splitlines ()):
1550
+ if "%% callback invoked %%" in line :
1551
+ skip = int ((i + 1 ) / 2 )
1552
+ break
1553
+ return get_current_traceback (skip = skip ).render_full (), 500
1554
+
1530
1555
if (debug and dev_tools .serve_dev_bundles and
1531
1556
not self .scripts .config .serve_locally ):
1532
1557
# Dev bundles only works locally.
@@ -1594,6 +1619,7 @@ def run_server(
1594
1619
dev_tools_hot_reload_watch_interval = None ,
1595
1620
dev_tools_hot_reload_max_retry = None ,
1596
1621
dev_tools_silence_routes_logging = None ,
1622
+ dev_tools_prune_errors = None ,
1597
1623
** flask_run_options ):
1598
1624
"""
1599
1625
Start the flask server in local mode, you should not run this on a
@@ -1652,6 +1678,11 @@ def run_server(
1652
1678
env: ``DASH_SILENCE_ROUTES_LOGGING``
1653
1679
:type dev_tools_silence_routes_logging: bool
1654
1680
1681
+ :param dev_tools_prune_errors: Reduce tracebacks to just user code,
1682
+ stripping out Flask and Dash pieces. Only available with debugging.
1683
+ `True` by default, set to `False` to see the complete traceback.
1684
+ :type dev_tools_prune_errors: bool
1685
+
1655
1686
:param flask_run_options: Given to `Flask.run`
1656
1687
1657
1688
:return:
@@ -1666,6 +1697,7 @@ def run_server(
1666
1697
dev_tools_hot_reload_watch_interval ,
1667
1698
dev_tools_hot_reload_max_retry ,
1668
1699
dev_tools_silence_routes_logging ,
1700
+ dev_tools_prune_errors
1669
1701
)
1670
1702
1671
1703
if self ._dev_tools .silence_routes_logging :
0 commit comments