Skip to content

Commit

Permalink
Align dpd callback signature to Dash one (no need to group Outputs, I…
Browse files Browse the repository at this point in the history
…nputs and States into list). (#322)

Co-authored-by: GFJ138 <sebastien.dementen@engie.com>
  • Loading branch information
sdementen and sebastiendementen committed Feb 24, 2021
1 parent b9b8712 commit 2a56742
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 13 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes should be documented in this file.

## [dev] - TBD

Align dpd callback signature to Dash one (no need to group Outputs, Inputs and States into list).

## [1.6.1] - 2021-02-06

Added a stub for `use_dash_dispatch` for backwards compatibility.
Expand Down
36 changes: 24 additions & 12 deletions django_plotly_dash/dash_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import warnings

import dash
from dash import Dash
from dash import Dash, dependencies
from dash._utils import split_callback_id, inputs_to_dict

from flask import Flask
Expand Down Expand Up @@ -320,7 +320,7 @@ def get_expanded_arguments(func, inputs, state):

return expanded

def callback(self, output, inputs=None, state=None, events=None):
def callback(self, *_args, **_kwargs):
'''Form a callback function by wrapping, in the same way as the underlying Dash application would
but handling extra arguments provided by dpd.
Expand All @@ -331,10 +331,15 @@ def callback(self, output, inputs=None, state=None, events=None):
Otherwise, take all arguments beyond the one provided by Dash (based on the Inputs/States provided).
'''

output, inputs, state, prevent_initial_call = dependencies.handle_callback_args(
_args, _kwargs
)

callback_set = {'output': output,
'inputs': inputs or [],
'state': state or [],
'events': events or []}
'inputs': inputs,
'state': state,
'prevent_initial_call': prevent_initial_call}

def wrap_func(func):
self._callback_sets.append((callback_set, func))
Expand All @@ -348,12 +353,17 @@ def wrap_func(func):

expanded_callback = callback

def clientside_callback(self, clientside_function, output, inputs=None, state=None):
def clientside_callback(self, clientside_function, *_args, **_kwargs):
'Form a callback function by wrapping, in the same way as the underlying Dash application would'
output, inputs, state, prevent_initial_call = dependencies.handle_callback_args(
_args, _kwargs
)

callback_set = { 'clientside_function': clientside_function,
'output': output,
'inputs': inputs and inputs or dict(),
'state': state and state or dict() }
'inputs': inputs,
'state': state,
'prevent_initial_call': prevent_initial_call}

self._clientside_callback_sets.append(callback_set)

Expand Down Expand Up @@ -589,7 +599,7 @@ def _fix_callback_item(self, item):
item.component_id = self._fix_id(item.component_id)
return item

def callback(self, output, inputs=[], state=[], events=[]): # pylint: disable=dangerous-default-value
def callback(self, output, inputs, state, prevent_initial_call):
'Invoke callback, adjusting variable names as needed'

if isinstance(output, (list, tuple)):
Expand All @@ -599,9 +609,10 @@ def callback(self, output, inputs=[], state=[], events=[]): # pylint: disable=da

return super().callback(fixed_outputs,
[self._fix_callback_item(x) for x in inputs],
[self._fix_callback_item(x) for x in state])
[self._fix_callback_item(x) for x in state],
prevent_initial_call=prevent_initial_call)

def clientside_callback(self, clientside_function, output, inputs=[], state=[]): # pylint: disable=dangerous-default-value
def clientside_callback(self, clientside_function, output, inputs, state, prevent_initial_call): # pylint: disable=dangerous-default-value
'Invoke callback, adjusting variable names as needed'

if isinstance(output, (list, tuple)):
Expand All @@ -612,7 +623,8 @@ def clientside_callback(self, clientside_function, output, inputs=[], state=[]):
return super().clientside_callback(clientside_function,
fixed_outputs,
[self._fix_callback_item(x) for x in inputs],
[self._fix_callback_item(x) for x in state])
[self._fix_callback_item(x) for x in state],
prevent_initial_call=prevent_initial_call)

#pylint: disable=too-many-locals
def dispatch_with_args(self, body, argMap):
Expand Down
52 changes: 51 additions & 1 deletion django_plotly_dash/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

import pytest
# pylint: disable=bare-except
from dash.dependencies import Input
from dash.dependencies import Input, State, Output
from django.urls import reverse

from django_plotly_dash import DjangoDash
Expand Down Expand Up @@ -202,6 +202,56 @@ def test_dash_stateful_app_client_contract(client):
assert DashApp.objects.get(instance_name="Some name").current_state() == final_state



def test_dash_callback_arguments():
'Test the flexibility of the callback arguments order (handling of inputs/outputs/states)'

# create a DjangoDash
ddash = DjangoDash(name="DashCallbackArguments")

# add a callback with the new flexible order of dependencies
@ddash.callback(
Output("one", "foo"),
Output("two", "foo"),
Input("one", "baz"),
Input("two", "baz"),
Input("three", "baz"),
State("one", "bil"),
)
def new():
pass

# add a callback with the old/classical flexible order of dependencies
@ddash.callback(
[Output("one", "foo"),
Output("two", "foo")],
[Input("one", "baz"),
Input("two", "baz"),
Input("three", "baz")],
[State("one", "bil")]
)
def old():
pass

assert ddash._callback_sets == [({'inputs': [Input("one", "baz"),
Input("two", "baz"),
Input("three", "baz"), ],
'output': [Output("one", "foo"),
Output("two", "foo")],
'prevent_initial_call': None,
'state': [State("one", "bil"), ]},
new),
({'inputs': [Input("one", "baz"),
Input("two", "baz"),
Input("three", "baz"), ],
'output': [Output("one", "foo"),
Output("two", "foo")],
'prevent_initial_call': None,
'state': [State("one", "bil"), ]},
old)
]


def test_util_error_cases(settings):
'Test handling of missing settings'

Expand Down

0 comments on commit 2a56742

Please sign in to comment.