return text
print(e)
-from . import UserInterface
+from .. import error as _error
+from . import UserInterface as _UserInterface
class QuestionCommandLine (_cmd.Cmd):
def __init__(self, ui):
super(QuestionCommandLine, self).__init__()
self.ui = ui
+ if self.ui.quiz.introduction:
+ self.intro = '\n\n'.join([self.intro, self.ui.quiz.introduction])
+ self._tempdir = None
- def preloop(self):
+ def get_question(self):
self.question = self.ui.get_question()
- self._reset()
+ if self.question:
+ self._reset()
+ else:
+ return True # out of questions
+
+ def preloop(self):
+ self.get_question()
def _reset(self):
self.answers = []
+ if self._tempdir:
+ self._tempdir.cleanup() # occasionally redundant, but that's ok
+ self._tempdir = None
self._set_ps1()
def _set_ps1(self):
answer = self.answers[0]
else:
answer = ''
- correct = self.ui.process_answer(question=self.question, answer=answer)
+ kwargs = {}
+ if self._tempdir:
+ kwargs['tempdir'] = self._tempdir
+ correct,details = self.ui.process_answer(
+ question=self.question, answer=answer, **kwargs)
if correct:
print(_colorize(self.ui.colors['correct'], 'correct\n'))
else:
- print(_colorize(self.ui.colors['incorrect'], 'incorrect\n'))
- self.question = self.ui.get_question()
- if not self.question:
- return True # out of questions
- self._reset()
+ print(_colorize(self.ui.colors['incorrect'], 'incorrect'))
+ if details:
+ print(_colorize(
+ self.ui.colors['incorrect'], '{}\n'.format(details)))
+ else:
+ print('')
+ return self.get_question()
def do_answer(self, arg):
"""Explicitly add a line to your answer
"""
return self.default(arg)
+ def do_shell(self, arg):
+ """Run a shell command in the question temporary directory
+
+ For example, you can spawn an interactive session with:
+
+ quizzer? !bash
+
+ If the question does not allow interactive sessions, this
+ action is a no-op.
+ """
+ if getattr(self.question, 'allow_interactive', False):
+ if not self._tempdir:
+ self._tempdir = self.question.setup_tempdir()
+ try:
+ self._tempdir.invoke(
+ interpreter='/bin/sh', text=arg, stdout=None, stderr=None,
+ universal_newlines=False,
+ env=self.question.get_environment())
+ except (KeyboardInterrupt, _error.CommandError) as e:
+ if isinstance(e, KeyboardInterrupt):
+ LOG.warning('KeyboardInterrupt')
+ else:
+ LOG.warning(e)
+ self._tempdir.cleanup()
+ self._tempdir = None
+
def do_quit(self, arg):
"Stop taking the quiz"
self._reset()
def do_skip(self, arg):
"Skip the current question, and continue with the quiz"
self.ui.stack.append(self.question)
- self.question = self.ui.get_question()
- if not self.question:
- return True # out of questions
- self._reset()
+ return self.get_question()
def do_hint(self, arg):
"Show a hint for the current question"
self._reset()
print(self.question.format_help())
+ def do_copyright(self, arg):
+ "Print the quiz copyright notice"
+ if self.ui.quiz.copyright:
+ print('\n'.join(self.ui.quiz.copyright))
+ else:
+ print(self.ui.quiz.copyright)
+
def do_help(self, arg):
'List available commands with "help" or detailed help with "help cmd"'
if not arg:
super(QuestionCommandLine, self).do_help(arg)
-class CommandLineInterface (UserInterface):
+class CommandLineInterface (_UserInterface):
colors = { # listed in pygments.console.light_colors
'question': 'turquoise',
'prompt': 'blue',
}
def run(self):
- if not self.stack:
- return
- cmd = QuestionCommandLine(ui=self)
- cmd.cmdloop()
- print()
+ if self.stack:
+ cmd = QuestionCommandLine(ui=self)
+ cmd.cmdloop()
+ print()
+ self._display_results()
- def display_results(self):
+ def _display_results(self):
print(_colorize(self.colors['result'], 'results:'))
for question in self.quiz:
if question.id in self.answers:
- self.display_result(question=question)
+ self._display_result(question=question)
print()
- self.display_totals()
+ self._display_totals()
- def display_result(self, question):
+ def _display_result(self, question):
answers = self.answers.get(question.id, [])
print('question:')
print(' {}'.format(
question.format_prompt(newline='\n '))))
la = len(answers)
lc = len([a for a in answers if a['correct']])
- print('answers: {}/{} ({:.2f})'.format(lc, la, float(lc)/la))
+ if la:
+ print('answers: {}/{} ({:.2f})'.format(lc, la, float(lc)/la))
for answer in answers:
if answer['correct']:
correct = 'correct'
print(' you answered: {}'.format(ans))
print(' which was: {}'.format(correct))
- def display_totals(self):
+ def _display_totals(self):
answered = self.answers.get_answered(questions=self.quiz)
correctly_answered = self.answers.get_correctly_answered(
questions=self.quiz)
la = len(answered)
lc = len(correctly_answered)
print('answered {} of {} questions'.format(la, len(self.quiz)))
- print(('of the answered questions, {} ({:.2f}) were answered correctly'
- ).format(lc, float(lc)/la))
+ if la:
+ print(('of the answered questions, '
+ '{} ({:.2f}) were answered correctly'
+ ).format(lc, float(lc)/la))