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 })
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))))
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)))
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})
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, 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, 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)
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)
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)
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)
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)
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): 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))
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))
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, 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): 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)
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)