""" graders/code_structure.py — Code structure quality grader. Weight: 3% of total reward. Checks: - No bare print() statements (production code uses logging) - Handles None/empty inputs (edge case awareness) - No bare except clauses (too broad) - No global mutable state (thread safety) """ import ast import re from typing import Dict, Any def grade_code_structure(code: str) -> Dict[str, Any]: checks = {} # Check 1: No print statements checks["no_print"] = "print(" not in code # Check 2: Has some error handling checks["has_error_handling"] = "try:" in code or "raise" in code or "ValueError" in code # Check 3: No bare except checks["no_bare_except"] = "except:" not in code # Check 4: No hardcoded credentials pattern has_hardcoded = bool(re.search( r'(password|secret|api_key|token)\s*=\s*["\'][^"\']{3,}["\']', code, re.IGNORECASE )) checks["no_hardcoded_creds"] = not has_hardcoded # Check 5: Has type annotations (bonus) checks["has_type_hints"] = "->" in code or ": str" in code or ": int" in code or ": bool" in code passed = sum(checks.values()) total = len(checks) score = round(passed / total, 4) issues = [k for k, v in checks.items() if not v] feedback = "Clean structure." if not issues else f"Issues: {', '.join(issues)}" return {"score": score, "feedback": feedback, "checks": checks}