From f9079bfd8a9576947655e1fee0dc343171c21e37 Mon Sep 17 00:00:00 2001 From: philippe Date: Tue, 29 Mar 2022 12:17:40 -0400 Subject: [PATCH] Fix werkzeug 2.1.0 import & dev tools error html rendering. --- .../error/FrontEnd/FrontEndError.react.js | 2 +- dash/dash.py | 42 +++++++++++++++---- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js b/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js index 5703add4..49939ea1 100644 --- a/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js +++ b/dash/dash-renderer/src/components/error/FrontEnd/FrontEndError.react.js @@ -110,7 +110,7 @@ function UnconnectedErrorContent({error, base}) { )} {/* Backend Error */} {typeof error.html !== 'string' ? null : error.html.indexOf( - '
diff --git a/dash/dash.py b/dash/dash.py index b4a3adf0..3d5dae25 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -19,7 +19,10 @@ from future.moves.urllib.parse import urlparse import flask from flask_compress import Compress -from werkzeug.debug.tbtools import get_current_traceback + +from werkzeug.debug import tbtools +from werkzeug.security import gen_salt + from pkg_resources import get_distribution, parse_version import plotly @@ -91,6 +94,30 @@ _re_index_scripts_id = 'src="[^"]*dash[-_]renderer[^"]*"', "dash-renderer" _re_renderer_scripts_id = 'id="_dash-renderer', "new DashRenderer" +def _get_traceback(secret, error): + def _get_skip(text): + skip = 0 + for i, line in enumerate(text.splitlines()): + if "%% callback invoked %%" in line: + skip = int((i + 1) / 2) + break + return skip + + # werkzeug<2.1.0 + if hasattr(tbtools, "get_current_traceback"): + tb = tbtools.get_current_traceback() + skip = _get_skip(tb.plaintext) + return tbtools.get_current_traceback(skip=skip).render_full() + + tb = tbtools.DebugTraceback(error) # pylint: disable=no-member + skip = _get_skip(tb.render_traceback_text()) + + # pylint: disable=no-member + return tbtools.DebugTraceback(error, skip=skip).render_debugger_html( + True, secret, True + ) + + class _NoUpdate(object): # pylint: disable=too-few-public-methods pass @@ -1463,19 +1490,16 @@ class Dash(object): if debug and dev_tools.prune_errors: + secret = gen_salt(20) + @self.server.errorhandler(Exception) - def _wrap_errors(_): + def _wrap_errors(error): # find the callback invocation, if the error is from a callback # and skip the traceback up to that point # if the error didn't come from inside a callback, we won't # skip anything. - tb = get_current_traceback() - skip = 0 - for i, line in enumerate(tb.plaintext.splitlines()): - if "%% callback invoked %%" in line: - skip = int((i + 1) / 2) - break - return get_current_traceback(skip=skip).render_full(), 500 + tb = _get_traceback(secret, error) + return tb, 500 if debug and dev_tools.ui: -- 2.35.1