Skip to content

Commit

Permalink
Merge pull request #2987 from plotly/fix/num-no-output-2986
Browse files Browse the repository at this point in the history
Fix multioutput requiring same number of no_update.
  • Loading branch information
T4rk1n authored Sep 6, 2024
2 parents 5a98989 + 2495492 commit 354d1a0
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).

## [UNRELEASED]

## Fixed

- [#2987](https://github.com/plotly/dash/pull/2987) Fix multioutput requiring same number of no_update. Fixes [#2986](https://github.com/plotly/dash/issues/2986)

## Deprecated

- [#2985](https://github.com/plotly/dash/pull/2985) Deprecate dynamic component loader.
Expand Down
14 changes: 9 additions & 5 deletions dash/_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,12 +528,16 @@ def add_context(*args, **kwargs):
# list or tuple
output_value = list(output_value)

# Flatten grouping and validate grouping structure
flat_output_values = flatten_grouping(output_value, output)
if NoUpdate.is_no_update(output_value):
flat_output_values = [output_value]
else:
# Flatten grouping and validate grouping structure
flat_output_values = flatten_grouping(output_value, output)

_validate.validate_multi_return(
output_spec, flat_output_values, callback_id
)
if not NoUpdate.is_no_update(output_value):
_validate.validate_multi_return(
output_spec, flat_output_values, callback_id
)

for val, spec in zip(flat_output_values, output_spec):
if NoUpdate.is_no_update(val):
Expand Down
35 changes: 34 additions & 1 deletion tests/integration/callbacks/test_missing_outputs.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import time

import pytest
from multiprocessing import Lock, Value

import dash
from dash import Dash, Input, Output, ALL, MATCH, html, dcc
from dash import Dash, Input, Output, ALL, MATCH, html, dcc, no_update

from dash.testing.wait import until

Expand Down Expand Up @@ -336,3 +338,34 @@ def chapter2_assertions():
dash_duo._wait_for_callbacks()
chapter2_assertions()
assert not dash_duo.get_logs()


def test_cbmo005_no_update_single_to_multi(dash_duo):
# Bugfix for #2986
app = dash.Dash(__name__)

app.layout = html.Div(
[
dcc.Input(id="input-box", type="text", value=""),
html.Button("Submit", id="button"),
html.Div(id="output-1", children="Output 1 will be displayed here"),
html.Div(id="output-2", children="Output 2 will be displayed here"),
]
)

@app.callback(
Output("output-1", "children"),
Output("output-2", "children"),
Input("button", "n_clicks"),
Input("input-box", "value"),
)
def update_outputs(n_clicks, value):
if n_clicks is None:
return no_update
return "Hello", "world!"

dash_duo.start_server(app)

# just wait to make sure the error get logged.
time.sleep(1)
assert dash_duo.get_logs() == []
3 changes: 3 additions & 0 deletions tests/integration/renderer/test_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

from dash import Dash, html, dcc, Input, Output

from flaky import flaky


@flaky(max_runs=3)
def test_rddp001_dependencies_on_components_that_dont_exist(dash_duo):
app = Dash(__name__, suppress_callback_exceptions=True)
app.layout = html.Div(
Expand Down

0 comments on commit 354d1a0

Please sign in to comment.