Total Complexity | 38 |
Total Lines | 326 |
Duplicated Lines | 0 % |
1 | """ |
||
13 | class Node: |
||
|
|||
14 | """ |
||
15 | Abstract class for SDoc2 nodes. |
||
16 | """ |
||
17 | |||
18 | # ------------------------------------------------------------------------------------------------------------------ |
||
19 | def __init__(self, name, options=None, argument=''): |
||
20 | """ |
||
21 | Object constructor. |
||
22 | |||
23 | :param str name: The (command) name of this node. |
||
24 | :param dict[str,str] options: The options of this node. |
||
25 | :param str argument: The argument of this node (inline commands only). |
||
26 | """ |
||
27 | self.id = 0 |
||
28 | """ |
||
29 | The ID of this SDoc2 node. |
||
30 | |||
31 | :type: int |
||
32 | """ |
||
33 | |||
34 | self.name = name |
||
35 | """ |
||
36 | The (command) name of this node. |
||
37 | |||
38 | :type: str |
||
39 | """ |
||
40 | |||
41 | self._argument = argument |
||
42 | """ |
||
43 | The argument of this node (inline commands only). |
||
44 | |||
45 | :type: str |
||
46 | """ |
||
47 | |||
48 | self._options = options if options else {} |
||
49 | """ |
||
50 | The options of this node. |
||
51 | |||
52 | :type: dict[str,int|str] |
||
53 | """ |
||
54 | |||
55 | self.child_nodes = [] |
||
56 | """ |
||
57 | The ID's of the SDoc2 child nodes of this SDoc2 node. |
||
58 | |||
59 | :type: list[int] |
||
60 | """ |
||
61 | |||
62 | self.position = None |
||
63 | """ |
||
64 | The position where this node is defined. |
||
65 | |||
66 | :type: None|sdoc.sdoc2.Position.Position |
||
67 | """ |
||
68 | |||
69 | self.labels = [] |
||
70 | """ |
||
71 | The list of labels in the node. |
||
72 | |||
73 | :type: |
||
74 | """ |
||
75 | |||
76 | # ------------------------------------------------------------------------------------------------------------------ |
||
77 | @property |
||
78 | def argument(self): |
||
79 | """ |
||
80 | Getter for argument. |
||
81 | |||
82 | :rtype: str |
||
83 | """ |
||
84 | return self._argument |
||
85 | |||
86 | # ------------------------------------------------------------------------------------------------------------------ |
||
87 | @argument.setter |
||
88 | def argument(self, new_argument): |
||
89 | """ |
||
90 | Setter for argument. |
||
91 | |||
92 | :param str new_argument: The new argument. |
||
93 | """ |
||
94 | self._argument = new_argument |
||
95 | |||
96 | # ------------------------------------------------------------------------------------------------------------------ |
||
97 | def print_info(self, level): |
||
98 | """ |
||
99 | Temp function for development. |
||
100 | |||
101 | :param int level: the level of block commands. |
||
102 | """ |
||
103 | print("{0!s}{1:4d} {2!s}".format(' ' * 4 * level, self.id, self.name)) |
||
104 | for node_id in self.child_nodes: |
||
105 | node = in_scope(node_id) |
||
106 | |||
107 | node.print_info(level + 1) |
||
108 | |||
109 | out_scope(node) |
||
110 | |||
111 | # ------------------------------------------------------------------------------------------------------------------ |
||
112 | def get_hierarchy_name(self): |
||
1 ignored issue
–
show
|
|||
113 | """ |
||
114 | Returns the hierarchy name if this node is a part of a hierarchy. Otherwise returns False. |
||
115 | |||
116 | :rtype: str|bool |
||
117 | """ |
||
118 | return False |
||
119 | |||
120 | # ------------------------------------------------------------------------------------------------------------------ |
||
121 | @abc.abstractmethod |
||
122 | def get_command(self): |
||
123 | """ |
||
124 | Returns command of this node. |
||
125 | |||
126 | :rtype: str |
||
127 | """ |
||
128 | raise NotImplementedError() |
||
129 | |||
130 | # ------------------------------------------------------------------------------------------------------------------ |
||
131 | def get_hierarchy_level(self, parent_hierarchy_level=-1): |
||
2 ignored issues
–
show
|
|||
132 | """ |
||
133 | Returns the hierarchy level if this node is a part of a hierarchy. |
||
134 | |||
135 | :param int parent_hierarchy_level: The hierarchy level of the parent node in the same hierarchy. |
||
136 | |||
137 | :rtype: int |
||
138 | """ |
||
139 | raise RuntimeError("This method MUST only be called when a node is a part of an hierarchy.") |
||
140 | |||
141 | # ------------------------------------------------------------------------------------------------------------------ |
||
142 | def get_option_value(self, option_name): |
||
143 | """ |
||
144 | Returns the value of an option. Returns None if the option is not set. |
||
145 | |||
146 | :param str option_name: The name of the option. |
||
147 | |||
148 | :rtype: str |
||
149 | """ |
||
150 | return self._options[option_name] if option_name in self._options else None |
||
151 | |||
152 | # ------------------------------------------------------------------------------------------------------------------ |
||
153 | def set_option_value(self, option, value): |
||
154 | """ |
||
155 | Sets value for option. |
||
156 | |||
157 | :param str option: The name of an option |
||
158 | :param mixed value: The value of an option |
||
159 | """ |
||
160 | self._options[option] = value |
||
161 | |||
162 | # ------------------------------------------------------------------------------------------------------------------ |
||
163 | @abc.abstractmethod |
||
164 | def is_block_command(self): |
||
165 | """ |
||
166 | Returns True if this node is created by a block command. Otherwise returns False. |
||
167 | |||
168 | :rtype: bool |
||
169 | """ |
||
170 | raise NotImplementedError() |
||
171 | |||
172 | # ------------------------------------------------------------------------------------------------------------------ |
||
173 | def is_document_root(self): |
||
1 ignored issue
–
show
|
|||
174 | """ |
||
175 | Returns True if this node is a document root node. Otherwise returns False. |
||
176 | |||
177 | :rtype: bool |
||
178 | """ |
||
179 | return False |
||
180 | |||
181 | # ------------------------------------------------------------------------------------------------------------------ |
||
182 | def is_hierarchy_root(self): |
||
1 ignored issue
–
show
|
|||
183 | """ |
||
184 | Returns True if this node can be the root of a hierarchy. Otherwise returns False. |
||
185 | |||
186 | :rtype: bool |
||
187 | """ |
||
188 | return False |
||
189 | |||
190 | # ------------------------------------------------------------------------------------------------------------------ |
||
191 | @abc.abstractmethod |
||
192 | def is_inline_command(self): |
||
193 | """ |
||
194 | Returns True if this node is created by a inline command. Otherwise returns False. |
||
195 | |||
196 | :rtype: bool |
||
197 | """ |
||
198 | raise NotImplementedError() |
||
199 | |||
200 | # ------------------------------------------------------------------------------------------------------------------ |
||
201 | def is_phrasing(self): |
||
1 ignored issue
–
show
|
|||
202 | """ |
||
203 | Returns True if this node is a phrasing node, i.e. is a part of a paragraph. Otherwise returns False. |
||
204 | |||
205 | :rtype: bool |
||
206 | """ |
||
207 | return False |
||
208 | |||
209 | # ------------------------------------------------------------------------------------------------------------------ |
||
210 | def is_list_element(self): |
||
1 ignored issue
–
show
|
|||
211 | """ |
||
212 | Returns True if this node is a list element, e.g. an item in itemize. Otherwise returns False. |
||
213 | |||
214 | :rtype: bool |
||
215 | """ |
||
216 | return False |
||
217 | |||
218 | # ------------------------------------------------------------------------------------------------------------------ |
||
219 | def append_child_node(self, child_node): |
||
220 | """ |
||
221 | Appends a child node to the list of child nodes of the node. |
||
222 | |||
223 | :param sdoc.sdoc2.node.Node.Node child_node: The new child node |
||
224 | """ |
||
225 | self.child_nodes.append(child_node.id) |
||
226 | |||
227 | # ------------------------------------------------------------------------------------------------------------------ |
||
228 | def prepare_content_tree(self): |
||
229 | """ |
||
230 | Prepares this node for further processing. |
||
231 | """ |
||
232 | for node_id in self.child_nodes: |
||
233 | node = in_scope(node_id) |
||
234 | |||
235 | node.prepare_content_tree() |
||
236 | |||
237 | out_scope(node) |
||
238 | |||
239 | # ------------------------------------------------------------------------------------------------------------------ |
||
240 | def number(self, numbers): |
||
241 | """ |
||
242 | Numbers all numerable nodes such as chapters, sections, figures, and, items. |
||
243 | |||
244 | :param numbers: The current numbers. |
||
245 | """ |
||
246 | for node_id in self.child_nodes: |
||
247 | node = in_scope(node_id) |
||
248 | |||
249 | node.number(numbers) |
||
250 | |||
251 | out_scope(node) |
||
252 | |||
253 | # ------------------------------------------------------------------------------------------------------------------ |
||
254 | def get_enumerated_items(self): |
||
255 | """ |
||
256 | Returns a list with a tuple with command and number of enumerated child nodes. |
||
257 | |||
258 | Thi method is intended for unit test only. |
||
259 | |||
260 | :rtype: list[(str,str)] |
||
261 | """ |
||
262 | items = list() |
||
263 | |||
264 | # First append the enumeration of this node (if any). |
||
265 | if 'number' in self._options: |
||
266 | items.append((self.get_command(), self._options['number'], self._argument)) |
||
267 | |||
268 | # Second append the enumeration of child nodes (if any). |
||
269 | for node_id in self.child_nodes: |
||
270 | node = in_scope(node_id) |
||
271 | |||
272 | tmp = node.get_enumerated_items() |
||
273 | if tmp: |
||
274 | items.append(tmp) |
||
275 | |||
276 | out_scope(node) |
||
277 | |||
278 | return items |
||
279 | |||
280 | # ------------------------------------------------------------------------------------------------------------------ |
||
281 | def parse_labels(self): |
||
282 | """ |
||
283 | Parses all labels and call methods to collect labels.and for |
||
284 | """ |
||
285 | self.modify_label_list() |
||
286 | |||
287 | if self.labels: |
||
288 | self.set_id_heading_node() |
||
289 | |||
290 | # ------------------------------------------------------------------------------------------------------------------ |
||
291 | def modify_label_list(self): |
||
292 | """ |
||
293 | Creates label list for each heading node, and for node_store. Removes label nodes from child list. |
||
294 | """ |
||
295 | for node_id in self.child_nodes: |
||
296 | node = in_scope(node_id) |
||
297 | |||
298 | if node.get_command() == 'label': |
||
299 | # Appending in Node labels list. |
||
300 | self.labels.append(node.id) |
||
301 | |||
302 | # Appending in NodeStore labels list. |
||
303 | if node.argument not in node_store.labels: |
||
304 | node_store.labels[node.argument] = self.argument |
||
305 | else: |
||
306 | raise NameError('Duplicate label', node.argument) |
||
307 | |||
308 | # Removing node from child nodes. |
||
309 | self.child_nodes.remove(node.id) |
||
310 | |||
311 | node.parse_labels() |
||
312 | |||
313 | out_scope(node) |
||
314 | |||
315 | # ------------------------------------------------------------------------------------------------------------------ |
||
316 | def set_id_heading_node(self): |
||
317 | """ |
||
318 | Sets id to heading node. (Argument of first label) |
||
319 | """ |
||
320 | node = in_scope(self.labels[0]) |
||
321 | self._options['id'] = node.argument |
||
322 | out_scope(node) |
||
323 | |||
324 | # ------------------------------------------------------------------------------------------------------------------ |
||
325 | def change_ref_argument(self): |
||
326 | """ |
||
327 | Changes reference argument on number of depending heading node. |
||
328 | """ |
||
329 | for node_id in self.child_nodes: |
||
330 | node = in_scope(node_id) |
||
331 | |||
332 | if node.argument in node_store.labels and node.get_command() == 'ref': |
||
333 | node.set_option_value('href', '#{0}'.format(node.argument)) |
||
334 | node.argument = node_store.labels[node.argument] |
||
335 | |||
336 | node.change_ref_argument() |
||
337 | |||
338 | out_scope(node) |
||
339 | |||
341 |