From c3e993a83e20f823a9dacb513eaaa00fda400933 Mon Sep 17 00:00:00 2001 From: Remi Baar Date: Thu, 13 May 2021 17:02:31 +0200 Subject: [PATCH 1/4] `test_devtools_ui` - Test if dash will run when other `before_request` functions has been registered to flask This test validates issue #1624 The root of this issue lies in the devtools ui, and only occurs when the devtools ui has been enabled --- .../integration/devtools/test_devtools_ui.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/integration/devtools/test_devtools_ui.py b/tests/integration/devtools/test_devtools_ui.py index aa80714c08..6d19dc5f61 100644 --- a/tests/integration/devtools/test_devtools_ui.py +++ b/tests/integration/devtools/test_devtools_ui.py @@ -1,4 +1,5 @@ from time import sleep +import flask import dash_core_components as dcc import dash_html_components as html @@ -224,3 +225,38 @@ def set_b(a): dash_duo.wait_for_text_to_equal("#b", "xyz") dash_duo.wait_for_no_elements("._dash-undo-redo") + + +def test_dvui007_other_before_request_func(dash_thread_server, dash_br): + # won't use `bash_br`, because it expects an dash app, but it gets an static html page. + # we take only the selenium driver from `bash_br`, this driver has already been set-up. + driver = dash_br.driver + + app = dash.Dash(__name__) + app.layout = html.Div( + [html.P(id="just_an_id", children="You should never see this")] + ) + + # create alternative response, for the endpoint '/' + # servering an alternative response, will disable further `before_request` functions e.g. those by dash + @app.server.before_request + def create_an_alternative_response(): + if flask.request.endpoint == "/": + return flask.Response( + '\n' + "Alternative repsonse\n" + '

Alternative response header

\n', + 200, + mimetype="text/html", + ) + + dash_thread_server.start( + app, + debug=True, + use_reloader=False, + use_debugger=True, + dev_tools_hot_reload=False, + ) + + driver.get(dash_thread_server.url) + driver.find_element_by_id("alternative_id") From dc740a10dfa74a5e16fb133445655281ece1d73a Mon Sep 17 00:00:00 2001 From: Remi Baar Date: Thu, 13 May 2021 17:12:54 +0200 Subject: [PATCH 2/4] debug and dev_tools: Handle missing `timing_information` gracefully In some situations the `timing_information` is not present in `flask.g`. E.g. when other functions have been registerd to the flask `before_request_funcs`. Dash should anticipate and handle gracefully. Fixes #1624 --- dash/dash.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 16417345d5..470ceec807 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1468,10 +1468,16 @@ def _before_request(): } def _after_request(response): - dash_total = flask.g.timing_information["__dash_server"] - dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) + timing_information = flask.g.get("timing_information", None) + if timing_information is None: + return response - for name, info in flask.g.timing_information.items(): + timing_information_dash = timing_information.get("__dash_server", None) + if timing_information_dash is not None: + dash_total = timing_information["__dash_server"] + dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) + + for name, info in timing_information.items(): value = name if info.get("desc") is not None: From 88dde344aa4a59467b74c126824d8d1b0e6385c1 Mon Sep 17 00:00:00 2001 From: Remi Date: Sun, 16 May 2021 16:37:13 +0200 Subject: [PATCH 3/4] Remove code duplication for `timing_information` Co-authored-by: Alex Johnson --- dash/dash.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dash/dash.py b/dash/dash.py index 470ceec807..db283a366b 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -1472,9 +1472,8 @@ def _after_request(response): if timing_information is None: return response - timing_information_dash = timing_information.get("__dash_server", None) - if timing_information_dash is not None: - dash_total = timing_information["__dash_server"] + dash_total = timing_information.get("__dash_server", None) + if dash_total is not None: dash_total["dur"] = round((time.time() - dash_total["dur"]) * 1000) for name, info in timing_information.items(): From 9c39768f8f4eb1b7321e1308f59b4c4b98f5a43f Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Mon, 17 May 2021 08:34:24 -0400 Subject: [PATCH 4/4] Changelog for timing_information fix --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e35f161292..62aa8afc0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to `dash` will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/). +## [UNRELEASED] +### Fixed +- [#1640](https://github.com/plotly/dash/pull/1640) Fix [#1475](https://github.com/plotly/dash/issues/1475), missing `timing_information` after certain modifications to Flask behavior + ## [1.20.0] - 2021-04-08 ## Dash and Dash Renderer