Skip to content

Commit

Permalink
two commits that need to be separated
Browse files Browse the repository at this point in the history
* allows CodeDemo to be None
* allows to input ParameterPanel as input for parameters
  • Loading branch information
agoscinski committed Dec 5, 2023
1 parent 71fa36b commit f893675
Showing 1 changed file with 99 additions and 53 deletions.
152 changes: 99 additions & 53 deletions src/scwidgets/code/_widget_code_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ class CodeDemo(VBox, CheckableWidget):

def __init__(
self,
code: Union[CodeInput, types.FunctionType],
code: Union[CodeInput, types.FunctionType] = None,
check_registry: Optional[CheckRegistry] = None,
parameters: Optional[Dict[str, Union[Check.FunInParamT, Widget]]] = None,
parameters: Optional[Union[Dict[str, Union[Check.FunInParamT, Widget]],
ParameterPanel]] = None,
update_mode: str = "release",
cue_outputs: Union[None, CueOutput, List[CueOutput]] = None,
update_process: Optional[
Expand Down Expand Up @@ -85,13 +86,13 @@ def __init__(
self._code = code
# TODO this needs to be settable
self._output = CueOutput()
self._parameters = deepcopy(parameters)
self._parameters = parameters
self._cue_code = self._code
self._cue_outputs = cue_outputs

if self._check_registry is None:
self._check_button = None
else:
elif self._code is not None:
self._cue_code = CheckCueBox(
self._code, "function_body", self._cue_code, cued=True
)
Expand All @@ -112,26 +113,43 @@ def __init__(
self._update_button = None
self._parameter_panel = VBox([])
else:
compatibility_result = self._code.compatible_with_signature(
list(self._parameters.keys())
)
if compatibility_result != "":
raise ValueError(compatibility_result)
allowed_parameter_types = [dict, ParameterPanel]
parameter_type_allowed = False
for allowed_parameter_type in allowed_parameter_types:
if isinstance(ParameterPanel, allowed_parameter_type):
parameter_type_allowed = True
if parameter_type_allowed:
raise ValueError(
f"Got parameter {type(ParameterPanel)!r} but only "
f"{allowed_parameter_types} are allowed."
)
if isinstance(self._parameters, dict):
if self._code is not None:
compatibility_result = self._code.compatible_with_signature(
list(self._parameters.keys())
)
if compatibility_result != "":
raise ValueError(compatibility_result)

# set up update button and cueing
# -------------------------------
self._cue_code = UpdateCueBox(
self._code,
"function_body",
self._cue_code,
cued=True,
layout=Layout(width="98%", height="auto"),
)

if self._code is not None:
self._cue_code = UpdateCueBox(
self._code,
"function_body",
self._cue_code,
cued=True,
layout=Layout(width="98%", height="auto"),
)

# set up parameter panel
# ----------------------

self._parameter_panel = ParameterPanel(**self._parameters)
if isinstance(self._parameters, ParameterPanel):
self._parameter_panel = self._parameters
else:
self._parameter_panel = ParameterPanel(**self._parameters)
if self._update_mode == "continuous":
self._parameter_panel.set_parameters_widget_attr(
"continuous_update", True
Expand All @@ -145,23 +163,28 @@ def __init__(
self._parameter_panel.observe_parameters(
self._on_trait_parameters_changed, "value"
)
# the button only cues on cue_code change
widgets_to_observe = [self._code]
traits_to_observe = ["function_body"]

if self._code is not None:
# the button only cues on cue_code change
widgets_to_observe = [self._code]
traits_to_observe = ["function_body"]
else:
widgets_to_observe = None
traits_to_observe = None
# assume when continuous that the function is fast
# and that disabling causes flicker
disable_during_action = False

for cue_output in self._cue_outputs:
# TODO this has to be made public
cue_output._widgets_to_observe = [self._code]
cue_output._traits_to_observe = ["function_body"]
cue_output.observe_widgets()

# TODO set this
self._output._widgets_to_observe = [self._code]
self._output._traits_to_observe = ["function_body"]
self._output.observe_widgets()
if self._code is not None:
for cue_output in self._cue_outputs:
# TODO this has to be made public
cue_output._widgets_to_observe = [self._code]
cue_output._traits_to_observe = ["function_body"]
cue_output.observe_widgets()

# TODO set this
self._output._widgets_to_observe = [self._code]
self._output._traits_to_observe = ["function_body"]
self._output.observe_widgets()

self._cue_parameter_panel = UpdateCueBox(
[],
Expand All @@ -180,18 +203,34 @@ def __init__(
)

for cue_output in self._cue_outputs:
# TODO this has to be made public
cue_output._widgets_to_observe = [
self._code
] + self._parameter_panel.parameters_widget
cue_output._traits_to_observe = [
"function_body"
] + self._parameter_panel.parameters_trait
cue_output.observe_widgets()

reset_update_cue_widgets = [self._cue_code, self._cue_parameter_panel]
if self._code is not None:
# TODO this has to be made public
cue_output._widgets_to_observe = [
self._code
] + self._parameter_panel.parameters_widget
cue_output._traits_to_observe = [
"function_body"
] + self._parameter_panel.parameters_trait
cue_output.observe_widgets()
else:
# TODO this has to be made public
cue_output._widgets_to_observe = self._parameter_panel.parameters_widget
cue_output._traits_to_observe = self._parameter_panel.parameters_trait
cue_output.observe_widgets()

reset_update_cue_widgets = []
if self._code is not None:
reset_update_cue_widgets.append(self._cue_code)
reset_update_cue_widgets.append(self._cue_parameter_panel)
reset_update_cue_widgets.extend(self._cue_outputs)

if self._code is not None:
description="Run Code"
button_tooltip = "Runs the code and updates outputs with the specified parameters"
else:
description="Update"
button_tooltip = "Updates outputs with the specified parameters"

self._update_button = UpdateResetCueButton(
reset_update_cue_widgets, # type: ignore[arg-type]
self._on_click_update_action,
Expand All @@ -203,8 +242,8 @@ def __init__(
),
widgets_to_observe=widgets_to_observe,
traits_to_observe=traits_to_observe,
description="Run Code",
button_tooltip="Runs the code with the specified parameters",
description=description,
button_tooltip=button_tooltip,
)

if self._check_button is None and self._update_button is None:
Expand All @@ -216,12 +255,14 @@ def __init__(
else:
self._buttons_panel = HBox([self._check_button, self._update_button])

demo_children = [
self._cue_code,
demo_children = []
if self._code is not None:
demo_children.append(self._cue_code)
demo_children.extend([
self._cue_parameter_panel,
self._buttons_panel,
self._output,
]
])
demo_children.extend(self._cue_outputs)

VBox.__init__(
Expand Down Expand Up @@ -296,14 +337,19 @@ def _on_click_update_action(self) -> bool:
# runs code and displays output
with self._output:
try:
if self._update_process is None:
result = self.code.run(**self.panel_parameters)
else:
result = None
if self._update_process is not None:
result = self._update_process(self, **self.panel_parameters)
print("Output:")
display(result)
for cue_output in self.cue_outputs:
cue_output.handle_result(result)
elif self._code is not None:
result = self._code.run(**self.panel_parameters)

if result is None:
for cue_output in self.cue_outputs:
cue_output.handle_result(**self.panel_parameters)
else:
for cue_output in self.cue_outputs:
cue_output.handle_result(result, **self.panel_parameters)

except CodeValidationError as e:
raised_error = True
raise e
Expand Down

0 comments on commit f893675

Please sign in to comment.