Coverage for server / validators / assignment_validator.py: 97%

39 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-10-04 09:33 +0000

1from fastapi import HTTPException, status 

2from typing import Dict, Any 

3 

4 

5def validate_assignment_fields(values: Dict[str, Any]) -> Dict[str, Any]: 

6 """ 

7 Validates that all required assignment fields are not empty or whitespace-only. 

8  

9 Required fields: 

10 - semester 

11 - type 

12 - category 

13 - format 

14 - title 

15 - description 

16 - questions 

17 - assigned_class 

18 - settings 

19  

20 Args: 

21 values (Dict[str, Any]): Dictionary containing assignment fields 

22  

23 Returns: 

24 Dict[str, Any]: The validated values dictionary 

25  

26 Raises: 

27 HTTPException: If any required field is empty or contains only whitespace 

28 """ 

29 required_fields = [ 

30 "semester", 

31 "type", 

32 "category", 

33 "format", 

34 "title", 

35 "description", 

36 "questions", 

37 "assigned_class", 

38 "settings" 

39 ] 

40 

41 for field in required_fields: 

42 if field not in values or values[field] is None: 

43 raise HTTPException( 

44 status_code=status.HTTP_400_BAD_REQUEST, 

45 detail=f"{field} field is required and cannot be empty" 

46 ) 

47 

48 # Check for empty strings or whitespace-only strings 

49 if isinstance(values[field], str) and values[field].strip() == "": 

50 raise HTTPException( 

51 status_code=status.HTTP_400_BAD_REQUEST, 

52 detail=f"{field} field cannot contain only whitespace" 

53 ) 

54 

55 # Special handling for lists 

56 if field in ["questions", "assigned_class"] and isinstance(values[field], list): 

57 if len(values[field]) == 0: 

58 raise HTTPException( 

59 status_code=status.HTTP_400_BAD_REQUEST, 

60 detail=f"{field} field is required and cannot be empty" 

61 ) 

62 

63 # Validate settings fields 

64 if "settings" in values and values["settings"] is not None: 

65 settings = values["settings"] 

66 settings_fields = [ 

67 "allowed_attempts", 

68 "shuffle_questions", 

69 "shuffle_choices", 

70 "allow_calculator", 

71 "show_score_after_submit", 

72 "show_correct_answers_after_submit", 

73 "allow_feedback_after_submit" 

74 ] 

75 

76 for field in settings_fields: 

77 if field not in settings or settings[field] is None: 

78 if field == "time_allowed": 

79 raise HTTPException( 

80 status_code=status.HTTP_400_BAD_REQUEST, 

81 detail="time_allowed field is required" 

82 ) 

83 else: 

84 raise HTTPException( 

85 status_code=status.HTTP_400_BAD_REQUEST, 

86 detail=f"settings.{field} field is required and cannot be empty" 

87 ) 

88 

89 return values 

90 

91 

92def validate_submission_fields(values: Dict[str, Any]) -> Dict[str, Any]: 

93 """ 

94 Validates that all required submission fields are not empty or whitespace-only. 

95  

96 Required fields: 

97 - assignment_id 

98 - answers 

99  

100 Args: 

101 values (Dict[str, Any]): Dictionary containing submission fields 

102  

103 Returns: 

104 Dict[str, Any]: The validated values dictionary 

105  

106 Raises: 

107 HTTPException: If any required field is empty or contains only whitespace 

108 """ 

109 required_fields = ["assignment_id", "answers"] 

110 

111 for field in required_fields: 

112 if field not in values or values[field] is None: 

113 raise HTTPException( 

114 status_code=status.HTTP_400_BAD_REQUEST, 

115 detail=f"{field} field is required and cannot be empty" 

116 ) 

117 

118 # Check for empty strings or whitespace-only strings 

119 if isinstance(values[field], str) and values[field].strip() == "": 

120 raise HTTPException( 

121 status_code=status.HTTP_400_BAD_REQUEST, 

122 detail=f"{field} field cannot contain only whitespace" 

123 ) 

124 

125 # Special handling for answers list 

126 if field == "answers" and isinstance(values[field], list): 

127 if len(values[field]) == 0: 

128 raise HTTPException( 

129 status_code=status.HTTP_400_BAD_REQUEST, 

130 detail=f"{field} field is required and cannot be empty" 

131 ) 

132 

133 # Validate each answer 

134 for i, answer in enumerate(values[field]): 

135 answer_fields = ["question_id", "user_answer", "is_correct"] 

136 for answer_field in answer_fields: 

137 if answer_field not in answer or answer[answer_field] is None: 

138 raise HTTPException( 

139 status_code=status.HTTP_400_BAD_REQUEST, 

140 detail=f"answers[{i}].{answer_field} field is required and cannot be empty" 

141 ) 

142 

143 # Check for empty strings or whitespace-only strings in string fields 

144 if answer_field in ["question_id", "user_answer"] and isinstance(answer[answer_field], str) and answer[answer_field].strip() == "": 

145 raise HTTPException( 

146 status_code=status.HTTP_400_BAD_REQUEST, 

147 detail=f"answers[{i}].{answer_field} field cannot contain only whitespace" 

148 ) 

149 

150 return values