Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added PreventUpdate exception and attached handler to Flask server #190

Merged
merged 5 commits into from
Jan 19, 2018

Conversation

ned2
Copy link
Contributor

@ned2 ned2 commented Jan 5, 2018

create a new exception PreventUpdate for use when a callback needs to be aborted without updating the state of the client.

This exception is registered with the Flask server using an errorhandler such that on catching this exception Flask will print any message included in the exception to standard error and then return an empty 204 NO CONTENT response.

@ned2
Copy link
Contributor Author

ned2 commented Jan 5, 2018

Oops, I forgot about Python 2. I hope importing the print function from future is ok. Without this I don't really know of an clean way to print to stderr. But now I think about it, it's not clear this message should be going to stderr. thoughts?

Also, tests are failing because of #189.

@chriddyp
Copy link
Member

chriddyp commented Jan 9, 2018

This looks good to me. I think we should add an integration test in here to lock down the behaviour. These tests would go in here: https://github.com/plotly/dash/blob/308579660b8791296f437bdcd060dc89a42f2b07/tests/test_integration.py. We basically want to check that raising this exception inside a callback will indeed:
1 - Not update the output
2 - Not trigger the output's dependencies

Let me know if you need some help with this!

I hope importing the print function from __future__ is ok

From https://stackoverflow.com/questions/5574702/how-to-print-to-stderr-in-python, it seems OK. In any case, if we add an integration test then we'll know for sure 🙂

@chriddyp
Copy link
Member

chriddyp commented Jan 9, 2018

Also #189 has been merged, so we can rebase this branch off master and the baseline tests should be fixed

@ned2 ned2 force-pushed the add-prevent-update-exception branch from 8a46164 to edd2a8c Compare January 13, 2018 01:53
@ned2
Copy link
Contributor Author

ned2 commented Jan 13, 2018

I rebased off master and tests are passing again :)

I also added an integration test that hopefully addresses the criteria you described.

One thing that was unexpected is that apparently callback2, which is the one that is dependant on the one that is aborted is never triggered, even on the initial page load. Is this expected? My intuitions are that callback2 should have been run once on the initial page load given that output1 is present in the layout on page load. May there's also an argument for the current behaviour though...

@chriddyp
Copy link
Member

Is this expected? My intuitions are that callback2 should have been run once on the initial page load given that output1 is present in the layout on page load.

Yes, I think that this is expected. The argument being that the value that was in the app.layout would, normally, be immediately over written by the callbacks, and therefore aren't strictly necessary in the app.layout.

This looks good to me, thanks for writing the integration test 😄 . Let me know if you are happy with it and then I'll merge and make a new release.

Thanks again for contributing!

@ned2
Copy link
Contributor Author

ned2 commented Jan 19, 2018

Yep, am happy, put it in!

@chriddyp chriddyp merged commit a79e7b2 into plotly:master Jan 19, 2018
@rquintino
Copy link

Hi @chriddyp @ned2 , I was testing this with a live dcc.Interval and a table component.

My issue, although the table values are not updated, as expected when raising the new exception, it seems to reset/mess up with table selected indexes/sort at each refresh.

Main scenario here was table live update, but refreshing only when data changes.

thx!

import datetime
import sys
import pandas as pd

app = dash.Dash()

DF_SIMPLE = pd.DataFrame({
'x': ['A', 'B', 'C', 'D', 'E', 'F'],
'y': [4, 3, 1, 2, 3, 6],
'z': ['a', 'b', 'c', 'a', 'b', 'c']
})

app.layout = html.Div([
html.H4('DataTable Sample',id="app_title"),
dt.DataTable(
rows=DF_SIMPLE.to_dict('records'),id='datatable-simple'
),
dcc.Interval(id='my-interval', interval=5000),
], className="container")

app.css.append_css({
'external_url': 'https://codepen.io/chriddyp/pen/bWLwgP.css'
})

@app.callback(
Output('datatable-simple', 'rows'),
[Input('my-interval', 'n_intervals')])
def update_table(n):
print("Checking...")
raise dash.exceptions.PreventUpdate("No data changed!")

HammadTheOne added a commit that referenced this pull request Jul 23, 2021
* Updated vignettes and dash-info.yaml

* Update CHANGELOG

* Updated changelog description
@ned2 ned2 deleted the add-prevent-update-exception branch December 11, 2022 05:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants