|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2003 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the builtin documentation generator. |
|
8 |
|
9 The different parts of the module document are assembled from the parsed |
|
10 Python file. The appearance is determined by several templates defined within |
|
11 this module. |
|
12 """ |
|
13 |
|
14 from __future__ import unicode_literals |
|
15 |
|
16 import sys |
|
17 import re |
|
18 |
|
19 from Utilities import html_uencode |
|
20 from Utilities.ModuleParser import RB_SOURCE, Function |
|
21 |
|
22 _signal = re.compile( |
|
23 r""" |
|
24 ^@signal [ \t]+ |
|
25 (?P<SignalName1> |
|
26 [a-zA-Z_] \w* [ \t]* \( [^)]* \) |
|
27 ) |
|
28 [ \t]* (?P<SignalDescription1> .*) |
|
29 | |
|
30 ^@signal [ \t]+ |
|
31 (?P<SignalName2> |
|
32 [a-zA-Z_] \w* |
|
33 ) |
|
34 [ \t]+ (?P<SignalDescription2> .*) |
|
35 """, re.VERBOSE | re.DOTALL | re.MULTILINE).search |
|
36 |
|
37 _event = re.compile( |
|
38 r""" |
|
39 ^@event [ \t]+ |
|
40 (?P<EventName1> |
|
41 [a-zA-Z_] \w* [ \t]* \( [^)]* \) |
|
42 ) |
|
43 [ \t]* (?P<EventDescription1> .*) |
|
44 | |
|
45 ^@event [ \t]+ |
|
46 (?P<EventName2> |
|
47 [a-zA-Z_] \w* |
|
48 ) |
|
49 [ \t]+ (?P<EventDescription2> .*) |
|
50 """, re.VERBOSE | re.DOTALL | re.MULTILINE).search |
|
51 |
|
52 |
|
53 class TagError(Exception): |
|
54 """ |
|
55 Exception class raised, if an invalid documentation tag was found. |
|
56 """ |
|
57 pass |
|
58 |
|
59 |
|
60 class ModuleDocument(object): |
|
61 """ |
|
62 Class implementing the builtin documentation generator. |
|
63 """ |
|
64 def __init__(self, module, colors, stylesheet=None): |
|
65 """ |
|
66 Constructor |
|
67 |
|
68 @param module the information of the parsed Python file |
|
69 @param colors dictionary specifying the various colors for the output |
|
70 (dictionary of strings) |
|
71 @param stylesheet the style to be used for the generated pages (string) |
|
72 """ |
|
73 self.module = module |
|
74 self.empty = True |
|
75 |
|
76 self.stylesheet = stylesheet |
|
77 |
|
78 if self.stylesheet: |
|
79 from . import TemplatesListsStyleCSS |
|
80 self.headerTemplate = TemplatesListsStyleCSS.headerTemplate |
|
81 self.footerTemplate = TemplatesListsStyleCSS.footerTemplate |
|
82 self.moduleTemplate = TemplatesListsStyleCSS.moduleTemplate |
|
83 self.rbFileTemplate = TemplatesListsStyleCSS.rbFileTemplate |
|
84 self.classTemplate = TemplatesListsStyleCSS.classTemplate |
|
85 self.methodTemplate = TemplatesListsStyleCSS.methodTemplate |
|
86 self.constructorTemplate = \ |
|
87 TemplatesListsStyleCSS.constructorTemplate |
|
88 self.rbModuleTemplate = TemplatesListsStyleCSS.rbModuleTemplate |
|
89 self.rbModulesClassTemplate = \ |
|
90 TemplatesListsStyleCSS.rbModulesClassTemplate |
|
91 self.functionTemplate = TemplatesListsStyleCSS.functionTemplate |
|
92 self.listTemplate = TemplatesListsStyleCSS.listTemplate |
|
93 self.listEntryTemplate = TemplatesListsStyleCSS.listEntryTemplate |
|
94 self.listEntryNoneTemplate = \ |
|
95 TemplatesListsStyleCSS.listEntryNoneTemplate |
|
96 self.listEntryDeprecatedTemplate = \ |
|
97 TemplatesListsStyleCSS.listEntryDeprecatedTemplate |
|
98 self.listEntrySimpleTemplate = \ |
|
99 TemplatesListsStyleCSS.listEntrySimpleTemplate |
|
100 self.paragraphTemplate = TemplatesListsStyleCSS.paragraphTemplate |
|
101 self.parametersListTemplate = \ |
|
102 TemplatesListsStyleCSS.parametersListTemplate |
|
103 self.parameterTypesListEntryTemplate = \ |
|
104 TemplatesListsStyleCSS.parameterTypesListEntryTemplate |
|
105 self.parametersListEntryTemplate = \ |
|
106 TemplatesListsStyleCSS.parametersListEntryTemplate |
|
107 self.returnsTemplate = TemplatesListsStyleCSS.returnsTemplate |
|
108 self.returnTypesTemplate = \ |
|
109 TemplatesListsStyleCSS.returnTypesTemplate |
|
110 self.exceptionsListTemplate = \ |
|
111 TemplatesListsStyleCSS.exceptionsListTemplate |
|
112 self.exceptionsListEntryTemplate = \ |
|
113 TemplatesListsStyleCSS.exceptionsListEntryTemplate |
|
114 self.signalsListTemplate = \ |
|
115 TemplatesListsStyleCSS.signalsListTemplate |
|
116 self.signalsListEntryTemplate = \ |
|
117 TemplatesListsStyleCSS.signalsListEntryTemplate |
|
118 self.eventsListTemplate = TemplatesListsStyleCSS.eventsListTemplate |
|
119 self.eventsListEntryTemplate = \ |
|
120 TemplatesListsStyleCSS.eventsListEntryTemplate |
|
121 self.deprecatedTemplate = TemplatesListsStyleCSS.deprecatedTemplate |
|
122 self.authorInfoTemplate = TemplatesListsStyleCSS.authorInfoTemplate |
|
123 self.seeListTemplate = TemplatesListsStyleCSS.seeListTemplate |
|
124 self.seeListEntryTemplate = \ |
|
125 TemplatesListsStyleCSS.seeListEntryTemplate |
|
126 self.seeLinkTemplate = TemplatesListsStyleCSS.seeLinkTemplate |
|
127 self.sinceInfoTemplate = TemplatesListsStyleCSS.sinceInfoTemplate |
|
128 else: |
|
129 from . import TemplatesListsStyle |
|
130 self.headerTemplate = \ |
|
131 TemplatesListsStyle.headerTemplate.format(**colors) |
|
132 self.footerTemplate = \ |
|
133 TemplatesListsStyle.footerTemplate.format(**colors) |
|
134 self.moduleTemplate = \ |
|
135 TemplatesListsStyle.moduleTemplate.format(**colors) |
|
136 self.rbFileTemplate = \ |
|
137 TemplatesListsStyle.rbFileTemplate.format(**colors) |
|
138 self.classTemplate = \ |
|
139 TemplatesListsStyle.classTemplate.format(**colors) |
|
140 self.methodTemplate = \ |
|
141 TemplatesListsStyle.methodTemplate.format(**colors) |
|
142 self.constructorTemplate = \ |
|
143 TemplatesListsStyle.constructorTemplate.format(**colors) |
|
144 self.rbModuleTemplate = \ |
|
145 TemplatesListsStyle.rbModuleTemplate.format(**colors) |
|
146 self.rbModulesClassTemplate = \ |
|
147 TemplatesListsStyle.rbModulesClassTemplate.format(**colors) |
|
148 self.functionTemplate = \ |
|
149 TemplatesListsStyle.functionTemplate.format(**colors) |
|
150 self.listTemplate = \ |
|
151 TemplatesListsStyle.listTemplate.format(**colors) |
|
152 self.listEntryTemplate = \ |
|
153 TemplatesListsStyle.listEntryTemplate.format(**colors) |
|
154 self.listEntryNoneTemplate = \ |
|
155 TemplatesListsStyle.listEntryNoneTemplate.format(**colors) |
|
156 self.listEntryDeprecatedTemplate = \ |
|
157 TemplatesListsStyle.listEntryDeprecatedTemplate.format( |
|
158 **colors) |
|
159 self.listEntrySimpleTemplate = \ |
|
160 TemplatesListsStyle.listEntrySimpleTemplate.format(**colors) |
|
161 self.paragraphTemplate = \ |
|
162 TemplatesListsStyle.paragraphTemplate.format(**colors) |
|
163 self.parametersListTemplate = \ |
|
164 TemplatesListsStyle.parametersListTemplate.format(**colors) |
|
165 self.parametersListEntryTemplate = \ |
|
166 TemplatesListsStyle.parametersListEntryTemplate.format( |
|
167 **colors) |
|
168 self.parameterTypesListEntryTemplate = \ |
|
169 TemplatesListsStyle.parameterTypesListEntryTemplate.format( |
|
170 **colors) |
|
171 self.returnsTemplate = \ |
|
172 TemplatesListsStyle.returnsTemplate.format(**colors) |
|
173 self.returnTypesTemplate = \ |
|
174 TemplatesListsStyle.returnTypesTemplate.format(**colors) |
|
175 self.exceptionsListTemplate = \ |
|
176 TemplatesListsStyle.exceptionsListTemplate.format(**colors) |
|
177 self.exceptionsListEntryTemplate = \ |
|
178 TemplatesListsStyle.exceptionsListEntryTemplate.format( |
|
179 **colors) |
|
180 self.signalsListTemplate = \ |
|
181 TemplatesListsStyle.signalsListTemplate.format(**colors) |
|
182 self.signalsListEntryTemplate = \ |
|
183 TemplatesListsStyle.signalsListEntryTemplate.format(**colors) |
|
184 self.eventsListTemplate = \ |
|
185 TemplatesListsStyle.eventsListTemplate.format(**colors) |
|
186 self.eventsListEntryTemplate = \ |
|
187 TemplatesListsStyle.eventsListEntryTemplate.format(**colors) |
|
188 self.deprecatedTemplate = \ |
|
189 TemplatesListsStyle.deprecatedTemplate.format(**colors) |
|
190 self.authorInfoTemplate = \ |
|
191 TemplatesListsStyle.authorInfoTemplate.format(**colors) |
|
192 self.seeListTemplate = \ |
|
193 TemplatesListsStyle.seeListTemplate.format(**colors) |
|
194 self.seeListEntryTemplate = \ |
|
195 TemplatesListsStyle.seeListEntryTemplate.format(**colors) |
|
196 self.seeLinkTemplate = \ |
|
197 TemplatesListsStyle.seeLinkTemplate.format(**colors) |
|
198 self.sinceInfoTemplate = \ |
|
199 TemplatesListsStyle.sinceInfoTemplate.format(**colors) |
|
200 |
|
201 self.keywords = [] |
|
202 # list of tuples containing the name (string) and |
|
203 # the ref (string). The ref is without the filename part. |
|
204 self.generated = False |
|
205 |
|
206 def isEmpty(self): |
|
207 """ |
|
208 Public method to determine, if the module contains any classes or |
|
209 functions. |
|
210 |
|
211 @return Flag indicating an empty module (i.e. __init__.py without |
|
212 any contents) |
|
213 """ |
|
214 return self.empty |
|
215 |
|
216 def name(self): |
|
217 """ |
|
218 Public method used to get the module name. |
|
219 |
|
220 @return The name of the module. (string) |
|
221 """ |
|
222 return self.module.name |
|
223 |
|
224 def description(self): |
|
225 """ |
|
226 Public method used to get the description of the module. |
|
227 |
|
228 @return The description of the module. (string) |
|
229 """ |
|
230 return self.__formatDescription(self.module.description) |
|
231 |
|
232 def shortDescription(self): |
|
233 """ |
|
234 Public method used to get the short description of the module. |
|
235 |
|
236 The short description is just the first line of the modules |
|
237 description. |
|
238 |
|
239 @return The short description of the module. (string) |
|
240 """ |
|
241 return self.__getShortDescription(self.module.description) |
|
242 |
|
243 def genDocument(self): |
|
244 """ |
|
245 Public method to generate the source code documentation. |
|
246 |
|
247 @return The source code documentation. (string) |
|
248 """ |
|
249 doc = self.headerTemplate.format( |
|
250 **{'Title': self.module.name, |
|
251 'Style': self.stylesheet}) + \ |
|
252 self.__genModuleSection() + \ |
|
253 self.footerTemplate |
|
254 self.generated = True |
|
255 return doc |
|
256 |
|
257 def __genModuleSection(self): |
|
258 """ |
|
259 Private method to generate the body of the document. |
|
260 |
|
261 @return The body of the document. (string) |
|
262 """ |
|
263 globalsList = self.__genGlobalsListSection() |
|
264 classList = self.__genClassListSection() |
|
265 functionList = self.__genFunctionListSection() |
|
266 try: |
|
267 if self.module.type == RB_SOURCE: |
|
268 rbModulesList = self.__genRbModulesListSection() |
|
269 modBody = self.rbFileTemplate.format( |
|
270 **{'Module': self.module.name, |
|
271 'ModuleDescription': |
|
272 self.__formatDescription(self.module.description), |
|
273 'GlobalsList': globalsList, |
|
274 'ClassList': classList, |
|
275 'RbModulesList': rbModulesList, |
|
276 'FunctionList': functionList, |
|
277 }) |
|
278 else: |
|
279 modBody = self.moduleTemplate.format( |
|
280 **{'Module': self.module.name, |
|
281 'ModuleDescription': |
|
282 self.__formatDescription(self.module.description), |
|
283 'GlobalsList': globalsList, |
|
284 'ClassList': classList, |
|
285 'FunctionList': functionList, |
|
286 }) |
|
287 except TagError as e: |
|
288 sys.stderr.write( |
|
289 "Error processing {0}.\n".format(self.module.file)) |
|
290 sys.stderr.write( |
|
291 "Error in tags of description of module {0}.\n".format( |
|
292 self.module.name)) |
|
293 sys.stderr.write("{0}\n".format(e)) |
|
294 return "" |
|
295 |
|
296 classesSection = self.__genClassesSection() |
|
297 functionsSection = self.__genFunctionsSection() |
|
298 if self.module.type == RB_SOURCE: |
|
299 rbModulesSection = self.__genRbModulesSection() |
|
300 else: |
|
301 rbModulesSection = "" |
|
302 return "{0}{1}{2}{3}".format( |
|
303 modBody, classesSection, rbModulesSection, functionsSection) |
|
304 |
|
305 def __genListSection(self, names, sectionDict, kwSuffix=""): |
|
306 """ |
|
307 Private method to generate a list section of the document. |
|
308 |
|
309 @param names The names to appear in the list. (list of strings) |
|
310 @param sectionDict dictionary containing all relevant information |
|
311 (dict) |
|
312 @param kwSuffix suffix to be used for the QtHelp keywords (string) |
|
313 @return list section (string) |
|
314 """ |
|
315 lst = [] |
|
316 for name in names: |
|
317 lst.append(self.listEntryTemplate.format( |
|
318 **{'Link': "{0}".format(name), |
|
319 'Name': sectionDict[name].name, |
|
320 'Description': |
|
321 self.__getShortDescription(sectionDict[name].description), |
|
322 'Deprecated': |
|
323 self.__checkDeprecated(sectionDict[name].description) and |
|
324 self.listEntryDeprecatedTemplate or "", |
|
325 })) |
|
326 if kwSuffix: |
|
327 n = "{0} ({1})".format(name, kwSuffix) |
|
328 else: |
|
329 n = "{0}".format(name) |
|
330 self.keywords.append((n, "#{0}".format(name))) |
|
331 return ''.join(lst) |
|
332 |
|
333 def __genGlobalsListSection(self, class_=None): |
|
334 """ |
|
335 Private method to generate the section listing all global attributes of |
|
336 the module. |
|
337 |
|
338 @param class_ reference to a class object (Class) |
|
339 @return The globals list section. (string) |
|
340 """ |
|
341 attrNames = [] |
|
342 if class_ is not None: |
|
343 scope = class_ |
|
344 else: |
|
345 scope = self.module |
|
346 attrNames = sorted(attr for attr in scope.globals.keys() |
|
347 if not scope.globals[attr].isSignal) |
|
348 if attrNames: |
|
349 s = ''.join( |
|
350 [self.listEntrySimpleTemplate.format(**{'Name': name}) |
|
351 for name in attrNames]) |
|
352 else: |
|
353 s = self.listEntryNoneTemplate |
|
354 return self.listTemplate.format(**{'Entries': s}) |
|
355 |
|
356 def __genClassListSection(self): |
|
357 """ |
|
358 Private method to generate the section listing all classes of the |
|
359 module. |
|
360 |
|
361 @return The classes list section. (string) |
|
362 """ |
|
363 names = sorted(list(self.module.classes.keys())) |
|
364 if names: |
|
365 self.empty = False |
|
366 s = self.__genListSection(names, self.module.classes) |
|
367 else: |
|
368 s = self.listEntryNoneTemplate |
|
369 return self.listTemplate.format(**{'Entries': s}) |
|
370 |
|
371 def __genRbModulesListSection(self): |
|
372 """ |
|
373 Private method to generate the section listing all modules of the file |
|
374 (Ruby only). |
|
375 |
|
376 @return The modules list section. (string) |
|
377 """ |
|
378 names = sorted(list(self.module.modules.keys())) |
|
379 if names: |
|
380 self.empty = False |
|
381 s = self.__genListSection(names, self.module.modules) |
|
382 else: |
|
383 s = self.listEntryNoneTemplate |
|
384 return self.listTemplate.format(**{'Entries': s}) |
|
385 |
|
386 def __genFunctionListSection(self): |
|
387 """ |
|
388 Private method to generate the section listing all functions of the |
|
389 module. |
|
390 |
|
391 @return The functions list section. (string) |
|
392 """ |
|
393 names = sorted(list(self.module.functions.keys())) |
|
394 if names: |
|
395 self.empty = False |
|
396 s = self.__genListSection(names, self.module.functions) |
|
397 else: |
|
398 s = self.listEntryNoneTemplate |
|
399 return self.listTemplate.format(**{'Entries': s}) |
|
400 |
|
401 def __genClassesSection(self): |
|
402 """ |
|
403 Private method to generate the document section with details about |
|
404 classes. |
|
405 |
|
406 @return The classes details section. (string) |
|
407 """ |
|
408 classNames = sorted(list(self.module.classes.keys())) |
|
409 classes = [] |
|
410 for className in classNames: |
|
411 _class = self.module.classes[className] |
|
412 supers = _class.super |
|
413 if len(supers) > 0: |
|
414 supers = ', '.join(supers) |
|
415 else: |
|
416 supers = 'None' |
|
417 |
|
418 globalsList = self.__genGlobalsListSection(_class) |
|
419 classMethList, classMethBodies = \ |
|
420 self.__genMethodSection(_class, className, Function.Class) |
|
421 methList, methBodies = \ |
|
422 self.__genMethodSection(_class, className, Function.General) |
|
423 staticMethList, staticMethBodies = \ |
|
424 self.__genMethodSection(_class, className, Function.Static) |
|
425 |
|
426 try: |
|
427 clsBody = self.classTemplate.format( |
|
428 **{'Anchor': className, |
|
429 'Class': _class.name, |
|
430 'ClassSuper': supers, |
|
431 'ClassDescription': |
|
432 self.__formatDescription(_class.description), |
|
433 'GlobalsList': globalsList, |
|
434 'ClassMethodList': classMethList, |
|
435 'MethodList': methList, |
|
436 'StaticMethodList': staticMethList, |
|
437 'MethodDetails': |
|
438 classMethBodies + methBodies + staticMethBodies, |
|
439 }) |
|
440 except TagError as e: |
|
441 sys.stderr.write( |
|
442 "Error processing {0}.\n".format(self.module.file)) |
|
443 sys.stderr.write( |
|
444 "Error in tags of description of class {0}.\n".format( |
|
445 className)) |
|
446 sys.stderr.write("{0}\n".format(e)) |
|
447 clsBody = "" |
|
448 |
|
449 classes.append(clsBody) |
|
450 |
|
451 return ''.join(classes) |
|
452 |
|
453 def __genMethodsListSection(self, names, sectionDict, className, clsName, |
|
454 includeInit=True): |
|
455 """ |
|
456 Private method to generate the methods list section of a class. |
|
457 |
|
458 @param names names to appear in the list (list of strings) |
|
459 @param sectionDict dictionary containing all relevant information |
|
460 (dict) |
|
461 @param className class name containing the names |
|
462 @param clsName visible class name containing the names |
|
463 @param includeInit flag indicating to include the __init__ method |
|
464 (boolean) |
|
465 @return methods list section (string) |
|
466 """ |
|
467 lst = [] |
|
468 if includeInit: |
|
469 try: |
|
470 lst.append(self.listEntryTemplate.format( |
|
471 **{'Link': "{0}.{1}".format(className, '__init__'), |
|
472 'Name': clsName, |
|
473 'Description': self.__getShortDescription( |
|
474 sectionDict['__init__'].description), |
|
475 'Deprecated': self.__checkDeprecated( |
|
476 sectionDict['__init__'].description) and |
|
477 self.listEntryDeprecatedTemplate or "", |
|
478 })) |
|
479 self.keywords.append( |
|
480 ("{0} (Constructor)".format(className), |
|
481 "#{0}.{1}".format(className, '__init__'))) |
|
482 except KeyError: |
|
483 pass |
|
484 |
|
485 for name in names: |
|
486 lst.append(self.listEntryTemplate.format( |
|
487 **{'Link': "{0}.{1}".format(className, name), |
|
488 'Name': sectionDict[name].name, |
|
489 'Description': |
|
490 self.__getShortDescription(sectionDict[name].description), |
|
491 'Deprecated': |
|
492 self.__checkDeprecated(sectionDict[name].description) and |
|
493 self.listEntryDeprecatedTemplate or "", |
|
494 })) |
|
495 self.keywords.append(("{0}.{1}".format(className, name), |
|
496 "#{0}.{1}".format(className, name))) |
|
497 return ''.join(lst) |
|
498 |
|
499 def __genMethodSection(self, obj, className, modifierFilter): |
|
500 """ |
|
501 Private method to generate the method details section. |
|
502 |
|
503 @param obj reference to the object being formatted |
|
504 @param className name of the class containing the method (string) |
|
505 @param modifierFilter filter value designating the method types |
|
506 @return method list and method details section (tuple of two string) |
|
507 """ |
|
508 methList = [] |
|
509 methBodies = [] |
|
510 methods = sorted(k for k in obj.methods.keys() |
|
511 if obj.methods[k].modifier == modifierFilter) |
|
512 if '__init__' in methods: |
|
513 methods.remove('__init__') |
|
514 try: |
|
515 methBody = self.constructorTemplate.format( |
|
516 **{'Anchor': className, |
|
517 'Class': obj.name, |
|
518 'Method': '__init__', |
|
519 'MethodDescription': |
|
520 self.__formatDescription( |
|
521 obj.methods['__init__'].description), |
|
522 'Params': |
|
523 ', '.join(obj.methods['__init__'].parameters[1:]), |
|
524 }) |
|
525 except TagError as e: |
|
526 sys.stderr.write( |
|
527 "Error processing {0}.\n".format(self.module.file)) |
|
528 sys.stderr.write( |
|
529 "Error in tags of description of method {0}.{1}.\n".format( |
|
530 className, '__init__')) |
|
531 sys.stderr.write("{0}\n".format(e)) |
|
532 methBody = "" |
|
533 methBodies.append(methBody) |
|
534 |
|
535 if modifierFilter == Function.Class: |
|
536 methodClassifier = " (class method)" |
|
537 elif modifierFilter == Function.Static: |
|
538 methodClassifier = " (static)" |
|
539 else: |
|
540 methodClassifier = "" |
|
541 for method in methods: |
|
542 try: |
|
543 methBody = self.methodTemplate.format( |
|
544 **{'Anchor': className, |
|
545 'Class': obj.name, |
|
546 'Method': obj.methods[method].name, |
|
547 'MethodClassifier': methodClassifier, |
|
548 'MethodDescription': |
|
549 self.__formatDescription( |
|
550 obj.methods[method].description), |
|
551 'Params': ', '.join(obj.methods[method].parameters[1:]), |
|
552 }) |
|
553 except TagError as e: |
|
554 sys.stderr.write( |
|
555 "Error processing {0}.\n".format(self.module.file)) |
|
556 sys.stderr.write( |
|
557 "Error in tags of description of method {0}.{1}.\n".format( |
|
558 className, method)) |
|
559 sys.stderr.write("{0}\n".format(e)) |
|
560 methBody = "" |
|
561 methBodies.append(methBody) |
|
562 |
|
563 methList = self.__genMethodsListSection( |
|
564 methods, obj.methods, className, obj.name, |
|
565 includeInit=modifierFilter == Function.General) |
|
566 |
|
567 if not methList: |
|
568 methList = self.listEntryNoneTemplate |
|
569 return (self.listTemplate.format(**{'Entries': methList}), |
|
570 ''.join(methBodies)) |
|
571 |
|
572 def __genRbModulesSection(self): |
|
573 """ |
|
574 Private method to generate the document section with details about |
|
575 Ruby modules. |
|
576 |
|
577 @return The Ruby modules details section. (string) |
|
578 """ |
|
579 rbModulesNames = sorted(list(self.module.modules.keys())) |
|
580 rbModules = [] |
|
581 for rbModuleName in rbModulesNames: |
|
582 rbModule = self.module.modules[rbModuleName] |
|
583 globalsList = self.__genGlobalsListSection(rbModule) |
|
584 methList, methBodies = self.__genMethodSection( |
|
585 rbModule, rbModuleName, Function.General) |
|
586 classList, classBodies = self.__genRbModulesClassesSection( |
|
587 rbModule, rbModuleName) |
|
588 |
|
589 try: |
|
590 rbmBody = self.rbModuleTemplate.format( |
|
591 **{'Anchor': rbModuleName, |
|
592 'Module': rbModule.name, |
|
593 'ModuleDescription': |
|
594 self.__formatDescription(rbModule.description), |
|
595 'GlobalsList': globalsList, |
|
596 'ClassesList': classList, |
|
597 'ClassesDetails': classBodies, |
|
598 'FunctionsList': methList, |
|
599 'FunctionsDetails': methBodies, |
|
600 }) |
|
601 except TagError as e: |
|
602 sys.stderr.write( |
|
603 "Error processing {0}.\n".format(self.module.file)) |
|
604 sys.stderr.write( |
|
605 "Error in tags of description of Ruby module {0}.\n" |
|
606 .format(rbModuleName)) |
|
607 sys.stderr.write("{0}\n".format(e)) |
|
608 rbmBody = "" |
|
609 |
|
610 rbModules.append(rbmBody) |
|
611 |
|
612 return ''.join(rbModules) |
|
613 |
|
614 def __genRbModulesClassesSection(self, obj, modName): |
|
615 """ |
|
616 Private method to generate the Ruby module classes details section. |
|
617 |
|
618 @param obj Reference to the object being formatted. |
|
619 @param modName Name of the Ruby module containing the classes. (string) |
|
620 @return The classes list and classes details section. |
|
621 (tuple of two string) |
|
622 """ |
|
623 classNames = sorted(list(obj.classes.keys())) |
|
624 classes = [] |
|
625 for className in classNames: |
|
626 _class = obj.classes[className] |
|
627 supers = _class.super |
|
628 if len(supers) > 0: |
|
629 supers = ', '.join(supers) |
|
630 else: |
|
631 supers = 'None' |
|
632 |
|
633 methList, methBodies = \ |
|
634 self.__genMethodSection(_class, className, Function.General) |
|
635 |
|
636 try: |
|
637 clsBody = self.rbModulesClassTemplate.format( |
|
638 **{'Anchor': className, |
|
639 'Class': _class.name, |
|
640 'ClassSuper': supers, |
|
641 'ClassDescription': |
|
642 self.__formatDescription(_class.description), |
|
643 'MethodList': methList, |
|
644 'MethodDetails': methBodies, |
|
645 }) |
|
646 except TagError as e: |
|
647 sys.stderr.write( |
|
648 "Error processing {0}.\n".format(self.module.file)) |
|
649 sys.stderr.write( |
|
650 "Error in tags of description of class {0}.\n".format( |
|
651 className)) |
|
652 sys.stderr.write("{0}\n".format(e)) |
|
653 clsBody = "" |
|
654 |
|
655 classes.append(clsBody) |
|
656 |
|
657 classesList = self.__genRbModulesClassesListSection( |
|
658 classNames, obj.classes, modName) |
|
659 |
|
660 if not classesList: |
|
661 classesList = self.listEntryNoneTemplate |
|
662 return (self.listTemplate.format(**{'Entries': classesList}), |
|
663 ''.join(classes)) |
|
664 |
|
665 def __genRbModulesClassesListSection(self, names, sectionDict, moduleName): |
|
666 """ |
|
667 Private method to generate the classes list section of a Ruby module. |
|
668 |
|
669 @param names The names to appear in the list. (list of strings) |
|
670 @param sectionDict dictionary containing all relevant information |
|
671 (dict) |
|
672 @param moduleName name of the Ruby module containing the classes |
|
673 (string) |
|
674 @return The list section. (string) |
|
675 """ |
|
676 lst = [] |
|
677 for name in names: |
|
678 lst.append(self.listEntryTemplate.format( |
|
679 **{'Link': "{0}.{1}".format(moduleName, name), |
|
680 'Name': sectionDict[name].name, |
|
681 'Description': |
|
682 self.__getShortDescription(sectionDict[name].description), |
|
683 'Deprecated': |
|
684 self.__checkDeprecated(sectionDict[name].description) and |
|
685 self.listEntryDeprecatedTemplate or "", |
|
686 })) |
|
687 self.keywords.append(("{0}.{1}".format(moduleName, name), |
|
688 "#{0}.{1}".format(moduleName, name))) |
|
689 return ''.join(lst) |
|
690 |
|
691 def __genFunctionsSection(self): |
|
692 """ |
|
693 Private method to generate the document section with details about |
|
694 functions. |
|
695 |
|
696 @return The functions details section. (string) |
|
697 """ |
|
698 funcBodies = [] |
|
699 funcNames = sorted(list(self.module.functions.keys())) |
|
700 for funcName in funcNames: |
|
701 try: |
|
702 funcBody = self.functionTemplate.format( |
|
703 **{'Anchor': funcName, |
|
704 'Function': self.module.functions[funcName].name, |
|
705 'FunctionDescription': self.__formatDescription( |
|
706 self.module.functions[funcName].description), |
|
707 'Params': |
|
708 ', '.join(self.module.functions[funcName].parameters), |
|
709 }) |
|
710 except TagError as e: |
|
711 sys.stderr.write( |
|
712 "Error processing {0}.\n".format(self.module.file)) |
|
713 sys.stderr.write( |
|
714 "Error in tags of description of function {0}.\n".format( |
|
715 funcName)) |
|
716 sys.stderr.write("{0}\n".format(e)) |
|
717 funcBody = "" |
|
718 |
|
719 funcBodies.append(funcBody) |
|
720 |
|
721 return ''.join(funcBodies) |
|
722 |
|
723 def __getShortDescription(self, desc): |
|
724 """ |
|
725 Private method to determine the short description of an object. |
|
726 |
|
727 The short description is just the first non empty line of the |
|
728 documentation string. |
|
729 |
|
730 @param desc The documentation string. (string) |
|
731 @return The short description. (string) |
|
732 """ |
|
733 dlist = desc.splitlines() |
|
734 sdlist = [] |
|
735 descfound = 0 |
|
736 for desc in dlist: |
|
737 desc = desc.strip() |
|
738 if desc: |
|
739 descfound = 1 |
|
740 dotpos = desc.find('.') |
|
741 if dotpos == -1: |
|
742 sdlist.append(desc.strip()) |
|
743 else: |
|
744 while dotpos + 1 < len(desc) and \ |
|
745 not desc[dotpos + 1].isspace(): |
|
746 # don't recognize '.' inside a number or word as |
|
747 # stop condition |
|
748 dotpos = desc.find('.', dotpos + 1) |
|
749 if dotpos == -1: |
|
750 break |
|
751 if dotpos == -1: |
|
752 sdlist.append(desc.strip()) |
|
753 else: |
|
754 sdlist.append(desc[:dotpos + 1].strip()) |
|
755 break # break if a '.' is found |
|
756 else: |
|
757 if descfound: |
|
758 break # break if an empty line is found |
|
759 if sdlist: |
|
760 return html_uencode(' '.join(sdlist)) |
|
761 else: |
|
762 return '' |
|
763 |
|
764 def __checkDeprecated(self, descr): |
|
765 """ |
|
766 Private method to check, if the object to be documented contains a |
|
767 deprecated flag. |
|
768 |
|
769 @param descr documentation string (string) |
|
770 @return flag indicating the deprecation status (boolean) |
|
771 """ |
|
772 dlist = descr.splitlines() |
|
773 for desc in dlist: |
|
774 desc = desc.strip() |
|
775 if desc.startswith("@deprecated"): |
|
776 return True |
|
777 return False |
|
778 |
|
779 def __genParagraphs(self, lines): |
|
780 """ |
|
781 Private method to assemble the descriptive paragraphs of a docstring. |
|
782 |
|
783 A paragraph is made up of a number of consecutive lines without |
|
784 an intermediate empty line. Empty lines are treated as a paragraph |
|
785 delimiter. |
|
786 |
|
787 @param lines A list of individual lines. (list of strings) |
|
788 @return Ready formatted paragraphs. (string) |
|
789 """ |
|
790 lst = [] |
|
791 linelist = [] |
|
792 for line in lines: |
|
793 if line.strip(): |
|
794 if line == '.': |
|
795 linelist.append("") |
|
796 else: |
|
797 linelist.append(html_uencode(line)) |
|
798 else: |
|
799 lst.append(self.paragraphTemplate.format( |
|
800 **{'Lines': '\n'.join(linelist)})) |
|
801 linelist = [] |
|
802 if linelist: |
|
803 lst.append(self.paragraphTemplate.format( |
|
804 **{'Lines': '\n'.join(linelist)})) |
|
805 return ''.join(lst) |
|
806 |
|
807 def __genDescriptionListSection(self, dictionary, template): |
|
808 """ |
|
809 Private method to generate the list section of a description. |
|
810 |
|
811 @param dictionary Dictionary containing the info for the |
|
812 list section. |
|
813 @param template The template to be used for the list. (string) |
|
814 @return The list section. (string) |
|
815 """ |
|
816 lst = [] |
|
817 keys = sorted(list(dictionary.keys())) |
|
818 for key in keys: |
|
819 lst.append(template.format( |
|
820 **{'Name': key, |
|
821 'Description': html_uencode('\n'.join(dictionary[key])), |
|
822 })) |
|
823 return ''.join(lst) |
|
824 |
|
825 def __genParamDescriptionListSection(self, _list): |
|
826 """ |
|
827 Private method to generate the list section of a description. |
|
828 |
|
829 @param _list list containing the info for the parameter description |
|
830 list section (list of lists with three elements) |
|
831 @return formatted list section (string) |
|
832 """ |
|
833 lst = [] |
|
834 for name, type_, lines in _list: |
|
835 if type_: |
|
836 lst.append(self.parameterTypesListEntryTemplate.format( |
|
837 **{'Name': name, |
|
838 'Type': type_, |
|
839 'Description': html_uencode('\n'.join(lines)), |
|
840 })) |
|
841 else: |
|
842 lst.append(self.parametersListEntryTemplate.format( |
|
843 **{'Name': name, |
|
844 'Description': html_uencode('\n'.join(lines)), |
|
845 })) |
|
846 return ''.join(lst) |
|
847 |
|
848 def __formatCrossReferenceEntry(self, entry): |
|
849 """ |
|
850 Private method to format a cross reference entry. |
|
851 |
|
852 This cross reference entry looks like "package.module#member label". |
|
853 |
|
854 @param entry the entry to be formatted (string) |
|
855 @return formatted entry (string) |
|
856 """ |
|
857 if entry.startswith('"'): |
|
858 return entry |
|
859 elif entry.startswith('<'): |
|
860 entry = entry[3:] |
|
861 else: |
|
862 try: |
|
863 reference, label = entry.split(None, 1) |
|
864 except ValueError: |
|
865 reference = entry |
|
866 label = entry |
|
867 try: |
|
868 path, anchor = reference.split('#', 1) |
|
869 except ValueError: |
|
870 path = reference |
|
871 anchor = '' |
|
872 reference = path and "{0}.html".format(path) or '' |
|
873 if anchor: |
|
874 reference = "{0}#{1}".format(reference, anchor) |
|
875 entry = 'href="{0}">{1}</a>'.format(reference, label) |
|
876 |
|
877 return self.seeLinkTemplate.format(**{'Link': entry}) |
|
878 |
|
879 def __genSeeListSection(self, _list, template): |
|
880 """ |
|
881 Private method to generate the "see also" list section of a |
|
882 description. |
|
883 |
|
884 @param _list List containing the info for the section. |
|
885 @param template The template to be used for the list. (string) |
|
886 @return The list section. (string) |
|
887 """ |
|
888 lst = [] |
|
889 for seeEntry in _list: |
|
890 seeEntryString = ''.join(seeEntry) |
|
891 lst.append(template.format( |
|
892 **{'Link': html_uencode(self.__formatCrossReferenceEntry( |
|
893 seeEntryString)), |
|
894 })) |
|
895 return '\n'.join(lst) |
|
896 |
|
897 def __processInlineTags(self, desc): |
|
898 """ |
|
899 Private method to process inline tags. |
|
900 |
|
901 @param desc One line of the description (string) |
|
902 @return processed line with inline tags expanded (string) |
|
903 @exception TagError raised to indicate an invalid tag |
|
904 """ |
|
905 start = desc.find('{@') |
|
906 while start != -1: |
|
907 stop = desc.find('}', start + 2) |
|
908 if stop == -1: |
|
909 raise TagError("Unterminated inline tag.\n{0}".format(desc)) |
|
910 |
|
911 tagText = desc[start + 1:stop] |
|
912 if tagText.startswith('@link'): |
|
913 parts = tagText.split(None, 1) |
|
914 if len(parts) < 2: |
|
915 raise TagError( |
|
916 "Wrong format in inline tag {0}.\n{1}".format( |
|
917 parts[0], desc)) |
|
918 |
|
919 formattedTag = self.__formatCrossReferenceEntry(parts[1]) |
|
920 desc = desc.replace("{{{0}}}".format(tagText), formattedTag) |
|
921 else: |
|
922 tag = tagText.split(None, 1)[0] |
|
923 raise TagError( |
|
924 "Unknown inline tag encountered, {0}.\n{1}".format( |
|
925 tag, desc)) |
|
926 |
|
927 start = desc.find('{@') |
|
928 |
|
929 return desc |
|
930 |
|
931 def __formatDescription(self, descr): |
|
932 """ |
|
933 Private method to format the contents of the documentation string. |
|
934 |
|
935 @param descr The contents of the documentation string. (string) |
|
936 @exception TagError A tag doesn't have the correct number |
|
937 of arguments. |
|
938 @return The formated contents of the documentation string. (string) |
|
939 """ |
|
940 if not descr: |
|
941 return "" |
|
942 |
|
943 paragraphs = [] |
|
944 paramList = [] |
|
945 returns = [] |
|
946 returnTypes = [] |
|
947 exceptionDict = {} |
|
948 signalDict = {} |
|
949 eventDict = {} |
|
950 deprecated = [] |
|
951 authorInfo = [] |
|
952 sinceInfo = [] |
|
953 seeList = [] |
|
954 lastItem = paragraphs |
|
955 inTagSection = False |
|
956 |
|
957 dlist = descr.splitlines() |
|
958 while dlist and not dlist[0]: |
|
959 del dlist[0] |
|
960 lastTag = "" |
|
961 for ditem in dlist: |
|
962 ditem = self.__processInlineTags(ditem) |
|
963 desc = ditem.strip() |
|
964 if desc: |
|
965 if desc.startswith(("@param", "@keyparam")): |
|
966 inTagSection = True |
|
967 parts = desc.split(None, 2) |
|
968 lastTag = parts[0] |
|
969 if len(parts) < 2: |
|
970 raise TagError( |
|
971 "Wrong format in {0} line.\n".format(parts[0])) |
|
972 paramName = parts[1] |
|
973 if parts[0] == "@keyparam": |
|
974 paramName += '=' |
|
975 try: |
|
976 paramList.append([paramName, "", [parts[2]]]) |
|
977 except IndexError: |
|
978 paramList.append([paramName, "", []]) |
|
979 lastItem = paramList[-1][2] |
|
980 elif desc.startswith("@type"): |
|
981 parts = desc.split(None, 1) |
|
982 if lastTag not in ["@param", "@keyparam"]: |
|
983 raise TagError( |
|
984 "{0} line must be preceded by a parameter line\n" |
|
985 .format(parts[0])) |
|
986 inTagSection = True |
|
987 lastTag = parts[0] |
|
988 if len(parts) < 2: |
|
989 raise TagError( |
|
990 "Wrong format in {0} line.\n".format(parts[0])) |
|
991 paramList[-1][1] = parts[1] |
|
992 elif desc.startswith("@ptype"): |
|
993 inTagSection = True |
|
994 parts = desc.split(None, 2) |
|
995 lastTag = parts[0] |
|
996 if len(parts) < 3: |
|
997 raise TagError( |
|
998 "Wrong format in {0} line.\n".format(parts[0])) |
|
999 param, type_ = parts[1:] |
|
1000 for index in range(len(paramList)): |
|
1001 if paramList[index][0] == param: |
|
1002 paramList[index][1] = type_ |
|
1003 break |
|
1004 else: |
|
1005 raise TagError( |
|
1006 "Unknow parameter name '{0}' in {1} line.\n" |
|
1007 .format(param, parts[0])) |
|
1008 elif desc.startswith(("@return", "@ireturn")): |
|
1009 inTagSection = True |
|
1010 parts = desc.split(None, 1) |
|
1011 lastTag = parts[0] |
|
1012 if len(parts) < 2: |
|
1013 raise TagError( |
|
1014 "Wrong format in {0} line.\n".format(parts[0])) |
|
1015 returns = [parts[1]] |
|
1016 lastItem = returns |
|
1017 elif desc.startswith("@rtype"): |
|
1018 parts = desc.split(None, 1) |
|
1019 if lastTag not in ["@return", "@ireturn"]: |
|
1020 raise TagError( |
|
1021 "{0} line must be preceded by a return line\n" |
|
1022 .format(parts[0])) |
|
1023 inTagSection = True |
|
1024 lastTag = parts[0] |
|
1025 if len(parts) < 2: |
|
1026 raise TagError( |
|
1027 "Wrong format in {0} line.\n".format(parts[0])) |
|
1028 returnTypes = [parts[1]] |
|
1029 lastItem = returnTypes |
|
1030 elif desc.startswith(("@exception", "@throws", "@raise")): |
|
1031 inTagSection = True |
|
1032 parts = desc.split(None, 2) |
|
1033 lastTag = parts[0] |
|
1034 if len(parts) < 2: |
|
1035 raise TagError( |
|
1036 "Wrong format in {0} line.\n".format(parts[0])) |
|
1037 excName = parts[1] |
|
1038 try: |
|
1039 exceptionDict[excName] = [parts[2]] |
|
1040 except IndexError: |
|
1041 exceptionDict[excName] = [] |
|
1042 lastItem = exceptionDict[excName] |
|
1043 elif desc.startswith("@signal"): |
|
1044 inTagSection = True |
|
1045 lastTag = desc.split(None, 1)[0] |
|
1046 m = _signal(desc, 0) |
|
1047 if m is None: |
|
1048 raise TagError("Wrong format in @signal line.\n") |
|
1049 signalName = 1 and m.group("SignalName1") \ |
|
1050 or m.group("SignalName2") |
|
1051 signalDesc = 1 and m.group("SignalDescription1") \ |
|
1052 or m.group("SignalDescription2") |
|
1053 signalDict[signalName] = [] |
|
1054 if signalDesc is not None: |
|
1055 signalDict[signalName].append(signalDesc) |
|
1056 lastItem = signalDict[signalName] |
|
1057 elif desc.startswith("@event"): |
|
1058 inTagSection = True |
|
1059 lastTag = desc.split(None, 1)[0] |
|
1060 m = _event(desc, 0) |
|
1061 if m is None: |
|
1062 raise TagError( |
|
1063 "Wrong format in {0} line.\n".format(parts[0])) |
|
1064 eventName = 1 and m.group("EventName1") \ |
|
1065 or m.group("EventName2") |
|
1066 eventDesc = 1 and m.group("EventDescription1") \ |
|
1067 or m.group("EventDescription2") |
|
1068 eventDict[eventName] = [] |
|
1069 if eventDesc is not None: |
|
1070 eventDict[eventName].append(eventDesc) |
|
1071 lastItem = eventDict[eventName] |
|
1072 elif desc.startswith("@deprecated"): |
|
1073 inTagSection = True |
|
1074 parts = desc.split(None, 1) |
|
1075 lastTag = parts[0] |
|
1076 if len(parts) < 2: |
|
1077 raise TagError( |
|
1078 "Wrong format in {0} line.\n".format(parts[0])) |
|
1079 deprecated = [parts[1]] |
|
1080 lastItem = deprecated |
|
1081 elif desc.startswith("@author"): |
|
1082 inTagSection = True |
|
1083 parts = desc.split(None, 1) |
|
1084 lastTag = parts[0] |
|
1085 if len(parts) < 2: |
|
1086 raise TagError( |
|
1087 "Wrong format in {0} line.\n".format(parts[0])) |
|
1088 authorInfo = [parts[1]] |
|
1089 lastItem = authorInfo |
|
1090 elif desc.startswith("@since"): |
|
1091 inTagSection = True |
|
1092 parts = desc.split(None, 1) |
|
1093 lastTag = parts[0] |
|
1094 if len(parts) < 2: |
|
1095 raise TagError( |
|
1096 "Wrong format in {0} line.\n".format(parts[0])) |
|
1097 sinceInfo = [parts[1]] |
|
1098 lastItem = sinceInfo |
|
1099 elif desc.startswith("@see"): |
|
1100 inTagSection = True |
|
1101 parts = desc.split(None, 1) |
|
1102 lastTag = parts[0] |
|
1103 if len(parts) < 2: |
|
1104 raise TagError( |
|
1105 "Wrong format in {0} line.\n".format(parts[0])) |
|
1106 seeList.append([parts[1]]) |
|
1107 lastItem = seeList[-1] |
|
1108 elif desc.startswith("@@"): |
|
1109 lastItem.append(desc[1:]) |
|
1110 elif desc.startswith("@"): |
|
1111 tag = desc.split(None, 1)[0] |
|
1112 raise TagError( |
|
1113 "Unknown tag encountered, {0}.\n".format(tag)) |
|
1114 else: |
|
1115 lastItem.append(ditem) |
|
1116 elif not inTagSection: |
|
1117 lastItem.append(ditem) |
|
1118 |
|
1119 if paragraphs: |
|
1120 description = self.__genParagraphs(paragraphs) |
|
1121 else: |
|
1122 description = "" |
|
1123 |
|
1124 if paramList: |
|
1125 parameterSect = self.parametersListTemplate.format( |
|
1126 **{'Parameters': self.__genParamDescriptionListSection( |
|
1127 paramList)}) |
|
1128 else: |
|
1129 parameterSect = "" |
|
1130 |
|
1131 if returns: |
|
1132 returnSect = self.returnsTemplate.format( |
|
1133 html_uencode('\n'.join(returns))) |
|
1134 else: |
|
1135 returnSect = "" |
|
1136 |
|
1137 if returnTypes: |
|
1138 returnTypesSect = self.returnTypesTemplate.format( |
|
1139 html_uencode('\n'.join(returnTypes))) |
|
1140 else: |
|
1141 returnTypesSect = "" |
|
1142 |
|
1143 if exceptionDict: |
|
1144 exceptionSect = self.exceptionsListTemplate.format( |
|
1145 **{'Exceptions': self.__genDescriptionListSection( |
|
1146 exceptionDict, self.exceptionsListEntryTemplate)}) |
|
1147 else: |
|
1148 exceptionSect = "" |
|
1149 |
|
1150 if signalDict: |
|
1151 signalSect = self.signalsListTemplate.format( |
|
1152 **{'Signals': self.__genDescriptionListSection( |
|
1153 signalDict, self.signalsListEntryTemplate)}) |
|
1154 else: |
|
1155 signalSect = "" |
|
1156 |
|
1157 if eventDict: |
|
1158 eventSect = self.eventsListTemplate.format( |
|
1159 **{'Events': self.__genDescriptionListSection( |
|
1160 eventDict, self.eventsListEntryTemplate)}) |
|
1161 else: |
|
1162 eventSect = "" |
|
1163 |
|
1164 if deprecated: |
|
1165 deprecatedSect = self.deprecatedTemplate.format( |
|
1166 **{'Lines': html_uencode('\n'.join(deprecated))}) |
|
1167 else: |
|
1168 deprecatedSect = "" |
|
1169 |
|
1170 if authorInfo: |
|
1171 authorInfoSect = self.authorInfoTemplate.format( |
|
1172 **{'Authors': html_uencode('\n'.join(authorInfo))}) |
|
1173 else: |
|
1174 authorInfoSect = "" |
|
1175 |
|
1176 if sinceInfo: |
|
1177 sinceInfoSect = self.sinceInfoTemplate.format( |
|
1178 **{'Info': html_uencode(sinceInfo[0])}) |
|
1179 else: |
|
1180 sinceInfoSect = "" |
|
1181 |
|
1182 if seeList: |
|
1183 seeSect = self.seeListTemplate.format( |
|
1184 **{'Links': self.__genSeeListSection( |
|
1185 seeList, self.seeListEntryTemplate)}) |
|
1186 else: |
|
1187 seeSect = '' |
|
1188 |
|
1189 return "{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}".format( |
|
1190 deprecatedSect, description, parameterSect, returnSect, |
|
1191 returnTypesSect, exceptionSect, signalSect, eventSect, |
|
1192 authorInfoSect, seeSect, sinceInfoSect, |
|
1193 ) |
|
1194 |
|
1195 def getQtHelpKeywords(self): |
|
1196 """ |
|
1197 Public method to retrieve the parts for the QtHelp keywords section. |
|
1198 |
|
1199 @return list of tuples containing the name (string) and the ref |
|
1200 (string). The ref is without the filename part. |
|
1201 """ |
|
1202 if not self.generated: |
|
1203 self.genDocument() |
|
1204 |
|
1205 return self.keywords |