Commit 9f9c3fafd7f8bbafd569b126a81969f241f5643b

Authored by Miguel Barão
1 parent 93c4dec9
Exists in master and in 1 other branch dev

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: