Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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")
            )
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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"))
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
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), ),
        )
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
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),
                    ),
                )
Ejemplo n.º 10
0
    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)),
            ),
        )
Ejemplo n.º 11
0
    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)),
                    ),
                )
Ejemplo n.º 12
0
    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)
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
    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
Ejemplo n.º 15
0
    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"))
Ejemplo n.º 16
0
    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))