@@ -16,16 +16,20 @@ class Question:
1616
1717 Examples:
1818 >>> from in2lambda.api.question import Question
19- >>> Question(title="Some title", _main_text ="Some text")
20- Question(title='Some title', parts=[], images=[], _main_text ='Some text')
19+ >>> Question(title="Some title", main_text ="Some text")
20+ Question(title='Some title', parts=[], images=[], main_text ='Some text')
2121 """
2222
2323 title : str = ""
2424
2525 parts : list [Part ] = field (default_factory = list )
2626 images : list [str ] = field (default_factory = list )
2727
28- _main_text : str = ""
28+ # Use getter/setter methods for main_text without exposing private attribute.
29+ # See https://stackoverflow.com/a/61480946
30+ main_text : str = ""
31+ _main_text : str = field (init = False , repr = False , default = "" )
32+
2933 _last_part : dict [str , int ] = field (
3034 default_factory = lambda : {"solution" : 0 , "text" : 0 }, repr = False
3135 )
@@ -34,15 +38,10 @@ class Question:
3438
3539 @property
3640 def main_text (self ) -> str :
37- """Main top-level question text."""
38- return self ._main_text
41+ r"""Main top-level question text.
3942
40- @main_text .setter
41- def main_text (self , value : Union [pf .Element , str ]) -> None :
42- r"""Appends to the top-level main text, which starts off as an empty string.
43-
44- Args:
45- value: A panflute element or string denoting what to append to the main text.
43+ Setting the attribute multiple times appends to the current value with a newline.
44+ This allows question text to be dynamically appended.
4645
4746 Examples:
4847 >>> from in2lambda.api.question import Question
@@ -52,7 +51,28 @@ def main_text(self, value: Union[pf.Element, str]) -> None:
5251 >>> question.main_text
5352 'hello\nthere'
5453 """
55- text_value = value if isinstance (value , str ) else pf .stringify (value , False )
54+ return self ._main_text
55+
56+ @main_text .setter
57+ def main_text (self , value : Union [pf .Element , str , property ]) -> None :
58+ r"""Appends to the top-level main text, which starts off as an empty string.
59+
60+ Args:
61+ value: A panflute element or string denoting what to append to the main text.
62+
63+ See example in main_text property.
64+ """
65+ # Converts the inputted value into a string, stored in text_value
66+ match value :
67+ case str ():
68+ text_value = value
69+ case property ():
70+ # Use default value when no value set at initialisation.
71+ # See https://stackoverflow.com/a/61480946
72+ text_value = self .main_text
73+ case pf .Element ():
74+ text_value = pf .stringify (value , False )
75+
5676 if self ._main_text :
5777 self ._main_text += "\n "
5878 self ._main_text += text_value
@@ -69,20 +89,20 @@ def add_solution(self, elem: Union[pf.Element, str]) -> None:
6989 >>> question.add_part_text("part a")
7090 >>> question.add_solution("part a solution")
7191 >>> question
72- Question(title='', parts=[Part(text='part a', worked_solution='part a solution')], images=[], _main_text ='')
92+ Question(title='', parts=[Part(text='part a', worked_solution='part a solution')], images=[], main_text ='')
7393 >>> question.add_part_text("part b")
7494 >>> question.add_part_text("part c")
7595 >>> question.add_solution("Solution for b")
7696 >>> # Note that since c doesn't have a solution, it's set to b's solution
7797 >>> question
7898 Question(title='', parts=[Part(text='part a', worked_solution='part a solution'), \
7999 Part(text='part b', worked_solution='Solution for b'), \
80- Part(text='part c', worked_solution='Solution for b')], images=[], _main_text ='')
100+ Part(text='part c', worked_solution='Solution for b')], images=[], main_text ='')
81101 >>> question.add_solution("We now have a solution for c!")
82102 >>> question
83103 Question(title='', parts=[Part(text='part a', worked_solution='part a solution'), \
84104 Part(text='part b', worked_solution='Solution for b'), \
85- Part(text='part c', worked_solution='We now have a solution for c!')], images=[], _main_text ='')
105+ Part(text='part c', worked_solution='We now have a solution for c!')], images=[], main_text ='')
86106 """
87107 elem_text = elem if isinstance (elem , str ) else pf .stringify (elem )
88108
@@ -111,13 +131,13 @@ def add_part_text(self, elem: Union[pf.Element, str]) -> None:
111131 >>> question.add_part_text("part a")
112132 >>> question.add_solution("part a solution")
113133 >>> question
114- Question(title='', parts=[Part(text='part a', worked_solution='part a solution')], images=[], _main_text ='')
134+ Question(title='', parts=[Part(text='part a', worked_solution='part a solution')], images=[], main_text ='')
115135 >>> # Supports adding the answer first.
116136 >>> question.add_solution("part b solution")
117137 >>> question.add_part_text("part b")
118138 >>> question
119139 Question(title='', parts=[Part(text='part a', worked_solution='part a solution'), \
120- Part(text='part b', worked_solution='part b solution')], images=[], _main_text ='')
140+ Part(text='part b', worked_solution='part b solution')], images=[], main_text ='')
121141 """
122142 elem_text = elem if isinstance (elem , str ) else pf .stringify (elem )
123143
0 commit comments