quizzer: Add ChoiceQuestion.display_choices
authorW. Trevor King <wking@tremily.us>
Thu, 14 Mar 2013 11:32:02 +0000 (07:32 -0400)
committerW. Trevor King <wking@tremily.us>
Thu, 14 Mar 2013 11:32:06 +0000 (07:32 -0400)
This gives us more traditional multiple-choice questions.

quizzer/question.py
quizzer/ui/cli.py
quizzer/ui/wsgi.py

index 3e69abb1541bf8d4b8069291747fbc7b2600fc29..a4da65534bd2a31db57fbc71c116646d14dfdf68 100644 (file)
@@ -106,6 +106,15 @@ class NormalizedStringQuestion (Question):
 
 
 class ChoiceQuestion (Question):
+    _state_attributes = Question._state_attributes + [
+        'display_choices',
+        ]
+
+    def __setstate__(self, state):
+        if 'display_choices' not in state:
+            state['display_choices'] = False
+        super(ChoiceQuestion, self).__setstate__(state)
+
     def check(self, answer):
         correct = answer in self.answer
         details = None
index 579d789696c836d779e3af3d4ae74348d53d644d..7b857b0a06dfe96cecd89afdeda15d4c07199d71 100644 (file)
@@ -28,6 +28,7 @@ except ImportError as e:
     print(e)
 
 from .. import error as _error
+from .. import question as _question
 from . import UserInterface as _UserInterface
 
 
@@ -67,10 +68,16 @@ class QuestionCommandLine (_cmd.Cmd):
     def _set_ps1(self):
         "Pose a question and prompt"
         if self.question:
-            self.prompt = '\n{}\n{}'.format(
+            lines = [
+                '',
                 _colorize(
                     self.ui.colors['question'], self.question.format_prompt()),
-                _colorize(self.ui.colors['prompt'], self._prompt))
+                ]
+            lines.extend(
+                _colorize(self.ui.colors['prompt'], line)
+                for line in self._extra_ps1_lines())
+            lines.append(_colorize(self.ui.colors['prompt'], self._prompt))
+            self.prompt = '\n'.join(lines)
         else:
             self.prompt = _colorize(self.ui.colors['prompt'], self._prompt)
 
@@ -78,6 +85,24 @@ class QuestionCommandLine (_cmd.Cmd):
         "Just prompt (without the question, e.g. for multi-line answers)"
         self.prompt = _colorize(self.ui.colors['prompt'], self._prompt)
 
+    def _extra_ps1_lines(self):
+        if (isinstance(self.question, _question.ChoiceQuestion) and
+                self.question.display_choices):
+            for i,choice in enumerate(self.question.answer):
+                yield '{}) {}'.format(i, choice)
+        return []
+
+    def _process_answer(self, answer):
+        "Back out any mappings suggested by _extra_ps1_lines()"
+        if (isinstance(self.question, _question.ChoiceQuestion) and
+                self.question.display_choices):
+            try:
+                a = int(answer)
+                return self.question.answer[a]
+            except (ValueError, IndexError):
+                pass
+        return answer
+
     def default(self, line):
         self.answers.append(line)
         if self.question.multiline:
@@ -98,6 +123,7 @@ class QuestionCommandLine (_cmd.Cmd):
         kwargs = {}
         if self._tempdir:
             kwargs['tempdir'] = self._tempdir
+        answer = self._process_answer(answer=answer)
         correct,details = self.ui.process_answer(
             question=self.question, answer=answer, **kwargs)
         if correct:
index ca635981c617f70f5d7daafaaca0df2155776cd8..c29323c09bd99b24b4eab116ba8bf60120372776 100644 (file)
@@ -7,6 +7,7 @@ import re as _re
 import urllib.parse as _urllib_parse
 import wsgiref.simple_server as _wsgiref_simple_server
 
+from .. import question as _question
 from . import UserInterface as _UserInterface
 
 
@@ -241,7 +242,13 @@ class QuestionApp (WSGI_DataObject):
         if question is None:
             raise HandlerError(
                 307, 'Temporary Redirect', headers=[('Location', '/results/')])
-        if question.multiline:
+        if (isinstance(question, _question.ChoiceQuestion) and
+                question.display_choices):
+            answer_element = '\n'.join(
+                ('<input type="radio" name="answer" value="{0}"/>{0}<br/>'
+                 ).format(answer)
+                for answer in question.answer)
+        elif question.multiline:
             answer_element = (
                 '<textarea rows="5" cols="60" name="answer"></textarea>')
         else: