import requests def fetch_student_info( student_performance_url_template: str, student_id: int, semester: int, intent: str, timeout: int = 20, ) -> dict: if "{student_id}" not in student_performance_url_template: raise ValueError( "STUDENT_PERFORMANCE_URL_TEMPLATE must include '{student_id}'." ) if "{semester}" not in student_performance_url_template: raise ValueError( "STUDENT_PERFORMANCE_URL_TEMPLATE must include '{semester}'." ) student_url = student_performance_url_template.format( student_id=student_id, semester=semester, ) backend_intent = "results" if intent == "result" else intent # Contract: GET with intent as URL query parameter. get_with_intent_resp = requests.get( student_url, params={"intent": backend_intent}, timeout=timeout, ) if get_with_intent_resp.ok: return _filter_student_info_by_intent( get_with_intent_resp.json(), semester=semester, intent=intent, ) # Fallback: plain GET if server ignores intent query param. get_resp = requests.get(student_url, timeout=timeout) if get_resp.ok: return _filter_student_info_by_intent(get_resp.json(), semester=semester, intent=intent) raise RuntimeError( "Failed to fetch student info from " f"{student_url}; " f"GET(intent={backend_intent}) status {get_with_intent_resp.status_code}, " f"GET status {get_resp.status_code}." ) def _filter_student_info_by_intent(payload: dict, semester: int, intent: str) -> dict: # Fallback local filtering in case backend ignores intent/semester params. data = dict(payload) if intent == "attendance": data.pop("results", None) return data if intent in {"result", "results"}: data.pop("attendance", None) results = data.get("results") if isinstance(results, dict): semesters = results.get("semesters") if isinstance(semesters, list): results["semesters"] = [ s for s in semesters if int(s.get("semester", -1)) == int(semester) ] return data return data