1 # Copyright (C) 2013 W. Trevor King <wking@tremily.us>
3 # This file is part of quizzer.
5 # quizzer is free software: you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation, either version 3 of the License, or (at your option) any later
10 # quizzer is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License along with
15 # quizzer. If not, see <http://www.gnu.org/licenses/>.
17 import codecs as _codecs
20 from . import __version__
21 from . import question as _question
25 def __init__(self, questions=None, path=None, encoding=None,
26 copyright=None, introduction=None):
29 super(Quiz, self).__init__(questions)
31 self.encoding = encoding
32 self.copyright = copyright
33 self.introduction = introduction
35 def _open(self, mode='r', path=None, encoding=None):
39 self.encoding = encoding
40 return _codecs.open(self.path, mode, self.encoding)
42 def load(self, **kwargs):
43 with self._open(mode='r', **kwargs) as f:
45 version = data.get('version', None)
46 if version != __version__:
47 raise NotImplementedError('upgrade from {} to {}'.format(
48 version, __version__))
49 self.copyright = data.get('copyright', None)
50 self.introduction = data.get('introduction', None)
51 for state in data['questions']:
52 question_class_name = state.pop('class', 'Question')
53 question_class = _question.QUESTION_CLASS[question_class_name]
58 def save(self, **kwargs):
61 state = question.__getstate__()
62 state['class'] = type(question).__name__
64 'version': __version__,
65 'copyright': self.copyright,
66 'introduction': self.introduction,
67 'questions': questions,
69 with self._open(mode='w', **kwargs) as f:
71 data, f, indent=2, separators=(',', ': '), sort_keys=True)
74 def leaf_questions(self):
75 "Questions that are not dependencies of other question"
78 dependents.update(question.dependencies)
79 return [q for q in self if q.id not in dependents]
81 def get(self, id=None):
82 matches = [q for q in self if q.id == id]
85 elif len(matches) == 0:
87 raise NotImplementedError(
88 'multiple questions with one ID: {}'.format(matches))