Source code for pykubegrader.widgets_base.select

import time
from typing import Callable, Optional, Tuple

import numpy as np
import panel as pn

from ..telemetry import ensure_responses, score_question, update_responses
from ..utils import shuffle_options, shuffle_questions
from ..widgets.style import drexel_colors

# Pass custom CSS to Panel
pn.extension(design="material", global_css=[drexel_colors])


[docs] class SelectQuestion: def __init__( self, title: str, style: Callable[ [list[str], list, list[str]], Tuple[list[pn.pane.HTML], list[pn.widgets.Select]], ], question_number: int, keys: list[str], options: list[Optional[str]] | list[list[Optional[str]]], descriptions: list[str], points: int, shuffle_answers: bool = True, ): responses = ensure_responses() self.points = points self.question_number = question_number self.keys = keys self.style = style try: seed: int = responses["seed"] except ValueError: raise ValueError( "You must submit your student info before starting the exam" ) # Dynamically assign attributes based on keys, with default values from responses for key in self.keys: setattr(self, key, responses.get(key, None)) self.initial_vals: list = [getattr(self, key) for key in self.keys] if shuffle_answers: shuffle_options(options, seed) desc_widgets, self.widgets = style(descriptions, options, self.initial_vals) self.submit_button = pn.widgets.Button(name="Submit", button_type="primary") self.submit_button.on_click(self.submit) widget_pairs = shuffle_questions(desc_widgets, self.widgets, seed) self.layout = pn.Column( f"# Question {self.question_number} (Points {np.sum(points)}): {title}", *( pn.Column(desc_widget, pn.Row(dropdown)) for desc_widget, dropdown in widget_pairs ), self.submit_button, )
[docs] def submit(self, _) -> None: selections = {key: widget.value for key, widget in zip(self.keys, self.widgets)} for value in selections.values(): if value is None: raise ValueError("Please answer all questions before submitting") for key, value in selections.items(): update_responses(key, value) score_question() # Debugging; update later # Temporarily change button text to indicate submission self.submit_button.name = "Responses Submitted" time.sleep(1) self.submit_button.name = "Submit"
[docs] def show(self): return self.layout