Skip to content

Change API in CodeExercise related to cue_outputs #71

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

Merged
merged 1 commit into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 38 additions & 16 deletions src/scwidgets/exercise/_widget_code_exercise.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import Any, Callable, Dict, List, Optional, Union

from ipywidgets import HTML, Box, HBox, HTMLMath, Layout, VBox, Widget
from matplotlib.figure import Figure
from widget_code_input import WidgetCodeInput
from widget_code_input.utils import CodeValidationError

Expand All @@ -18,6 +19,8 @@
from ..cue import (
CheckCueBox,
CheckResetCueButton,
CueFigure,
CueObject,
CueOutput,
SaveCueBox,
SaveResetCueButton,
Expand Down Expand Up @@ -47,8 +50,8 @@ class CodeExercise(VBox, CheckableWidget, ExerciseWidget):
Determines how the parameters are refreshed on changes of the code input
or parameters

:param cue_outputs:
List of CueOuputs that are drawn an refreshed
:param outputs:
List of CueOuputs that are drawn and refreshed

:param update_func:
A function that is run during the update process. The function takes as argument
Expand All @@ -66,7 +69,7 @@ def __init__(
Union[Dict[str, Union[Check.FunInParamT, Widget]], ParameterPanel]
] = None,
update_mode: str = "release",
cue_outputs: Union[None, CueOutput, List[CueOutput]] = None,
outputs: Union[None, Figure, CueOutput, List[CueOutput]] = None,
update_func: Optional[
Union[
Callable[[CodeExercise], Union[Any, Check.FunOutParamsT]],
Expand Down Expand Up @@ -170,11 +173,6 @@ def __init__(
"Code and parameters do no match: " + compatibility_result
)

if cue_outputs is None:
cue_outputs = []
elif not (isinstance(cue_outputs, list)):
cue_outputs = [cue_outputs]

CheckableWidget.__init__(self, check_registry, exercise_key)
ExerciseWidget.__init__(self, exercise_registry, exercise_key)

Expand All @@ -190,7 +188,20 @@ def __init__(
self._parameter_panel = None

self._cue_code = self._code
self._cue_outputs = cue_outputs

if outputs is None:
outputs = []
elif not (isinstance(outputs, list)):
outputs = [outputs]

self._cue_outputs: List[CueOutput] = []
for output in outputs:
if isinstance(output, Figure):
self._cue_outputs.append(CueFigure(output))
elif isinstance(output, CueOutput):
self._cue_outputs.append(output)
else:
self._cue_outputs.append(CueObject(output))

if self._check_registry is None or self._code is None:
self._check_button = None
Expand Down Expand Up @@ -289,17 +300,24 @@ def __init__(
cue_output._widgets_to_observe = [
self._code
] + self._parameter_panel.parameters_widget
cue_output._traits_to_observe = [
"function_body"
] + self._parameter_panel.parameters_trait
# fmt: off
cue_output._traits_to_observe = (

[ # type: ignore[assignment]
"function_body"
]
+ self._parameter_panel.parameters_trait
)
# fmt: on

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
self._parameter_panel.parameters_trait # type: ignore[assignment] # noqa: E501
)
cue_output.observe_widgets()
elif self._code is not None:
Expand Down Expand Up @@ -659,7 +677,11 @@ def code(self):
return self._code

@property
def cue_outputs(self):
def output(self) -> CueOutput | None:
return self._cue_outputs[0] if len(self._cue_outputs) > 0 else None

@property
def outputs(self) -> List[CueOutput]:
return self._cue_outputs

def _on_click_update_action(self) -> bool:
Expand All @@ -668,7 +690,7 @@ def _on_click_update_action(self) -> bool:
# runs code and displays output
with self._output:
try:
for cue_output in self.cue_outputs:
for cue_output in self.outputs:
if hasattr(cue_output, "clear_display"):
cue_output.clear_display(wait=True)

Expand All @@ -680,7 +702,7 @@ def _on_click_update_action(self) -> bool:
elif self._code is not None:
self.run_code(**self.params)

for cue_output in self.cue_outputs:
for cue_output in self.outputs:
if hasattr(cue_output, "draw_display"):
cue_output.draw_display()

Expand Down
10 changes: 5 additions & 5 deletions tests/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,19 @@ def get_code_exercise(

def update_print():
output = code_ex.run_code(**code_ex.params)
code_ex.cue_outputs[0].display_object = f"Output:\n{output}"
code_ex.output.display_object = f"Output:\n{output}"

else:

def update_print(code_ex: CodeExercise):
output = code_ex.run_code(**code_ex.params)
code_ex.cue_outputs[0].display_object = f"Output:\n{output}"
code_ex.output.display_object = f"Output:\n{output}"

code_ex = CodeExercise(
code=code_input,
check_registry=CheckRegistry() if include_checks is True else None,
parameters=parameters if include_params is True else None,
cue_outputs=[CueObject("Not initialized")],
outputs=[CueObject("Not initialized")],
update_func=update_print,
update_mode=update_mode,
)
Expand Down Expand Up @@ -260,7 +260,7 @@ def test_save_registry(self, function):
"""

def print_success(code_ex: CodeExercise | None):
code_ex.cue_outputs[0].display_object = "Success"
code_ex.output.display_object = "Success"

cue_output = CueObject("Not initialized")
exercise_registry = ExerciseRegistry()
Expand Down Expand Up @@ -310,7 +310,7 @@ def mock_clear_output(wait):
# Be aware that the raised error is captured in the code_ex._output
# To debug failures in the test you have to manually run it in debug
# mode and execute `code_ex._update_button.click()` Redirecting stderr
# does des not workc
# does des not work
code_ex.run_update()
assert "Output:\n0" in buffer.getvalue()

Expand Down