emilhe / dash-extensions

The dash-extensions package is a collection of utility functions, syntax extensions, and Dash components that aim to improve the Dash development experience
https://www.dash-extensions.com/
MIT License
417 stars 59 forks source link

DataclassTransform #271

Closed emilhe closed 1 year ago

codecov-commenter commented 1 year ago

Codecov Report

Merging #271 (775a90f) into master (2bf9f45) will increase coverage by 0.22%. The diff coverage is 94.73%.

:exclamation: Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

@@            Coverage Diff             @@
##           master     #271      +/-   ##
==========================================
+ Coverage   84.12%   84.35%   +0.22%     
==========================================
  Files           9        9              
  Lines         945      965      +20     
==========================================
+ Hits          795      814      +19     
- Misses        150      151       +1     
Impacted Files Coverage Δ
dash_extensions/enrich.py 82.42% <94.73%> (+0.32%) :arrow_up:
emilhe commented 1 year ago

@gedemagt did you get a chance to test if this PR works as intended?

gedemagt commented 1 year ago

Just had a bit of summervacation :D

Not exactly - I tried the following:

from dataclasses import dataclass
from datetime import datetime

from dash import Output, html, dcc
from dataclass_wizard import asdict

from dash_extensions.enrich import callback, DashProxy, TriggerTransform, NoOutputTransform, DataclassTransform, Trigger, State

app = DashProxy(
    transforms=[
        TriggerTransform(), NoOutputTransform(), DataclassTransform()
    ]
)

@dataclass
class StateModel:
    value: datetime
    list_of_values: list[int]

@callback(
    Output('output-div','children'),
    Trigger('some-btn', 'n_clicks'),
    State('state-object', 'data')
)
def do_stuff(state: StateModel):
    return f"Before now? {state.value > datetime.utcnow()} - with {len(state.list_of_values)} values"

app.layout = html.Div([
    dcc.Store(id="state-object", data=asdict(StateModel(datetime.utcnow(), [1, 2, 3]))),
    html.Button("Hello", id="some-btn"),
    html.Div(id="output-div")
])

app.run_server(debug=True)

But I get an error

Traceback (most recent call last):
  File "/home/jesper/projects/dash-extensions/dash_extensions/enrich.py", line 1050, in decorated_function
    an = full_arg_spec.annotations.get(full_arg_spec.args[i])
IndexError: list index out of range

It seems like the full-arg-spec found in L1039 (enrich.py) is empty. I will try to debug a bit later.

gedemagt commented 1 year ago

Seems like the TriggerTransform strips all the info. I tried with an input instead of a Trigger, and that works fine.

@callback(
    Output('output-div','children'),
    Input('some-btn', 'n_clicks'),
    State('state-object', 'data')
)
def do_stuff(n, state: StateModel):
    return f"Before now? {state.value > datetime.utcnow()} - with {len(state.list_of_values)} values"
emilhe commented 1 year ago

Ah yes, that makes sense. For the transform to work, it must be applied before the trigger transform. I just specified that, so now your example seems to work.