quizcomp.model.feedback
1import typing 2 3import edq.util.serial 4 5import quizcomp.model.errors 6import quizcomp.parser.document 7 8class Feedback(edq.util.serial.PODConverter): 9 """ 10 Text that can be attached to objects (generally questions and answers) as a form of feedback for an action. 11 Feedback can be specific to a correct/incorrect action, or just general. 12 """ 13 14 serialization_omit_none = True 15 serialization_omit_empty = True 16 17 def __init__(self, 18 general: typing.Union[quizcomp.parser.document.ParsedDocument, None] = None, 19 correct: typing.Union[quizcomp.parser.document.ParsedDocument, None] = None, 20 incorrect: typing.Union[quizcomp.parser.document.ParsedDocument, None] = None, 21 **kwargs: typing.Any) -> None: 22 if ((general is not None) and general.is_empty()): 23 general = None 24 25 self.general: typing.Union[quizcomp.parser.document.ParsedDocument, None] = general 26 """ Feedback to be shown regardless of the outcome. """ 27 28 if ((correct is not None) and correct.is_empty()): 29 correct = None 30 31 self.correct: typing.Union[quizcomp.parser.document.ParsedDocument, None] = correct 32 """ Feedback to be shown if the action/choice/answer was correct. """ 33 34 if ((incorrect is not None) and incorrect.is_empty()): 35 incorrect = None 36 37 self.incorrect: typing.Union[quizcomp.parser.document.ParsedDocument, None] = incorrect 38 """ Feedback to be shown if the action/choice/answer was incorrect. """ 39 40 def collect_documents(self) -> typing.List[quizcomp.parser.document.ParsedDocument]: 41 """ Collect all documents in this object. """ 42 43 documents = [] 44 45 if (self.general is not None): 46 documents.append(self.general) 47 48 if (self.correct is not None): 49 documents.append(self.correct) 50 51 if (self.incorrect is not None): 52 documents.append(self.incorrect) 53 54 return documents 55 56 def is_empty(self) -> bool: 57 """ Check if this feedback item contains any actual feedback. """ 58 59 return ((self.general is None) and (self.correct is None) and (self.incorrect is None)) 60 61 def _serialization_is_empty(self) -> bool: 62 """ A special method for the serialization library to check. """ 63 64 return self.is_empty() 65 66 def to_pod(self, 67 context: typing.Union[edq.util.serial.SerializationContext, None] = None, 68 ) -> edq.util.serial.PODType: 69 if (self.is_empty()): 70 return None 71 72 if ((self.general is not None) and (self.correct is None) and (self.incorrect is None)): 73 return self.general.to_pod(context) 74 75 return super().to_pod(context) 76 77 @classmethod 78 def from_raw_data(cls, 79 raw_data: typing.Any, 80 context: edq.util.serial.SerializationContext, 81 ) -> 'Feedback': 82 """ Parse out feedback from one of several allowed forms. """ 83 84 if (raw_data is None): 85 return Feedback() 86 87 if (isinstance(raw_data, str)): 88 parsed_text = quizcomp.parser.document.ParsedDocument.parse_text(raw_data, context) 89 return Feedback(general = parsed_text) 90 91 quizcomp.model.errors.check_type(raw_data, dict, "'feedback'") 92 93 data: typing.Dict[str, typing.Any] = typing.cast(typing.Dict[str, typing.Any], raw_data) 94 result = {} 95 96 allowed_keys = ['general', 'correct', 'incorrect'] 97 actual_keys = list(data.keys()) 98 99 bad_keys = list(sorted(set(actual_keys) - set(allowed_keys))) 100 if (len(bad_keys) > 0): 101 raise quizcomp.model.errors.QuestionValidationError( 102 f"Unknown keys in feedback ({bad_keys}). Allowed keys: {allowed_keys}.", 103 context = edq.util.serial.SerializationContext) 104 105 for (key, value) in data.items(): 106 if (value is None): 107 continue 108 109 quizcomp.model.errors.check_type(value, str, f"'{key}' feedback value") 110 111 value = str(value).strip() 112 if (len(value) == 0): 113 continue 114 115 result[key] = quizcomp.parser.document.ParsedDocument.parse_text(value, context) 116 117 return Feedback(**result)
class
Feedback(edq.util.serial.PODConverter):
9class Feedback(edq.util.serial.PODConverter): 10 """ 11 Text that can be attached to objects (generally questions and answers) as a form of feedback for an action. 12 Feedback can be specific to a correct/incorrect action, or just general. 13 """ 14 15 serialization_omit_none = True 16 serialization_omit_empty = True 17 18 def __init__(self, 19 general: typing.Union[quizcomp.parser.document.ParsedDocument, None] = None, 20 correct: typing.Union[quizcomp.parser.document.ParsedDocument, None] = None, 21 incorrect: typing.Union[quizcomp.parser.document.ParsedDocument, None] = None, 22 **kwargs: typing.Any) -> None: 23 if ((general is not None) and general.is_empty()): 24 general = None 25 26 self.general: typing.Union[quizcomp.parser.document.ParsedDocument, None] = general 27 """ Feedback to be shown regardless of the outcome. """ 28 29 if ((correct is not None) and correct.is_empty()): 30 correct = None 31 32 self.correct: typing.Union[quizcomp.parser.document.ParsedDocument, None] = correct 33 """ Feedback to be shown if the action/choice/answer was correct. """ 34 35 if ((incorrect is not None) and incorrect.is_empty()): 36 incorrect = None 37 38 self.incorrect: typing.Union[quizcomp.parser.document.ParsedDocument, None] = incorrect 39 """ Feedback to be shown if the action/choice/answer was incorrect. """ 40 41 def collect_documents(self) -> typing.List[quizcomp.parser.document.ParsedDocument]: 42 """ Collect all documents in this object. """ 43 44 documents = [] 45 46 if (self.general is not None): 47 documents.append(self.general) 48 49 if (self.correct is not None): 50 documents.append(self.correct) 51 52 if (self.incorrect is not None): 53 documents.append(self.incorrect) 54 55 return documents 56 57 def is_empty(self) -> bool: 58 """ Check if this feedback item contains any actual feedback. """ 59 60 return ((self.general is None) and (self.correct is None) and (self.incorrect is None)) 61 62 def _serialization_is_empty(self) -> bool: 63 """ A special method for the serialization library to check. """ 64 65 return self.is_empty() 66 67 def to_pod(self, 68 context: typing.Union[edq.util.serial.SerializationContext, None] = None, 69 ) -> edq.util.serial.PODType: 70 if (self.is_empty()): 71 return None 72 73 if ((self.general is not None) and (self.correct is None) and (self.incorrect is None)): 74 return self.general.to_pod(context) 75 76 return super().to_pod(context) 77 78 @classmethod 79 def from_raw_data(cls, 80 raw_data: typing.Any, 81 context: edq.util.serial.SerializationContext, 82 ) -> 'Feedback': 83 """ Parse out feedback from one of several allowed forms. """ 84 85 if (raw_data is None): 86 return Feedback() 87 88 if (isinstance(raw_data, str)): 89 parsed_text = quizcomp.parser.document.ParsedDocument.parse_text(raw_data, context) 90 return Feedback(general = parsed_text) 91 92 quizcomp.model.errors.check_type(raw_data, dict, "'feedback'") 93 94 data: typing.Dict[str, typing.Any] = typing.cast(typing.Dict[str, typing.Any], raw_data) 95 result = {} 96 97 allowed_keys = ['general', 'correct', 'incorrect'] 98 actual_keys = list(data.keys()) 99 100 bad_keys = list(sorted(set(actual_keys) - set(allowed_keys))) 101 if (len(bad_keys) > 0): 102 raise quizcomp.model.errors.QuestionValidationError( 103 f"Unknown keys in feedback ({bad_keys}). Allowed keys: {allowed_keys}.", 104 context = edq.util.serial.SerializationContext) 105 106 for (key, value) in data.items(): 107 if (value is None): 108 continue 109 110 quizcomp.model.errors.check_type(value, str, f"'{key}' feedback value") 111 112 value = str(value).strip() 113 if (len(value) == 0): 114 continue 115 116 result[key] = quizcomp.parser.document.ParsedDocument.parse_text(value, context) 117 118 return Feedback(**result)
Text that can be attached to objects (generally questions and answers) as a form of feedback for an action. Feedback can be specific to a correct/incorrect action, or just general.
Feedback( general: Optional[quizcomp.parser.document.ParsedDocument] = None, correct: Optional[quizcomp.parser.document.ParsedDocument] = None, incorrect: Optional[quizcomp.parser.document.ParsedDocument] = None, **kwargs: Any)
18 def __init__(self, 19 general: typing.Union[quizcomp.parser.document.ParsedDocument, None] = None, 20 correct: typing.Union[quizcomp.parser.document.ParsedDocument, None] = None, 21 incorrect: typing.Union[quizcomp.parser.document.ParsedDocument, None] = None, 22 **kwargs: typing.Any) -> None: 23 if ((general is not None) and general.is_empty()): 24 general = None 25 26 self.general: typing.Union[quizcomp.parser.document.ParsedDocument, None] = general 27 """ Feedback to be shown regardless of the outcome. """ 28 29 if ((correct is not None) and correct.is_empty()): 30 correct = None 31 32 self.correct: typing.Union[quizcomp.parser.document.ParsedDocument, None] = correct 33 """ Feedback to be shown if the action/choice/answer was correct. """ 34 35 if ((incorrect is not None) and incorrect.is_empty()): 36 incorrect = None 37 38 self.incorrect: typing.Union[quizcomp.parser.document.ParsedDocument, None] = incorrect 39 """ Feedback to be shown if the action/choice/answer was incorrect. """
serialization_omit_empty =
True
Do not include empty fields in serialization. An empty field meets one of the following conditions:
- Has a
__len__method which returns 0. - Has a
_serialization_is_emptymethod that returns true.
general: Optional[quizcomp.parser.document.ParsedDocument]
Feedback to be shown regardless of the outcome.
correct: Optional[quizcomp.parser.document.ParsedDocument]
Feedback to be shown if the action/choice/answer was correct.
incorrect: Optional[quizcomp.parser.document.ParsedDocument]
Feedback to be shown if the action/choice/answer was incorrect.
41 def collect_documents(self) -> typing.List[quizcomp.parser.document.ParsedDocument]: 42 """ Collect all documents in this object. """ 43 44 documents = [] 45 46 if (self.general is not None): 47 documents.append(self.general) 48 49 if (self.correct is not None): 50 documents.append(self.correct) 51 52 if (self.incorrect is not None): 53 documents.append(self.incorrect) 54 55 return documents
Collect all documents in this object.
def
is_empty(self) -> bool:
57 def is_empty(self) -> bool: 58 """ Check if this feedback item contains any actual feedback. """ 59 60 return ((self.general is None) and (self.correct is None) and (self.incorrect is None))
Check if this feedback item contains any actual feedback.
def
to_pod( self, context: Optional[edq.util.common.SerializationContext] = None) -> Union[bool, float, int, str, List[ForwardRef('PODType')], Dict[str, ForwardRef('PODType')], NoneType]:
67 def to_pod(self, 68 context: typing.Union[edq.util.serial.SerializationContext, None] = None, 69 ) -> edq.util.serial.PODType: 70 if (self.is_empty()): 71 return None 72 73 if ((self.general is not None) and (self.correct is None) and (self.incorrect is None)): 74 return self.general.to_pod(context) 75 76 return super().to_pod(context)
Get a POD representation of this object.
The default implementation will convert to a dict (similar to a DictSerializer).
@classmethod
def
from_raw_data( cls, raw_data: Any, context: edq.util.common.SerializationContext) -> Feedback:
78 @classmethod 79 def from_raw_data(cls, 80 raw_data: typing.Any, 81 context: edq.util.serial.SerializationContext, 82 ) -> 'Feedback': 83 """ Parse out feedback from one of several allowed forms. """ 84 85 if (raw_data is None): 86 return Feedback() 87 88 if (isinstance(raw_data, str)): 89 parsed_text = quizcomp.parser.document.ParsedDocument.parse_text(raw_data, context) 90 return Feedback(general = parsed_text) 91 92 quizcomp.model.errors.check_type(raw_data, dict, "'feedback'") 93 94 data: typing.Dict[str, typing.Any] = typing.cast(typing.Dict[str, typing.Any], raw_data) 95 result = {} 96 97 allowed_keys = ['general', 'correct', 'incorrect'] 98 actual_keys = list(data.keys()) 99 100 bad_keys = list(sorted(set(actual_keys) - set(allowed_keys))) 101 if (len(bad_keys) > 0): 102 raise quizcomp.model.errors.QuestionValidationError( 103 f"Unknown keys in feedback ({bad_keys}). Allowed keys: {allowed_keys}.", 104 context = edq.util.serial.SerializationContext) 105 106 for (key, value) in data.items(): 107 if (value is None): 108 continue 109 110 quizcomp.model.errors.check_type(value, str, f"'{key}' feedback value") 111 112 value = str(value).strip() 113 if (len(value) == 0): 114 continue 115 116 result[key] = quizcomp.parser.document.ParsedDocument.parse_text(value, context) 117 118 return Feedback(**result)
Parse out feedback from one of several allowed forms.