def __init__(self, vctx, location, name, answers_desc): super(ShortAnswer, self).__init__(vctx, location, name, answers_desc) validate_struct( vctx, location, answers_desc, required_attrs=(("type", str), ("correct_answer", list)), allowed_attrs=( ("weight", (int, float)), ("prepended_text", str), ("appended_text", str), ("hint", str), ("hint_title", str), ("width", (str, int, float)), ("required", bool), ), ) self.weight = getattr(answers_desc, "weight", 0) if len(answers_desc.correct_answer) == 0: raise ValidationError( string_concat("%s: ", _("at least one answer must be provided")) % location) self.hint = getattr(self.answers_desc, "hint", "") self.width = getattr(self.answers_desc, "width", None) parsed_length = self.get_length_attr_em(location, self.width) self.width = 0 if parsed_length is not None: self.width = max(MINIMUN_WIDTH, parsed_length) else: self.width = DEFAULT_WIDTH self.width_str = "width: " + str(self.width) + "em" self.matchers = [ parse_matcher( vctx, string_concat( "%s, ", # Translators: refers to optional # correct answer for checking # correctness sumbitted by students. _("answer"), " %d") % (location, i + 1), answer) for i, answer in enumerate(answers_desc.correct_answer) ] if not any(matcher.correct_answer_text() is not None for matcher in self.matchers): raise ValidationError( string_concat( "%s: ", _("no matcher is able to provide a plain-text " "correct answer")) % location)
def __init__(self, vctx, location, matcher_desc): self.matcher_desc = matcher_desc validate_struct( vctx, location, matcher_desc, required_attrs=(("type", str), ("value", (int, float, str))), allowed_attrs=(("rtol", (int, float, str)), ("atol", (int, float, str))), ) try: self.matcher_desc.value = float_or_sympy_evalf(matcher_desc.value) except: raise ValidationError(string_concat("%s: 'value' ", _("does not provide a valid float literal")) % location) if hasattr(matcher_desc, "rtol"): try: self.matcher_desc.rtol = float_or_sympy_evalf(matcher_desc.rtol) except: raise ValidationError( string_concat("%s: 'rtol' ", _("does not provide a valid float literal")) % location ) if hasattr(matcher_desc, "atol"): try: self.matcher_desc.atol = float_or_sympy_evalf(matcher_desc.atol) except: raise ValidationError( string_concat("%s: 'atol' ", _("does not provide a valid float literal")) % location ) if not hasattr(matcher_desc, "atol") and not hasattr(matcher_desc, "rtol") and vctx is not None: vctx.add_warning( location, _("Float match should have either rtol or atol--" "otherwise it will match any number") )
def __init__(self, vctx, location, page_desc): validate_struct( location, page_desc, required_attrs=[ ("type", str), ("id", str), ("value", (int, float)), ("title", str), ("prompt", str), ("timeout", (int, float)), ], allowed_attrs=[ ("setup_code", str), ("names_for_user", list), ("names_from_user", list), ("test_code", str), ("correct_code", str), ], ) if vctx is not None: validate_markup(vctx, location, page_desc.prompt) PageBase.__init__(self, vctx, location, page_desc.id) self.page_desc = page_desc
def __init__(self, vctx, location, matcher_desc): self.matcher_desc = matcher_desc validate_struct( vctx, location, matcher_desc, required_attrs=( ("type", str), ("value", (int, float, str)), ), allowed_attrs=( ("rtol", (int, float, str)), ("atol", (int, float, str)), ), ) try: self.matcher_desc.value = \ float_or_sympy_evalf(matcher_desc.value) except: raise ValidationError( string_concat("%s: 'value' ", _("does not provide a valid float literal")) % location) if hasattr(matcher_desc, "rtol"): try: self.matcher_desc.rtol = \ float_or_sympy_evalf(matcher_desc.rtol) except: raise ValidationError( string_concat("%s: 'rtol' ", _("does not provide a valid float literal")) % location) if matcher_desc.value == 0: raise ValidationError( string_concat("%s: 'rtol' ", _("not allowed when 'value' is zero")) % location) if hasattr(matcher_desc, "atol"): try: self.matcher_desc.atol = \ float_or_sympy_evalf(matcher_desc.atol) except: raise ValidationError( string_concat("%s: 'atol' ", _("does not provide a valid float literal")) % location) if (not hasattr(matcher_desc, "atol") and not hasattr(matcher_desc, "rtol") and vctx is not None): vctx.add_warning( location, _("Float match should have either rtol or atol--" "otherwise it will match any number"))
def __init__(self, vctx, location, name, answers_desc): super(ChoicesAnswer, self).__init__( vctx, location, name, answers_desc) validate_struct( vctx, location, answers_desc, required_attrs=( ("type", str), ("choices", list) ), allowed_attrs=( ("weight", (int, float)), ("hint", str), ("hint_title", str), ("required", bool), ), ) self.weight = getattr(answers_desc, "weight", 0) correct_choice_count = 0 for choice_idx, choice in enumerate(answers_desc.choices): try: choice = str(choice) except Exception: raise ValidationError( string_concat( "%(location)s: '%(answer_name)s' ", _("choice %(idx)d: unable to convert to string") ) % {'location': location, 'answer_name': self.name, 'idx': choice_idx+1}) if choice.startswith(self.CORRECT_TAG): correct_choice_count += 1 if vctx is not None: validate_markup(vctx, location, remove_prefix(self.CORRECT_TAG, choice)) if correct_choice_count < 1: raise ValidationError( string_concat( "%(location)s: ", _("one or more correct answer(s) expected " " for question '%(question_name)s', " "%(n_correct)d found")) % { 'location': location, 'question_name': self.name, 'n_correct': correct_choice_count}) self.hint = getattr(self.answers_desc, "hint", "") self.width = 0
def __init__(self, vctx, location, validator_desc): self.validator_desc = validator_desc validate_struct( vctx, location, validator_desc, required_attrs=(("type", str), ), allowed_attrs=(("page_type", str), ), )
def __init__(self, vctx, location, page_desc): """ :arg vctx: a :class:`course.validation.ValidationContext`, or None if no validation is desired """ self.location = location if isinstance(page_desc, Struct): if vctx is not None: validate_struct( vctx, location, page_desc, required_attrs=self.required_attrs(), allowed_attrs=self.allowed_attrs()) # {{{ validate access_rules if hasattr(page_desc, "access_rules"): ar_loc = "%s: access rules" % location validate_struct( vctx, ar_loc, page_desc.access_rules, required_attrs=(), allowed_attrs=( ("add_permissions", list), ("remove_permissions", list), )) from course.validation import validate_flow_permission for attr in ["add_permissions", "remove_permissions"]: if hasattr(page_desc.access_rules, attr): for perm in getattr(page_desc.access_rules, attr): validate_flow_permission( vctx, "%s: %s" % (ar_loc, attr), perm) # }}} self.page_desc = page_desc self.is_optional_page = getattr(page_desc, "is_optional_page", False) else: from warnings import warn warn(_("Not passing page_desc to PageBase.__init__ is deprecated"), DeprecationWarning) id = page_desc del page_desc self.id = id
def __init__(self, vctx, location, validator_desc): self.validator_desc = validator_desc validate_struct( vctx, location, validator_desc, required_attrs=( ("type", str), ), allowed_attrs=( ("page_type", str), ), )
def __init__(self, vctx, location, matcher_desc): self.matcher_desc = matcher_desc validate_struct( vctx, location, matcher_desc, required_attrs=( ("type", str), ("value", (int, float)), ), allowed_attrs=( ("rtol", (int, float)), ("atol", (int, float)), ), )
def __init__(self, vctx, location, page_desc): validate_struct( location, page_desc, required_attrs=[ ("type", str), ("id", str), ("content", str), ("title", str), ], allowed_attrs=[], ) PageBase.__init__(self, vctx, location, page_desc.id) self.page_desc = page_desc if vctx is not None: validate_markup(vctx, location, page_desc.content)
def __init__(self, vctx, location, page_desc): validate_struct( location, page_desc, required_attrs=[ ("type", str), ("id", str), ("value", (int, float)), ("title", str), ("choices", list), ("prompt", str), ], allowed_attrs=[ ("shuffle", bool), ], ) correct_choice_count = 0 for choice in page_desc.choices: if choice.startswith(self.CORRECT_TAG): correct_choice_count += 1 if vctx is not None: validate_markup(vctx, location, remove_prefix(self.CORRECT_TAG, choice)) if correct_choice_count < 1: raise ValidationError("%s: one or more correct answer(s) " "expected, %d found" % (location, correct_choice_count)) if vctx is not None: validate_markup(vctx, location, page_desc.prompt) PageBase.__init__(self, vctx, location, page_desc.id) self.page_desc = page_desc self.shuffle = getattr(self.page_desc, "shuffle", False)
def __init__(self, vctx, location, page_desc): validate_struct( location, page_desc, required_attrs=[ ("type", str), ("id", str), ("value", (int, float)), ("title", str), ("answers", list), ("prompt", str), ], allowed_attrs=[], ) if len(page_desc.answers) == 0: raise ValidationError("%s: at least one answer must be provided" % location) self.matchers = [ parse_matcher( vctx, "%s, answer %d" % (location, i+1), answer) for i, answer in enumerate(page_desc.answers)] if not any(matcher.correct_answer_text() is not None for matcher in self.matchers): raise ValidationError("%s: no matcher is able to provide a plain-text " "correct answer") if vctx is not None: validate_markup(vctx, location, page_desc.prompt) PageBase.__init__(self, vctx, location, page_desc.id) self.page_desc = page_desc
def __init__(self, vctx, location, matcher_desc): self.matcher_desc = matcher_desc validate_struct( vctx, location, matcher_desc, required_attrs=( ("type", str), ("value", six.integer_types + (float, str)), ), allowed_attrs=( ("rtol", six.integer_types + (float, str)), ("atol", six.integer_types + (float, str)), ), ) try: self.matcher_desc.value = \ float_or_sympy_evalf(matcher_desc.value) except Exception: raise ValidationError( string_concat( "%s: 'value' ", _("does not provide a valid float literal")) % location) if hasattr(matcher_desc, "rtol"): try: self.matcher_desc.rtol = \ float_or_sympy_evalf(matcher_desc.rtol) except Exception: raise ValidationError( string_concat( "%s: 'rtol' ", _("does not provide a valid float literal")) % location) if matcher_desc.value == 0: raise ValidationError( string_concat( "%s: 'rtol' ", _("not allowed when 'value' is zero")) % location) if hasattr(matcher_desc, "atol"): try: self.matcher_desc.atol = \ float_or_sympy_evalf(matcher_desc.atol) except Exception: raise ValidationError( string_concat( "%s: 'atol' ", _("does not provide a valid float literal")) % location) else: if matcher_desc.value == 0: vctx.add_warning(location, _("Float match for 'value' zero should have atol--" "otherwise it will match any number")) if ( not matcher_desc.value == 0 and not hasattr(matcher_desc, "atol") and not hasattr(matcher_desc, "rtol") and vctx is not None): vctx.add_warning(location, _("Float match should have either rtol or atol--" "otherwise it will match any number"))
def __init__(self, vctx, location, name, answers_desc): super(ShortAnswer, self).__init__( vctx, location, name, answers_desc) validate_struct( vctx, location, answers_desc, required_attrs=( ("type", str), ("correct_answer", list) ), allowed_attrs=( ("weight", (int, float)), ("prepended_text", str), ("appended_text", str), ("hint", str), ("hint_title", str), ("width", (str, int, float)), ("required", bool), ), ) weight = getattr(answers_desc, "weight", 0) if weight < 0: raise ValidationError( string_concat( "%s: %s: ", _("'weight' must be a non-negative value, " "got '%s' instead") % str(weight)) % (location, self.name)) self.weight = weight if len(answers_desc.correct_answer) == 0: raise ValidationError( string_concat( "%s: %s: ", _("at least one answer must be provided")) % (location, self.name)) self.hint = getattr(self.answers_desc, "hint", "") width = getattr(self.answers_desc, "width", None) parsed_length = self.get_length_attr_em( "%s: %s: 'width'" % (location, self.name), width) self.width = 0 if parsed_length is not None: self.width = max(MINIMUN_WIDTH, parsed_length) else: self.width = DEFAULT_WIDTH self.width_str = "width: " + str(self.width) + "em" self.matchers = [ parse_matcher( vctx, string_concat("%s, ", # Translators: refers to optional # correct answer for checking # correctness sumbitted by students. _("answer"), " %d") % (location, i+1), answer) for i, answer in enumerate(answers_desc.correct_answer)] if not any(matcher.correct_answer_text() is not None for matcher in self.matchers): raise ValidationError( string_concat( "%s: %s: ", _("no matcher is able to provide a plain-text " "correct answer")) % (location, self.name))