From 7ac08f910f0c71327e61c55924bd78d55c83cab1 Mon Sep 17 00:00:00 2001 From: Jonathan Harker Date: Mon, 2 Feb 2015 14:36:05 +1300 Subject: [PATCH] Documentation, slight refactor. --- quiz.py | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 118 insertions(+), 6 deletions(-) diff --git a/quiz.py b/quiz.py index 81c34fe..12fd99e 100644 --- a/quiz.py +++ b/quiz.py @@ -1,5 +1,10 @@ #!/usr/bin/env python ## -*- coding: utf-8 -*- +""" +A MozQuizz question library for Python. +See http://moxquizz.de/ for the original implementation in TCL. +""" + from __future__ import unicode_literals, print_function from io import open @@ -10,30 +15,103 @@ class Question: """ category = None + """ + The question category. Arbitrary text; optional. + """ + question = None + """ + The question. Arbitrary text; required. + """ + answer = None + """ + The answer. Arbitrary text; required. Correct answers can also be covered + by the :attr:`regexp` property. + """ + regexp = None + """ + A regular expression that will generate correct answers. Optional. See + also the :attr:`answer` property. + """ + author = None - level = None + """ + The question author. Arbitrary text; optional. + """ + + level = None # Default: NORMAL (constructor) + """ + The difficulty level. Value must be from the :attr:`LEVELS` tuple. + The default value is :attr:`NORMAL`. + """ + comment = None - score = 0 + """ + A comment. Arbitrary text; optional. + """ + + score = 1 + """ + The points scored for the correct answer. Integer value; default is 1. + """ tip = list() + """ + An ordered list of tips (hints) to display to users. Optional. + """ + tipcycle = 0 + """ + Indicates which tip is to be displayed next, if any. + """ TRIVIAL = 1 + """ + A value for :attr:`level` that indicates a question of trivial difficulty. + """ + EASY = 2 + """ + A value for :attr:`level` that indicates a question of easy difficulty. + """ + NORMAL = 3 + """ + A value for :attr:`level` that indicates a question of average or normal + difficulty. + """ + HARD = 4 + """ + A value for :attr:`level` that indicates a question of hard difficulty. + """ + EXTREME = 5 + """ + A value for :attr:`level` that indicates a question of extreme difficulty + or obscurity. + """ LEVELS = (TRIVIAL, EASY, NORMAL, HARD, EXTREME) + """ + The available :attr:`level` difficulty values, :attr:`TRIVIAL`, :attr:`EASY`, + :attr:`NORMAL`, :attr:`HARD` and :attr:`EXTREME`. + """ def __init__(self, attributes_dict): + """ + Constructor that takes a dictionary of MoxQuizz key-value pairs. Usually + called from a :class:`QuestionBank`. + """ + # Set defaults first. + self.level = self.NORMAL self.parse(attributes_dict) def parse(self, attributes_dict): """ - Populate fields from a dictionary of attributes (from a question bank). + Populate fields from a dictionary of attributes, usually provided by a + :class:`QuestionBank` :attr:`~QuestionBank.parse` call. """ ## Valid keys: @@ -69,7 +147,9 @@ class Question: self.category = attributes_dict['Author'] if 'Level' in attributes_dict.keys() and attributes_dict['Level'] in self.LEVELS: - self.level = attributes_dict['level'] + self.level = attributes_dict['Level'] + elif 'Level' in attributes_dict.keys() and attributes_dict['Level'] in QuestionBank.LEVEL_VALUES.keys(): + self.level = QuestionBank.LEVEL_VALUES[attributes_dict['Level']] if 'Comment' in attributes_dict.keys(): self.comment = attributes_dict['Comment'] @@ -90,7 +170,15 @@ class QuestionBank: """ filename = '' + """ + The path or filename of the question bank file. + """ + questions = list() + """ + A list of :class:`Question` objects, constituting the questions in the + question bank. + """ # Case sensitive, to remain backwards-compatible with MoxQuizz. KEYS = ('Answer', @@ -104,17 +192,34 @@ class QuestionBank: 'Tip', 'Tipcycle', ) + """ + The valid attributes available in a MoxQuizz question bank file. + """ + + LEVEL_VALUES = { + 'trivial': Question.TRIVIAL, + 'baby': Question.TRIVIAL, + 'easy': Question.EASY, + 'normal': Question.NORMAL, + 'hard': Question.HARD, + 'difficult': Question.HARD, + 'extreme': Question.EXTREME + } + """ + Text labels for the :attr:`Question.level` difficulty values. + """ def __init__(self, filename): """ - Construct a question bank from a file. + Constructor, takes a MozQuizz-formatted question bank filename. """ self.filename = filename self.questions = self.parse(filename) def parse(self, filename): """ - Read a Moxquizz question bank file into a list. + Read a MoxQuizz-formatted question bank file. Returns a ``list`` of + :class:`Question` objects found in the file. """ questions = list() @@ -149,6 +254,8 @@ class QuestionBank: # Fetch the next parameter. try: (key, value) = line.split(':', 1) + key = key.strip() + value = value.strip() except ValueError: print("Unexpected weirdness in MoxQuizz questionbank '%s', line %s." % (self.filename, i)) continue @@ -162,6 +269,11 @@ class QuestionBank: # Enumerate the Tips. if key == 'Tip': q['Tip'].append(value.strip()) + elif key == 'Level': + if value not in self.LEVEL_VALUES: + print("Unexpected Level value '%s' in MoxQuizz questionbank '%s', line '%s'." % (value, self.filename, i)) + else: + q['Level'] = self.LEVEL_VALUES[value] else: q[key] = value.strip()