Source code for pykubegrader.widgets.student_info

import os
import re
import socket

import numpy as np
import panel as pn

from ..telemetry import ensure_responses, update_responses

#
# Constants
#

EMAIL_PATTERN = re.compile(r"[a-z]+\d+@drexel\.edu")

KEYS = [
    "first_name",
    "last_name",
    "drexel_id",
    "drexel_email",
    "hostname",
    "ip_address",
    "jupyter_user",
    "seed",
]

#
# Form class
#


[docs] class StudentInfoForm: def __init__(self, **kwargs) -> None: self.first_name = kwargs.get("first_name", "") self.last_name = kwargs.get("last_name", "") self.drexel_id = kwargs.get("drexel_id", "") self.drexel_email = kwargs.get("drexel_email", "") self.hostname = kwargs.get("hostname", "") self.ip_address = kwargs.get("ip_address", "") self.jupyter_user = kwargs.get("jupyter_user", "") self.seed = kwargs.get("seed", np.random.randint(0, 100)) self.first_name_widget = pn.widgets.TextInput( name="First Name", value=self.first_name ) self.last_name_widget = pn.widgets.TextInput( name="Last Name", value=self.last_name ) self.drexel_id_widget = pn.widgets.TextInput( name="Drexel ID", value=self.drexel_id ) self.drexel_email_widget = pn.widgets.TextInput( name="Drexel Email", value=self.drexel_email ) self.submit_button = pn.widgets.Button( name="Submit", button_type="primary", styles=dict(margin_top="1.5em") ) self.submit_button.on_click(self.submit) self.message = pn.pane.Str("") # Placeholder for status message self.layout = pn.Column( "# Student Information Form", self.first_name_widget, self.last_name_widget, self.drexel_id_widget, self.drexel_email_widget, self.submit_button, self.message, )
[docs] def submit(self, _) -> None: info = ensure_responses() info["first_name"] = self.first_name_widget.value.strip() info["last_name"] = self.last_name_widget.value.strip() info["drexel_id"] = self.drexel_id_widget.value.strip() info["drexel_email"] = self.drexel_email_widget.value.strip() info["hostname"] = socket.gethostname() info["jupyter_user"] = os.environ.get("JUPYTERHUB_USER", "Not on JupyterHub") if "seed" not in info: info["seed"] = np.random.randint(0, 100) try: info["ip_address"] = socket.gethostbyname(info["hostname"]) except socket.gaierror: info["ip_address"] = "IP unavailable" try: for key in KEYS: if info[key] == "": raise ValueError(f"Missing form input: {key}") if not EMAIL_PATTERN.fullmatch(info["drexel_email"]): raise ValueError(f"Invalid email format: {info['drexel_email']}") email_prefix = info["drexel_email"].split("@")[0] if info["drexel_id"] != email_prefix: raise ValueError( f"Drexel ID {info['drexel_id']} does not match email {info['drexel_email']}" ) for key in KEYS: update_responses(key, info[key]) self.message.object = "Student info recorded successfully!" self.message.style = {"color": "green"} except ValueError as e: self.message.object = str(e) self.message.style = {"color": "red"}
[docs] def show(self): return self.layout