Commit 9f9c3fafd7f8bbafd569b126a81969f241f5643b
1 parent
93c4dec9
Exists in
master
and in
1 other branch
minor refactor of questions.py
Showing
1 changed file
with
56 additions
and
86 deletions
Show diff stats
perguntations/questions.py
| @@ -32,44 +32,6 @@ QDict = NewType('QDict', Dict[str, Any]) | @@ -32,44 +32,6 @@ QDict = NewType('QDict', Dict[str, Any]) | ||
| 32 | class QuestionException(Exception): | 32 | class QuestionException(Exception): |
| 33 | '''Exceptions raised in this module''' | 33 | '''Exceptions raised in this module''' |
| 34 | 34 | ||
| 35 | -# FIXME if this works, use it below | ||
| 36 | -def QuestionFrom(question: dict): | ||
| 37 | - types = { | ||
| 38 | - 'radio': QuestionRadio, | ||
| 39 | - 'checkbox': QuestionCheckbox, | ||
| 40 | - 'text': QuestionText, | ||
| 41 | - 'text-regex': QuestionTextRegex, | ||
| 42 | - 'numeric-interval': QuestionNumericInterval, | ||
| 43 | - 'textarea': QuestionTextArea, | ||
| 44 | - # 'code': QuestionCode, | ||
| 45 | - # -- informative panels -- | ||
| 46 | - 'information': QuestionInformation, | ||
| 47 | - 'success': QuestionInformation, | ||
| 48 | - 'warning': QuestionInformation, | ||
| 49 | - 'alert': QuestionInformation, | ||
| 50 | - } | ||
| 51 | - | ||
| 52 | - # Get class for this question type | ||
| 53 | - try: | ||
| 54 | - qclass = types[question['type']] | ||
| 55 | - except KeyError: | ||
| 56 | - logger.error('Invalid type "%s" in "%s"', | ||
| 57 | - question['type'], question['ref']) | ||
| 58 | - raise | ||
| 59 | - | ||
| 60 | - # Finally create an instance of Question() | ||
| 61 | - try: | ||
| 62 | - qinstance = qclass(QDict(question)) | ||
| 63 | - except QuestionException: | ||
| 64 | - logger.error('Error generating question "%s". See "%s/%s"', | ||
| 65 | - question['ref'], | ||
| 66 | - question['path'], | ||
| 67 | - question['filename']) | ||
| 68 | - raise | ||
| 69 | - | ||
| 70 | - return qinstance | ||
| 71 | - | ||
| 72 | - | ||
| 73 | 35 | ||
| 74 | # ============================================================================ | 36 | # ============================================================================ |
| 75 | # Questions derived from Question are already instantiated and ready to be | 37 | # Questions derived from Question are already instantiated and ready to be |
| @@ -769,6 +731,48 @@ class QuestionInformation(Question): | @@ -769,6 +731,48 @@ class QuestionInformation(Question): | ||
| 769 | super().correct() | 731 | super().correct() |
| 770 | self['grade'] = 1.0 # always "correct" but points should be zero! | 732 | self['grade'] = 1.0 # always "correct" but points should be zero! |
| 771 | 733 | ||
| 734 | + | ||
| 735 | + | ||
| 736 | + | ||
| 737 | +# ============================================================================ | ||
| 738 | +def question_from(qdict: dict): | ||
| 739 | + ''' | ||
| 740 | + Converts a question specified in a dict into an instance of Question() | ||
| 741 | + ''' | ||
| 742 | + types = { | ||
| 743 | + 'radio': QuestionRadio, | ||
| 744 | + 'checkbox': QuestionCheckbox, | ||
| 745 | + 'text': QuestionText, | ||
| 746 | + 'text-regex': QuestionTextRegex, | ||
| 747 | + 'numeric-interval': QuestionNumericInterval, | ||
| 748 | + 'textarea': QuestionTextArea, | ||
| 749 | + # 'code': QuestionCode, | ||
| 750 | + # -- informative panels -- | ||
| 751 | + 'information': QuestionInformation, | ||
| 752 | + 'success': QuestionInformation, | ||
| 753 | + 'warning': QuestionInformation, | ||
| 754 | + 'alert': QuestionInformation, | ||
| 755 | + } | ||
| 756 | + | ||
| 757 | + # Get class for this question type | ||
| 758 | + try: | ||
| 759 | + qclass = types[qdict['type']] | ||
| 760 | + except KeyError: | ||
| 761 | + logger.error('Invalid type "%s" in "%s"', | ||
| 762 | + qdict['type'], qdict['ref']) | ||
| 763 | + raise | ||
| 764 | + | ||
| 765 | + # Create an instance of Question() of appropriate type | ||
| 766 | + try: | ||
| 767 | + qinstance = qclass(QDict(qdict)) | ||
| 768 | + except QuestionException: | ||
| 769 | + logger.error('Error generating "%s" in %s/%s', | ||
| 770 | + qdict['ref'], qdict['path'], qdict['filename']) | ||
| 771 | + raise | ||
| 772 | + | ||
| 773 | + return qinstance | ||
| 774 | + | ||
| 775 | + | ||
| 772 | # ============================================================================ | 776 | # ============================================================================ |
| 773 | class QFactory(): | 777 | class QFactory(): |
| 774 | ''' | 778 | ''' |
| @@ -802,25 +806,8 @@ class QFactory(): | @@ -802,25 +806,8 @@ class QFactory(): | ||
| 802 | grade = question['grade'] # get grade | 806 | grade = question['grade'] # get grade |
| 803 | ''' | 807 | ''' |
| 804 | 808 | ||
| 805 | - # Depending on the type of question, a different question class will be | ||
| 806 | - # instantiated. All these classes derive from the base class `Question`. | ||
| 807 | - _types = { | ||
| 808 | - 'radio': QuestionRadio, | ||
| 809 | - 'checkbox': QuestionCheckbox, | ||
| 810 | - 'text': QuestionText, | ||
| 811 | - 'text-regex': QuestionTextRegex, | ||
| 812 | - 'numeric-interval': QuestionNumericInterval, | ||
| 813 | - 'textarea': QuestionTextArea, | ||
| 814 | - # 'code': QuestionCode, | ||
| 815 | - # -- informative panels -- | ||
| 816 | - 'information': QuestionInformation, | ||
| 817 | - 'success': QuestionInformation, | ||
| 818 | - 'warning': QuestionInformation, | ||
| 819 | - 'alert': QuestionInformation, | ||
| 820 | - } | ||
| 821 | - | ||
| 822 | def __init__(self, qdict: QDict = QDict({})) -> None: | 809 | def __init__(self, qdict: QDict = QDict({})) -> None: |
| 823 | - self.question = qdict | 810 | + self.qdict = qdict |
| 824 | 811 | ||
| 825 | # ------------------------------------------------------------------------ | 812 | # ------------------------------------------------------------------------ |
| 826 | async def gen_async(self) -> Question: | 813 | async def gen_async(self) -> Question: |
| @@ -829,44 +816,27 @@ class QFactory(): | @@ -829,44 +816,27 @@ class QFactory(): | ||
| 829 | which is a descendent of base class Question. | 816 | which is a descendent of base class Question. |
| 830 | ''' | 817 | ''' |
| 831 | 818 | ||
| 832 | - logger.debug('generating %s...', self.question["ref"]) | 819 | + logger.debug('generating %s...', self.qdict["ref"]) |
| 833 | # Shallow copy so that script generated questions will not replace | 820 | # Shallow copy so that script generated questions will not replace |
| 834 | # the original generators | 821 | # the original generators |
| 835 | - question = self.question.copy() | ||
| 836 | - question['qid'] = str(uuid.uuid4()) # unique for each question | 822 | + qdict = self.qdict.copy() |
| 823 | + qdict['qid'] = str(uuid.uuid4()) # unique for each question | ||
| 837 | 824 | ||
| 838 | # If question is of generator type, an external program will be run | 825 | # If question is of generator type, an external program will be run |
| 839 | # which will print a valid question in yaml format to stdout. This | 826 | # which will print a valid question in yaml format to stdout. This |
| 840 | # output is then yaml parsed into a dictionary `q`. | 827 | # output is then yaml parsed into a dictionary `q`. |
| 841 | - if question['type'] == 'generator': | ||
| 842 | - logger.debug(' \\_ Running "%s".', question['script']) | ||
| 843 | - question.setdefault('args', []) | ||
| 844 | - question.setdefault('stdin', '') | ||
| 845 | - script = path.join(question['path'], question['script']) | 828 | + if qdict['type'] == 'generator': |
| 829 | + logger.debug(' \\_ Running "%s".', qdict['script']) | ||
| 830 | + qdict.setdefault('args', []) | ||
| 831 | + qdict.setdefault('stdin', '') | ||
| 832 | + script = path.join(qdict['path'], qdict['script']) | ||
| 846 | out = await run_script_async(script=script, | 833 | out = await run_script_async(script=script, |
| 847 | - args=question['args'], | ||
| 848 | - stdin=question['stdin']) | ||
| 849 | - question.update(out) | ||
| 850 | - | ||
| 851 | - # Get class for this question type | ||
| 852 | - try: | ||
| 853 | - qclass = self._types[question['type']] | ||
| 854 | - except KeyError: | ||
| 855 | - logger.error('Invalid type "%s" in "%s"', | ||
| 856 | - question['type'], question['ref']) | ||
| 857 | - raise | 834 | + args=qdict['args'], |
| 835 | + stdin=qdict['stdin']) | ||
| 836 | + qdict.update(out) | ||
| 858 | 837 | ||
| 859 | - # Finally create an instance of Question() | ||
| 860 | - try: | ||
| 861 | - qinstance = qclass(QDict(question)) | ||
| 862 | - except QuestionException: | ||
| 863 | - logger.error('Error generating question "%s". See "%s/%s"', | ||
| 864 | - question['ref'], | ||
| 865 | - question['path'], | ||
| 866 | - question['filename']) | ||
| 867 | - raise | ||
| 868 | - | ||
| 869 | - return qinstance | 838 | + question = question_from(qdict) # returns a Question instance |
| 839 | + return question | ||
| 870 | 840 | ||
| 871 | # ------------------------------------------------------------------------ | 841 | # ------------------------------------------------------------------------ |
| 872 | def generate(self) -> Question: | 842 | def generate(self) -> Question: |