Exemplo n.º 1
0
    def __init__(self, vctx, location, page_desc):
        super(ChoiceQuestion, self).__init__(vctx, location, page_desc)

        correct_choice_count = 0
        for choice_idx, choice in enumerate(page_desc.choices):
            try:
                choice = str(choice)
            except:
                raise ValidationError(
                    string_concat(
                        "%(location)s, ",
                        _("choice %(idx)d: unable to convert to string")) % {
                            'location': location,
                            '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, %(n_correct)d found")) % {
                          'location': location,
                          'n_correct': correct_choice_count
                      })
Exemplo n.º 2
0
    def __init__(self, vctx, location, page_desc):
        super(ChoiceQuestionBase, self).__init__(vctx, location, page_desc)

        self.correct_choice_count = 0
        self.disregard_choice_count = 0
        self.always_correct_choice_count = 0
        for choice_idx, choice in enumerate(page_desc.choices):
            try:
                choice = str(choice)
            except:
                raise ValidationError(
                        string_concat(
                            "%(location)s, ",
                            _("choice %(idx)d: unable to convert to string")
                            )
                        % {'location': location, 'idx': choice_idx+1})

            if choice.startswith(self.CORRECT_TAG):
                self.correct_choice_count += 1

            if choice.startswith(self.DISREGARD_TAG):
                self.disregard_choice_count += 1

            if choice.startswith(self.ALWAYS_CORRECT_TAG):
                self.always_correct_choice_count += 1

            if vctx is not None:
                validate_markup(vctx, location,
                        remove_prefix(self.DISREGARD_TAG,
                            remove_prefix(self.CORRECT_TAG,
                                remove_prefix(self.ALWAYS_CORRECT_TAG,
                                    choice))))
Exemplo n.º 3
0
    def __init__(self, vctx, location, page_desc):
        super(ChoiceQuestionBase, self).__init__(vctx, location, page_desc)

        self.correct_choice_count = 0
        self.disregard_choice_count = 0
        for choice_idx, choice in enumerate(page_desc.choices):
            try:
                choice = str(choice)
            except:
                raise ValidationError(
                        string_concat(
                            "%(location)s, ",
                            _("choice %(idx)d: unable to convert to string")
                            )
                        % {'location': location, 'idx': choice_idx+1})

            if choice.startswith(self.CORRECT_TAG):
                self.correct_choice_count += 1

            if choice.startswith(self.DISREGARD_TAG):
                self.disregard_choice_count += 1

            if vctx is not None:
                validate_markup(vctx, location,
                        remove_prefix(self.DISREGARD_TAG,
                            remove_prefix(self.CORRECT_TAG,
                                choice)))
Exemplo n.º 4
0
    def __init__(self, vctx, location, page_desc):
        super(ChoiceQuestion, self).__init__(vctx, location, page_desc)

        correct_choice_count = 0
        for choice_idx, choice in enumerate(page_desc.choices):
            try:
                choice = str(choice)
            except:
                raise ValidationError(
                        string_concat(
                            "%(location)s, ",
                            _("choice %(idx)d: unable to convert to string")
                            )
                        % {'location': location, '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, %(n_correct)d found")
                    % {
                        'location': location,
                        'n_correct': correct_choice_count})
Exemplo n.º 5
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
Exemplo 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
Exemplo n.º 7
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
Exemplo n.º 8
0
    def __init__(self, vctx, location, page_desc):
        super(SurveyChoiceQuestion, self).__init__(vctx, location, page_desc)

        for choice_idx, choice in enumerate(page_desc.choices):
            if not isinstance(choice, six.string_types):
                raise ValidationError("%s, choice %d: not a string" %
                                      (location, choice_idx + 1))

            if vctx is not None:
                validate_markup(vctx, location, choice)
Exemplo n.º 9
0
    def parse_from_yaml(cls, vctx, location, node):
        # could be a number or a bool due to sloppy YAML
        try:
            node = str(node)
        except Exception:
            raise ValidationError(
                _("%(location)s: unable to convert to string") %
                {'location': location})

        tag_mode_dict = {
            cls.CORRECT_TAG: ChoiceModes.CORRECT,
            cls.DISREGARD_TAG: ChoiceModes.DISREGARD,
            cls.ALWAYS_CORRECT_TAG: ChoiceModes.ALWAYS_CORRECT
        }

        s = node

        item_mode = [None]

        def find_tag_by_mode(mode):
            for k, v in tag_mode_dict.items():  # pragma: no branch
                if v == mode:
                    return k

        def mode_from_prefix(s):
            for prefix in tag_mode_dict.keys():
                if s.startswith(prefix):
                    s = s[len(prefix):].strip()

                    if item_mode[0] is not None:
                        raise ValidationError(
                            _("%(location)s: more than one choice modes "
                              "set: '%(modes)s'") % {
                                  'location':
                                  location,
                                  'modes':
                                  "".join(
                                      [find_tag_by_mode(item_mode[0]), prefix])
                              })

                    item_mode[0] = tag_mode_dict[prefix]
                    s = mode_from_prefix(s)
            return s

        s = mode_from_prefix(s)

        if item_mode[0] is None:
            item_mode[0] = ChoiceModes.INCORRECT

        if vctx is not None:
            validate_markup(vctx, location, s)

        return ChoiceInfo(item_mode[0], s)
Exemplo n.º 10
0
    def parse_from_yaml(cls, vctx, location, node):
        # could be a number or a bool due to sloppy YAML
        try:
            node = str(node)
        except Exception:
            raise ValidationError(
                    _("%(location)s: unable to convert to string")
                    % {'location': location})

        tag_mode_dict = {
            cls.CORRECT_TAG: ChoiceModes.CORRECT,
            cls.DISREGARD_TAG: ChoiceModes.DISREGARD,
            cls.ALWAYS_CORRECT_TAG: ChoiceModes.ALWAYS_CORRECT
        }

        s = node

        item_mode = [None]

        def find_tag_by_mode(mode):
            for k, v in six.iteritems(tag_mode_dict):  # pragma: no branch
                if v == mode:
                    return k

        def mode_from_prefix(s):
            for prefix in tag_mode_dict.keys():
                if s.startswith(prefix):
                    s = s[len(prefix):].strip()

                    if item_mode[0] is not None:
                        raise ValidationError(
                                _("%(location)s: more than one choice modes "
                                  "set: '%(modes)s'")
                                % {'location': location,
                                   'modes':
                                       "".join([find_tag_by_mode(item_mode[0]),
                                                  prefix])
                                   })

                    item_mode[0] = tag_mode_dict[prefix]
                    s = mode_from_prefix(s)
            return s

        s = mode_from_prefix(s)

        if item_mode[0] is None:
            item_mode[0] = ChoiceModes.INCORRECT

        if vctx is not None:
            validate_markup(vctx, location, s)

        return ChoiceInfo(item_mode[0], s)
Exemplo n.º 11
0
    def __init__(self, vctx, location, page_desc):
        super(SurveyChoiceQuestion, self).__init__(vctx, location, page_desc)

        for choice_idx, choice in enumerate(page_desc.choices):
            try:
                choice = str(choice)
            except:
                raise ValidationError(
                    string_concat("%(location)s, ", _("choice %(idx)d: unable to convert to string"))
                    % {"location": location, "idx": choice_idx + 1}
                )

            if vctx is not None:
                validate_markup(vctx, location, choice)
Exemplo n.º 12
0
    def __init__(self, vctx, location, page_desc):
        super(SurveyChoiceQuestion, self).__init__(vctx, location, page_desc)

        for choice_idx, choice in enumerate(page_desc.choices):
            try:
                choice = str(choice)
            except:
                raise ValidationError(
                    string_concat(
                        "%(location)s, ",
                        _("choice %(idx)d: unable to convert to string")
                        )
                    % {"location": location, "idx": choice_idx+1})

            if vctx is not None:
                validate_markup(vctx, location, choice)
Exemplo n.º 13
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)
Exemplo n.º 14
0
    def __init__(self, vctx, location, page_desc):
        super(ChoiceQuestion, self).__init__(vctx, location, page_desc)

        correct_choice_count = 0
        for choice_idx, choice in enumerate(page_desc.choices):
            if not isinstance(choice, six.string_types):
                raise ValidationError("%s, choice %d: not a string"
                        % (location, 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("%s: one or more correct answer(s) "
                    "expected, %d found" % (location, correct_choice_count))
Exemplo n.º 15
0
    def __init__(self, vctx, location, page_desc):
        super(ChoiceQuestion, self).__init__(vctx, location, page_desc)

        correct_choice_count = 0
        for choice_idx, choice in enumerate(page_desc.choices):
            if not isinstance(choice, six.string_types):
                raise ValidationError("%s, choice %d: not a string" %
                                      (location, 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("%s: one or more correct answer(s) "
                                  "expected, %d found" %
                                  (location, correct_choice_count))
Exemplo n.º 16
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
Exemplo n.º 17
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)
Exemplo n.º 18
0
    def __init__(self, vctx, location, page_desc):
        super(InlineMultiQuestion, self).__init__(vctx, location, page_desc)

        expanded_question = page_desc.question

        self.embedded_wrapped_name_list = WRAPPED_NAME_RE.findall(
            expanded_question)
        self.embedded_name_list = NAME_RE.findall(expanded_question)

        answer_instance_list = []

        for idx, name in enumerate(self.embedded_name_list):
            answers_desc = getattr(self.page_desc.answers, name)

            parsed_answer = parse_question(vctx, location, name, answers_desc)
            answer_instance_list.append(parsed_answer)

        self.answer_instance_list = answer_instance_list

        from relate.utils import struct_to_dict
        answers_name_list = struct_to_dict(page_desc.answers).keys()

        invalid_answer_name = []
        invalid_embedded_name = []

        if not answer_instance_list:
            raise ValidationError(
                string_concat(
                    "%(location)s: ",
                    _("InlineMultiQuestion requires at least one "
                      "answer field to be defined.")) % {'location': location})

        for answers_name in answers_name_list:
            if NAME_VALIDATE_RE.match(answers_name) is None:
                invalid_answer_name.append(answers_name)
        if len(invalid_answer_name) > 0:
            raise ValidationError(
                string_concat(
                    "%s: ", _("invalid answers name %s. "),
                    _("A valid name should start with letters. "
                      "Alphanumeric with underscores. "
                      "Do not use spaces.")) % (location, ", ".join(
                          ["'" + name + "'" for name in invalid_answer_name])))

        for embedded_name in self.embedded_name_list:
            if NAME_VALIDATE_RE.match(embedded_name) is None:
                invalid_embedded_name.append(embedded_name)
        if len(invalid_embedded_name) > 0:
            raise ValidationError(
                string_concat(
                    "%s: ", _("invalid embedded question name %s. "),
                    _("A valid name should start with letters. "
                      "Alphanumeric with underscores. "
                      "Do not use spaces.")) % (location, ", ".join(
                          ["'" + name + "'"
                           for name in invalid_embedded_name])))

        if len(set(self.embedded_name_list)) < len(self.embedded_name_list):
            duplicated = list(
                set([
                    x for x in self.embedded_name_list
                    if self.embedded_name_list.count(x) > 1
                ]))
            raise ValidationError(
                string_concat("%s: ",
                              _("embedded question name %s not unique.")) %
                (location, ", ".join(duplicated)))

        no_answer_set = set(self.embedded_name_list) - set(answers_name_list)
        redundant_answer_list = list(
            set(answers_name_list) - set(self.embedded_name_list))

        if no_answer_set:
            raise ValidationError(
                string_concat(
                    "%s: ",
                    _("correct answer(s) not provided for question %s.")) %
                (location, ", ".join(
                    ["'" + item + "'" for item in list(no_answer_set)])))

        if redundant_answer_list:
            if vctx is not None:
                vctx.add_warning(
                    location,
                    _("redundant answers %s provided for "
                      "non-existing question(s).") % ", ".join(
                          ["'" + item + "'"
                           for item in redundant_answer_list]))

        if vctx is not None:
            validate_markup(vctx, location, page_desc.question)

            def reverse_func(*args, **kwargs):
                pass

            # FIXME This is a bit redundant since validate_markup already calls
            # markup_to_html.
            remainder_html = markup_to_html(vctx,
                                            page_desc.question,
                                            reverse_func=reverse_func)

            html_list = []
            for wrapped_name in self.embedded_wrapped_name_list:
                [html, remainder_html] = remainder_html.split(wrapped_name)
                html_list.append(html)

            if remainder_html != "":
                html_list.append(remainder_html)

            # make sure all [[ and ]] are paired.
            embedded_removed = " ".join(html_list)

            for sep in ["[[", "]]"]:
                if sep in embedded_removed:
                    raise ValidationError(
                        string_concat("%s: ", _("have unpaired '%s'.")) %
                        (location, sep))

            for idx, name in enumerate(self.embedded_name_list):
                answers_desc = getattr(page_desc.answers, name)

                parse_question(vctx, location, name, answers_desc)
Exemplo n.º 19
0
    def __init__(self, vctx, location, page_desc):
        super(InlineMultiQuestion, self).__init__(
                vctx, location, page_desc)

        expanded_question = page_desc.question

        self.embedded_wrapped_name_list = WRAPPED_NAME_RE.findall(expanded_question)
        self.embedded_name_list = NAME_RE.findall(expanded_question)

        answer_instance_list = []

        for idx, name in enumerate(self.embedded_name_list):
            answers_desc = getattr(self.page_desc.answers, name)

            parsed_answer = parse_question(
                    vctx, location, name, answers_desc)
            answer_instance_list.append(parsed_answer)

        self.answer_instance_list = answer_instance_list

        from relate.utils import struct_to_dict
        answers_name_list = struct_to_dict(page_desc.answers).keys()

        invalid_answer_name = []

        if not answer_instance_list:
            raise ValidationError(
                    string_concat(
                        "%(location)s: ",
                        _("InlineMultiQuestion requires at least one "
                        "answer field to be defined."))
                    % {'location': location})

        for answers_name in answers_name_list:
            if NAME_VALIDATE_RE.match(answers_name) is None:
                invalid_answer_name.append(answers_name)
        if invalid_answer_name:
            raise ValidationError(
                    string_concat(
                        "%s: ",
                        _("invalid answers name %s. "),
                        _("A valid name should start with letters. "
                            "Alphanumeric with underscores. "
                            "Do not use spaces."))
                    % (
                        location,
                        ", ".join([
                            "'" + name + "'"
                            for name in invalid_answer_name])
                        ))

        if len(set(self.embedded_name_list)) < len(self.embedded_name_list):
            duplicated = list(
                 set([x for x in self.embedded_name_list
                      if self.embedded_name_list.count(x) > 1]))
            raise ValidationError(
                 string_concat(
                     "%s: ",
                     _("embedded question name %s not unique."))
                 % (location, ", ".join(["'%s'" % d for d in sorted(duplicated)])))

        redundant_answer_list = list(set(answers_name_list)
                - set(self.embedded_name_list))

        if redundant_answer_list:
            if vctx is not None:
                vctx.add_warning(location,
                        _("redundant answers %s provided for "
                            "non-existing question(s).")
                        % ", ".join(
                            ["'" + item + "'"
                                for item in redundant_answer_list]))

        if vctx is not None:
            validate_markup(vctx, location, page_desc.question)

            remainder_html = page_desc.question
            html_list = []
            for wrapped_name in self.embedded_wrapped_name_list:
                [html, remainder_html] = remainder_html.split(wrapped_name)
                html_list.append(html)

            if remainder_html.strip():
                html_list.append(remainder_html)

            # make sure all [[ and ]] are paired.
            embedded_removed = " ".join(html_list)

            for sep in ["[[", "]]"]:
                if sep in embedded_removed:
                    raise ValidationError(
                        string_concat(
                            "%s: ",
                            _("question has unpaired '%s'."))
                        % (location, sep))

            for idx, name in enumerate(self.embedded_name_list):
                answers_desc = getattr(page_desc.answers, name)

                parse_question(vctx, location, name, answers_desc)