Source code for pykubegrader.initialize
import hashlib
import os
import shutil
from pathlib import Path
from typing import Optional
import panel as pn
import requests
from IPython.core.getipython import get_ipython
from .telemetry import ensure_responses, log_variable, telemetry, update_responses
from .utils import api_base_url
# TODO: could cleanup to remove redundant imports
[docs]
def initialize_assignment(
name: str,
week: str,
assignment_type: str,
verbose: bool = False,
assignment_points: Optional[float] = None,
assignment_tag: Optional[str] = None,
) -> dict:
"""
Initialize an assignment in a Jupyter environment.
Args:
name (str): The name of the assignment.
url (str): The URL of the API server.
verbose (bool): Whether to print detailed initialization information.
Returns:
dict: The responses dictionary after initialization.
Raises:
Exception: If the environment is unsupported or initialization fails.
"""
if assignment_tag is None:
assignment_tag = f"{week}-{assignment_type}"
ipython = get_ipython()
if ipython is None:
raise Exception("Setup unsuccessful. Are you in a Jupyter environment?")
try:
move_dotfiles()
ipython.events.register("pre_run_cell", telemetry)
except Exception as e:
raise Exception(f"Failed to register telemetry: {e}")
jhub_user = os.getenv("JUPYTERHUB_USER")
if jhub_user is None:
raise Exception("Setup unsuccessful. Are you on JupyterHub?")
try:
seed = username_to_seed(jhub_user) % 1000
update_responses(key="seed", value=seed)
update_responses(key="week", value=week)
update_responses(key="assignment_type", value=assignment_type)
update_responses(key="assignment", value=name)
update_responses(key="jhub_user", value=jhub_user)
# TODO: Check whether this is called correctly
log_variable("Student Info", jhub_user, seed)
responses = ensure_responses()
# TODO: Add more checks here?
assert isinstance(responses.get("seed"), int), "Seed not set"
pn.extension(silent=True)
# Check connection to API server
if not api_base_url:
raise Exception("Environment variable for API URL not set")
params = {"jhub_user": responses["jhub_user"]}
response = requests.get(api_base_url, params=params)
if verbose:
print(f"status code: {response.status_code}")
data = response.json()
for k, v in data.items():
print(f"{k}: {v}")
except Exception as e:
raise Exception(f"Failed to initialize assignment: {e}")
log_variable("total-points", f"{assignment_tag}, {name}", assignment_points)
print("Assignment successfully initialized")
if verbose:
print(f"Assignment: {name}")
print(f"Username: {jhub_user}")
return responses
#
# Helper functions
#
[docs]
def move_dotfiles():
"""
Move essential dotfiles from a fixed source directory to the current working directory.
Raises:
FileNotFoundError: If a source file is missing.
Exception: If copying fails for any other reason.
"""
source_dir = Path("/opt/dotfiles")
target_dir = Path.cwd()
files_to_copy = [".client_private_key.bin", ".server_public_key.bin"]
for file_name in files_to_copy:
source_file = source_dir / file_name
target_file = target_dir / file_name
if not source_file.exists():
raise FileNotFoundError(f"Key file not found: {source_file}")
try:
shutil.copy2(source_file, target_file)
except Exception as e:
raise Exception(f"Failed to copy {source_file} to {target_file}: {e}")
[docs]
def username_to_seed(username: str, mod: int = 1000) -> int:
hash_object = hashlib.sha256(username.encode())
hash_hex = hash_object.hexdigest()
hash_int = int(hash_hex, 16)
return hash_int % mod