Skip to content

Commit 707399b

Browse files
committed
Add custom_data hook
1 parent 61ff4f6 commit 707399b

File tree

4 files changed

+46
-1
lines changed

4 files changed

+46
-1
lines changed

dash/_callback_context.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,11 @@ def origin(self):
304304
"""
305305
return _get_from_context("origin", "")
306306

307+
@property
308+
@has_context
309+
def custom_data(self):
310+
return _get_from_context("custom_data", {})
311+
307312

308313
callback_context = CallbackContext()
309314

dash/_hooks.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def __init__(self) -> None:
4545
"error": [],
4646
"callback": [],
4747
"index": [],
48+
"custom_data": [],
4849
}
4950
self._js_dist = []
5051
self._css_dist = []
@@ -191,6 +192,19 @@ def wrap(func):
191192

192193
return wrap
193194

195+
def custom_data(self, namespace, priority: _t.Optional[int] = None, final=False):
196+
def wrap(func):
197+
self.add_hook(
198+
"custom_data",
199+
func,
200+
priority=priority,
201+
final=final,
202+
data={"namespace": namespace},
203+
)
204+
return func
205+
206+
return wrap
207+
194208

195209
hooks = _Hooks()
196210

dash/dash.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,10 @@ def dispatch(self):
13891389
g.path = flask.request.full_path
13901390
g.remote = flask.request.remote_addr
13911391
g.origin = flask.request.origin
1392+
g.custom_data = AttributeDict({})
1393+
1394+
for hook in self._hooks.get_hooks("custom_data"):
1395+
g.custom_data[hook.data["namespace"]] = hook(g)
13921396

13931397
except KeyError as missing_callback_function:
13941398
msg = f"Callback function not found for output '{output}', perhaps you forgot to prepend the '@'?"

tests/integration/test_hooks.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import requests
33
import pytest
44

5-
from dash import Dash, Input, Output, html, hooks, set_props
5+
from dash import Dash, Input, Output, html, hooks, set_props, ctx
66

77

88
@pytest.fixture
@@ -14,6 +14,7 @@ def hook_cleanup():
1414
hooks._ns["error"] = []
1515
hooks._ns["callback"] = []
1616
hooks._ns["index"] = []
17+
hooks._ns["custom_data"] = []
1718
hooks._css_dist = []
1819
hooks._js_dist = []
1920
hooks._finals = {}
@@ -188,3 +189,24 @@ def test_hook009_hook_clientside_callback(hook_cleanup, dash_duo):
188189

189190
dash_duo.wait_for_element("#hook-start").click()
190191
dash_duo.wait_for_text_to_equal("#hook-output", "Called 1")
192+
193+
194+
def test_hook010_hook_custom_data(hook_cleanup, dash_duo):
195+
@hooks.custom_data("custom")
196+
def custom_data(_):
197+
return "custom-data"
198+
199+
app = Dash()
200+
app.layout = [html.Button("insert", id="btn"), html.Div(id="output")]
201+
202+
@app.callback(
203+
Output("output", "children"),
204+
Input("btn", "n_clicks"),
205+
prevent_initial_call=True,
206+
)
207+
def cb(_):
208+
return ctx.custom_data.custom
209+
210+
dash_duo.start_server(app)
211+
dash_duo.wait_for_element("#btn").click()
212+
dash_duo.wait_for_text_to_equal("#output", "custom-data")

0 commit comments

Comments
 (0)