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_none = True

Do not include None (null) fields in serialization.

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_empty method that returns true.

Feedback to be shown regardless of the outcome.

Feedback to be shown if the action/choice/answer was correct.

Feedback to be shown if the action/choice/answer was incorrect.

def collect_documents(self) -> List[quizcomp.parser.document.ParsedDocument]:
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.