Skip to content

Commit 4190e5d

Browse files
authored
Merge pull request #138 from plotly/circular_callbacks
Removed unnecessary checks for the validity of callbacks
2 parents e6d713d + 9453d68 commit 4190e5d

File tree

5 files changed

+44
-49
lines changed

5 files changed

+44
-49
lines changed

src/app/callbacks.jl

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,21 +165,11 @@ function check_callback(func, app::DashApp, deps::CallbackDeps)
165165
isempty(deps.output) && error("The callback method requires that one or more properly formatted outputs are passed.")
166166
isempty(deps.input) && error("The callback method requires that one or more properly formatted inputs are passed.")
167167

168-
!check_unique(deps.output) && error("One or more callback outputs have been duplicated; please confirm that all outputs are unique.")
169-
170-
for out in deps.output
171-
if any(x->out in x.dependencies.output, values(app.callbacks))
172-
error("output \"$(out)\" already registered")
173-
end
174-
end
175168

176169
args_count = length(deps.state) + length(deps.input)
177170

178171
check_callback_func(func, args_count)
179172

180-
for id_prop in deps.input
181-
id_prop in deps.output && error("Circular input and output arguments were found. Please verify that callback outputs are not also input arguments.")
182-
end
183173
end
184174

185175
function check_callback_func(func::Function, args_count)

src/handler/callback_context.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using .Contexts
22
const CallbackContextItems = Union{Nothing, Vector{NamedTuple}}
33
const TriggeredParam = NamedTuple{(:prop_id, :value)}
4+
5+
46
mutable struct CallbackContext
57
response::HTTP.Response
68
inputs::Dict{String, Any}
@@ -19,16 +21,16 @@ end
1921

2022
const _callback_context_storage = TaskContextStorage()
2123

22-
function with_callback_context(f, context::CallbackContext)
24+
function with_callback_context(f, context::CallbackContext)
2325
return with_context(f, _callback_context_storage, context)
24-
end
26+
end
2527

2628
"""
2729
callback_context()::CallbackContext
2830
2931
Get context of current callback, available only inside callback processing function
3032
"""
31-
function callback_context()
33+
function callback_context()
3234
!has_context(_callback_context_storage) && error("callback_context() is only available from a callback processing function")
3335
return get_context(_callback_context_storage)
3436
end

test/callbacks.jl

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -260,32 +260,6 @@ end
260260
@test app.callbacks[Symbol("my-div.children")].func("value") == "value"
261261
@test app.callbacks[Symbol("my-div2.children")].func("value") == "v_value"
262262

263-
#output already exists
264-
@test_throws ErrorException callback!(app, Output("my-div2","children"), Input("my-id","value")) do value
265-
return "v_$(value)"
266-
end
267-
268-
#output same as input
269-
@test_throws ErrorException callback!(app,
270-
Output("my-id","value"),
271-
Input("my-id","value"),
272-
State("my-id","value")) do value
273-
return "v_$(value)"
274-
end
275-
276-
#output same as input
277-
@test_throws ErrorException callback!(app,
278-
Output("my-id","value"),
279-
[Input("my-id","value"), Input("my-div","children")]) do value
280-
return "v_$(value)"
281-
end
282-
283-
#output same as input
284-
@test_throws ErrorException callback!(app,
285-
[Output("my-id","value"), Output("my-div","children")],
286-
Input("my-id","value")) do value
287-
return "v_$(value)"
288-
end
289263

290264
#empty input
291265
@test_throws ErrorException callback!(app,
@@ -295,13 +269,6 @@ end
295269
end
296270

297271

298-
#duplicated output
299-
@test_throws ErrorException callback!(app,
300-
[Output("my-div","value"), Output("my-div","value")],
301-
Input("my-id","value")) do value
302-
return "v_$(value)"
303-
end
304-
305272
app = dash()
306273

307274
app.layout = html_div() do
@@ -339,6 +306,36 @@ end
339306

340307
end
341308

309+
@testset "empty triggered params" begin
310+
app = dash()
311+
app.layout = html_div() do
312+
dcc_input(id = "test-in", value="initial value", type = "text"),
313+
html_div(id = "test-out")
314+
end
315+
316+
callback!(app, Output("test-out", "children"), Input("test-out", "value")) do value
317+
context = callback_context()
318+
@test length(context.triggered) == 0
319+
@test isempty(context.triggered)
320+
return string(value)
321+
end
322+
@test length(app.callbacks) == 1
323+
324+
handler = Dash.make_handler(app)
325+
request = (
326+
output = "test-out.children",
327+
changedPropIds = [],
328+
inputs = [
329+
(id = "test-in", property = "value", value = "test")
330+
]
331+
)
332+
test_json = JSON2.write(request)
333+
request = HTTP.Request("POST", "/_dash-update-component", [], Vector{UInt8}(test_json))
334+
response = HTTP.handle(handler, request)
335+
336+
@test response.status == 200
337+
338+
end
342339
@testset "pattern-match" begin
343340
app = dash()
344341
app.layout = html_div() do

test/integration/callbacks/jl_test_wildcards/jlcbwc004_layout_chunk_changed_props.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,14 @@ end
2424

2525
function trigger_info()
2626
triggered = callback_context().triggered
27-
trig_string = !isempty(triggered) ? "Truthy" : "Falsy"
28-
prop_ids = join(getproperty.(triggered, :prop_id), ", ")
27+
trig_string = ""
28+
prop_ids = ""
29+
if isempty(triggered)
30+
trig_string = "Falsy"
31+
else
32+
trig_string = "Truthy"
33+
prop_ids = join(getproperty.(triggered, :prop_id), ", ")
34+
end
2935
return "triggered is $trig_string with prop_ids $prop_ids"
3036
end
3137

test/integration/callbacks/test_wildcards.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ def test_jlcbwc004_layout_chunk_changed_props(dashjl):
174174

175175
dashjl.wait_for_text_to_equal("#container", "No content initially", timeout = 10)
176176
dashjl.wait_for_text_to_equal(
177-
"#output-outer", "triggered is Falsy with prop_ids", timeout = 10
177+
"#output-outer", "triggered is Falsy with prop_ids", timeout = 30
178178
)
179179

180180
dashjl.find_element("#btn").click()

0 commit comments

Comments
 (0)