@@ -16,16 +16,20 @@ class Question:
16
16
17
17
Examples:
18
18
>>> 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')
21
21
"""
22
22
23
23
title : str = ""
24
24
25
25
parts : list [Part ] = field (default_factory = list )
26
26
images : list [str ] = field (default_factory = list )
27
27
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
+
29
33
_last_part : dict [str , int ] = field (
30
34
default_factory = lambda : {"solution" : 0 , "text" : 0 }, repr = False
31
35
)
@@ -34,15 +38,10 @@ class Question:
34
38
35
39
@property
36
40
def main_text (self ) -> str :
37
- """Main top-level question text."""
38
- return self ._main_text
41
+ r"""Main top-level question text.
39
42
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.
46
45
47
46
Examples:
48
47
>>> from in2lambda.api.question import Question
@@ -52,7 +51,28 @@ def main_text(self, value: Union[pf.Element, str]) -> None:
52
51
>>> question.main_text
53
52
'hello\nthere'
54
53
"""
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
+
56
76
if self ._main_text :
57
77
self ._main_text += "\n "
58
78
self ._main_text += text_value
@@ -69,20 +89,20 @@ def add_solution(self, elem: Union[pf.Element, str]) -> None:
69
89
>>> question.add_part_text("part a")
70
90
>>> question.add_solution("part a solution")
71
91
>>> 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 ='')
73
93
>>> question.add_part_text("part b")
74
94
>>> question.add_part_text("part c")
75
95
>>> question.add_solution("Solution for b")
76
96
>>> # Note that since c doesn't have a solution, it's set to b's solution
77
97
>>> question
78
98
Question(title='', parts=[Part(text='part a', worked_solution='part a solution'), \
79
99
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 ='')
81
101
>>> question.add_solution("We now have a solution for c!")
82
102
>>> question
83
103
Question(title='', parts=[Part(text='part a', worked_solution='part a solution'), \
84
104
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 ='')
86
106
"""
87
107
elem_text = elem if isinstance (elem , str ) else pf .stringify (elem )
88
108
@@ -111,13 +131,13 @@ def add_part_text(self, elem: Union[pf.Element, str]) -> None:
111
131
>>> question.add_part_text("part a")
112
132
>>> question.add_solution("part a solution")
113
133
>>> 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 ='')
115
135
>>> # Supports adding the answer first.
116
136
>>> question.add_solution("part b solution")
117
137
>>> question.add_part_text("part b")
118
138
>>> question
119
139
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 ='')
121
141
"""
122
142
elem_text = elem if isinstance (elem , str ) else pf .stringify (elem )
123
143
0 commit comments