From 3fc4be57135e168ae5f53ea8e1784e5aac5ad64c Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Thu, 14 Mar 2013 08:13:08 -0400 Subject: [PATCH] question: Move ChoiceQuestion.open_ended to Question.accept_all Accepting all answers is a more general case of an open ended multiple choice question. It also allows us to ask questions that are difficult or impossible to grade automatically. We just record the student's answer for the grader to look at later. --- quizzer/question.py | 22 ++++++++++++++-------- quizzer/ui/cli.py | 2 +- quizzer/ui/wsgi.py | 8 ++++---- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/quizzer/question.py b/quizzer/question.py index cc4cfff..95d9022 100644 --- a/quizzer/question.py +++ b/quizzer/question.py @@ -34,6 +34,7 @@ class Question (object): 'id', 'prompt', 'answer', + 'accept_all', 'multiline', 'help', 'dependencies', @@ -57,20 +58,26 @@ class Question (object): def __setstate__(self, state): if 'id' not in state: state['id'] = state.get('prompt', None) - if 'multiline' not in state: - state['multiline'] = False if 'dependencies' not in state: state['dependencies'] = [] if 'tags' not in state: state['tags'] = set() else: state['tags'] = set(state['tags']) + for attr in ['accept_all', 'multiline']: + if attr not in state: + state[attr] = False for attr in self._state_attributes: if attr not in state: state[attr] = None self.__dict__.update(state) def check(self, answer): + if self.accept_all: + return (True, None) + return self._check(answer) + + def _check(self, answer): correct = answer == self.answer details = None if not correct: @@ -95,7 +102,7 @@ class NormalizedStringQuestion (Question): def normalize(self, string): return string.strip().lower() - def check(self, answer): + def _check(self, answer): normalized_answer = self.normalize(answer) correct = normalized_answer == self.normalize(self.answer) details = None @@ -108,17 +115,16 @@ class NormalizedStringQuestion (Question): class ChoiceQuestion (Question): _state_attributes = Question._state_attributes + [ 'display_choices', - 'open_ended', ] def __setstate__(self, state): - for key in ['display_choices', 'open_ended']: + for key in ['display_choices']: if key not in state: state[key] = False super(ChoiceQuestion, self).__setstate__(state) - def check(self, answer): - correct = answer in self.answer or self.open_ended + def _check(self, answer): + correct = answer in self.answer details = None if not correct: details = 'answer ({}) is not in list of expected values'.format( @@ -229,7 +235,7 @@ class ScriptQuestion (Question): return (a_status,a_stdout,a_stderr, t_status,t_stdout,t_stderr) - def check(self, answer=None, tempdir=None): + def _check(self, answer=None, tempdir=None): """Compare the user's answer with expected values Arguments are passed through to ._invoke() for calculating the diff --git a/quizzer/ui/cli.py b/quizzer/ui/cli.py index e91a0dd..cbfa16d 100644 --- a/quizzer/ui/cli.py +++ b/quizzer/ui/cli.py @@ -90,7 +90,7 @@ class QuestionCommandLine (_cmd.Cmd): self.question.display_choices): for i,choice in enumerate(self.question.answer): yield '{}) {}'.format(i, choice) - if self.question.open_ended: + if self.question.accept_all: yield 'or fill in something else' return [] diff --git a/quizzer/ui/wsgi.py b/quizzer/ui/wsgi.py index de2c595..91f4321 100644 --- a/quizzer/ui/wsgi.py +++ b/quizzer/ui/wsgi.py @@ -248,9 +248,9 @@ class QuestionApp (WSGI_DataObject): ('{0}
' ).format(answer) for answer in question.answer] - if question.open_ended: + if question.accept_all: choices.extend([ - '', + '', '']) answer_element = '\n'.join(choices) elif question.multiline: @@ -300,8 +300,8 @@ class QuestionApp (WSGI_DataObject): raise HandlerError(404, 'Not Found') from e if (isinstance(question, _question.ChoiceQuestion) and question.display_choices and - question.open_ended and - raw_answer == 'open_ended'): + question.accept_all and + raw_answer == 'answer-other'): answer = print_answer = data.get('answer-other', None) elif question.multiline: answer = raw_answer.splitlines() -- 2.26.2