-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Support Dash prop callback connection closer to function signature #1810
Comments
I really like this idea. I just put together a simple (but working) prototype implementation inspired by your code. So far, the syntax looks like this,
where |
Another option would be to use a syntax closer to the current one, e.g. something like
This approach doesn't allow the use of actual type annotations though, which might be a drawback. On the other hand, native Dash doesn't allow complex types as input/output for callbacks, so it might not be so bad after all. |
🎉🙂
Overall I like the syntax and think using type hint annotations improves readability. I'm not sure if the following are ideas, maybe more questions:
My hope is that it will change after #1786 - and then it would be nice to able to use the full power of type hint annotations. 🙂 One option (combining the class approach above and also reuse existing @callback
def hello(n_clicks: A[sometype, Input("btn", "n_clicks")]) -> A[sometype, Output("log", "children")]:
return "Hello world!" but it feels more verbose/explicit than necessary ( |
I have done another (small) iteration of the syntax, partly based on your comments, @anders-kiaer . My working example now looks like this, from dash_extensions.enrich import DashProxy, callback, html, dcc, prop
@callback
def hello(n_clicks: prop("btn", "n_clicks", int), # the type definition "int" is optional
name: prop("name", "value", trigger=False)) -> prop("log", "children"):
return f"Hello {name}! (click count is {n_clicks})"
app = DashProxy(prevent_initial_callbacks=True)
app.layout = html.Div([
dcc.Input(placeholder="Enter your name here", id="name"),
html.Button("Click me!", id="btn"),
html.Div(id="log")
])
if __name__ == '__main__':
app.run_server() A few notes on the syntax,
You should be able to try out the syntax with the following rc release, https://pypi.org/project/dash-extensions/0.0.67rc2/ I haven't tested much more than the example above, so expect dragons :) |
Hey @anders-kiaer and @emilhe I'd be interested to hear your feedback on #1952 Improved |
Is your feature request related to a problem? Please describe.
When creating complex Dash dashbords/callbacks, there can be a long list of input/state/output. We in some cases have seen things of the size of:
😱 Both during development, but also code review/maintenance, there is mental overhead with respect to seeing which
(id, prop)
pair belongs to which named argument in the function. This has gotten a bit better with https://dash.plotly.com/flexible-callback-signatures, but the underlying problem with(id, prop)
and named argument in the function being defined in two different lines remains.Describe the solution you'd like
Utilize the Python 3+ typing syntax to annotate the
(id, prop)
closer to the argument. By using that we at the same time can avoid explicitly statingOutput
as that is already explicit by being defined as the returned type(s) of the function. The only thing to differentiate between isInput
/State
which could be done by some extra annotation tag. E.g. something likeAnother benefit is that we encourage Dash app developers to type hint their callback functions which again helps IDEs and
mypy
detect bugs (related to #1786).Additional context
See https://docs.python.org/3/library/typing.html#typing.Annotated for documentation on
typing.Annotated
(backported to earlier Python 3 versions intyping_extensions
).Related to #1748 and #1786, but implementation is independent of those.
PoC code showing how type annotations potentially can be transformed into the
Input
/Output
/State
when callbacks are registered/decorated:The below code will print out
The text was updated successfully, but these errors were encountered: