Source code for pykubegrader.submit.submit_assignment
import os
import json
from typing import Dict
import requests
from requests.auth import HTTPBasicAuth
[docs]
def get_credentials():
    """
    Fetch the username and password from environment variables.
    """
    username = os.getenv("user_name_student")
    password = os.getenv("keys_student")
    if not username or not password:
        raise ValueError(
            "Environment variables 'user_name_student' or 'keys_student' are not set."
        )
    return {"username": username, "password": password} 
[docs]
def call_score_assignment(
    assignment_title: str,
    notebook_title: str,
    file_path: str = ".output_reduced.log"
) -> Dict[str, str]:
    """
    Submit an assignment to the scoring endpoint.
    Args:
        assignment_title (str): Title of the assignment
        notebook_title (str): Title of the notebook
        file_path (str): Path to the log file to upload
    Returns:
        dict: JSON response from the server
    Raises:
        RuntimeError: If server returns a client or server error
        FileNotFoundError: If the log file doesn't exist
    """
    base_url = os.getenv("DB_URL")
    if not base_url:
        raise ValueError("Environment variable 'DB_URL' not set")
    url = base_url.rstrip("/") + "/score-assignment"
    params = {
        "assignment_title": assignment_title,
        "notebook_title": notebook_title,
    }
    token = os.getenv("TOKEN")
    if token:
        params["key_used"] = token
    username, password = get_credentials().values()
    try:
        with open(file_path, "rb") as file:
            res = requests.post(
                url=url,
                params=params,
                auth=HTTPBasicAuth(username, password),
                files={"log_file": file},
            )
            if res.status_code != 200:
                # Try to extract a meaningful error message
                try:
                    err_detail = res.json().get("detail", "No detail provided")
                except json.JSONDecodeError:
                    err_detail = res.text  # fallback to raw text
                raise RuntimeError(f"Server returned {res.status_code}: {err_detail}")
            return res.json()
    except FileNotFoundError:
        raise FileNotFoundError(f"File {file_path} does not exist")
    except requests.RequestException as err:
        raise RuntimeError(f"Request failed to {url}: {err}")
    except Exception as err:
        raise RuntimeError(f"Unexpected error: {err}") 
[docs]
def submit_assignment(
    assignment_title: str,
    notebook_title: str,
    file_path: str = ".output_reduced.log",
) -> None:
    """
    Synchronous wrapper for the `call_score_assignment` function.
    Args:
        assignment_title (str): Title of the assignment.
        file_path (str): Path to the log file to upload.
    """
    response = call_score_assignment(assignment_title, notebook_title, file_path)
    print("Server Response:", response.get("message", "No message in response")) 
# Example usage (remove this section if only the function needs to be importable):
if __name__ == "__main__":
    submit_assignment("week1-readings", "path/to/your/log_file.txt")