1
2
3
4
5
6
7
8
9 """
10 The LaTeX output generator for epydoc. The main interface provided by
11 this module is the L{LatexWriter} class.
12
13 @todo: Inheritance=listed
14 """
15 __docformat__ = 'epytext en'
16
17 import os.path, sys, time, re, textwrap, codecs
18
19 from epydoc.apidoc import *
20 from epydoc.compat import *
21 import epydoc
22 from epydoc import log
23 from epydoc import markup
24 from epydoc.util import plaintext_to_latex
25 import epydoc.markup
26
28 PREAMBLE = [
29 "\\documentclass{article}",
30 "\\usepackage{alltt, parskip, fancyheadings, boxedminipage}",
31 "\\usepackage{makeidx, multirow, longtable, tocbibind, amssymb}",
32 "\\usepackage{fullpage}",
33
34
35 "\\setlength{\\headheight}{16pt}",
36 "\\setlength{\\headsep}{24pt}",
37 "\\setlength{\\topmargin}{-\\headsep}",
38
39 "\\setlength{\\parindent}{0ex}",
40
41 "\\setlength{\\fboxrule}{2\\fboxrule}",
42
43 "\\newlength{\\BCL} % base class length, for base trees.",
44
45 "\\pagestyle{fancy}",
46 "\\renewcommand{\\sectionmark}[1]{\\markboth{#1}{}}",
47 "\\renewcommand{\\subsectionmark}[1]{\\markright{#1}}",
48
49 textwrap.dedent("""\
50 \\newenvironment{Ventry}[1]%
51 {\\begin{list}{}{%
52 \\renewcommand{\\makelabel}[1]{\\texttt{##1:}\\hfil}%
53 \\settowidth{\\labelwidth}{\\texttt{#1:}}%
54 \\setlength{\\leftmargin}{\\labelsep}%
55 \\addtolength{\\leftmargin}{\\labelwidth}}}%
56 {\\end{list}}"""),
57 ]
58
59 HRULE = '\\rule{\\textwidth}{0.5\\fboxrule}\n\n'
60
61 SECTIONS = ['\\part{%s}', '\\chapter{%s}', '\\section{%s}',
62 '\\subsection{%s}', '\\subsubsection{%s}',
63 '\\textbf{%s}']
64
65 STAR_SECTIONS = ['\\part*{%s}', '\\chapter*{%s}', '\\section*{%s}',
66 '\\subsection*{%s}', '\\subsubsection*{%s}',
67 '\\textbf{%s}']
68
70 self.docindex = docindex
71
72 self._show_private = kwargs.get('private', 0)
73 self._prj_name = kwargs.get('prj_name', None) or 'API Documentation'
74 self._crossref = kwargs.get('crossref', 1)
75 self._index = kwargs.get('index', 1)
76 self._list_classes_separately=kwargs.get('list_classes_separately',0)
77 self._inheritance = kwargs.get('inheritance', 'listed')
78 self._exclude = kwargs.get('exclude', 1)
79 self._top_section = 2
80 self._index_functions = 1
81 self._hyperref = 1
82 self._encoding = kwargs.get('encoding', 'latin1')
83 self.valdocs = sorted(docindex.reachable_valdocs(
84 imports=False, packages=False, bases=False, submodules=False,
85 subclasses=False, private=self._show_private))
86 self._num_files = self.num_files()
87
88 if self._show_private: self._public_filter = None
89 else: self._public_filter = True
90
91 - def write(self, directory=None):
92 """
93 Write the API documentation for the entire project to the
94 given directory.
95
96 @type directory: C{string}
97 @param directory: The directory to which output should be
98 written. If no directory is specified, output will be
99 written to the current directory. If the directory does
100 not exist, it will be created.
101 @rtype: C{None}
102 @raise OSError: If C{directory} cannot be created,
103 @raise OSError: If any file cannot be created or written to.
104 """
105
106 self._files_written = 0.
107
108
109 if not directory: directory = os.curdir
110 self._mkdir(directory)
111 self._directory = directory
112
113
114 self._write(self.write_topfile, directory, 'api.tex')
115
116
117 for val_doc in self.valdocs:
118 if isinstance(val_doc, ModuleDoc):
119 filename = '%s-module.tex' % val_doc.canonical_name
120 self._write(self.write_module, directory, filename, val_doc)
121 elif (isinstance(val_doc, ClassDoc) and
122 self._list_classes_separately):
123 filename = '%s-class.tex' % val_doc.canonical_name
124 self._write(self.write_class, directory, filename, val_doc)
125
126 - def _write(self, write_func, directory, filename, *args):
127
128 self._files_written += 1
129 log.progress(self._files_written/self._num_files, filename)
130
131 path = os.path.join(directory, filename)
132 if self._encoding == 'utf8':
133 f = codecs.open(path, 'w', 'utf-8')
134 write_func(f.write, *args)
135 f.close()
136 else:
137 result = []
138 write_func(result.append, *args)
139 s = u''.join(result)
140 try:
141 s = s.encode(self._encoding)
142 except UnicodeError:
143 log.error("Output could not be represented with the "
144 "given encoding (%r). Unencodable characters "
145 "will be displayed as '?'. It is recommended "
146 "that you use a different output encoding (utf8, "
147 "if it's supported by latex on your system).")
148 s = s.encode(self._encoding, 'replace')
149 f = open(path, 'w')
150 f.write(s)
151 f.close()
152
154 """
155 @return: The number of files that this C{LatexFormatter} will
156 generate.
157 @rtype: C{int}
158 """
159 n = 1
160 for doc in self.valdocs:
161 if isinstance(doc, ModuleDoc): n += 1
162 if isinstance(doc, ClassDoc) and self._list_classes_separately:
163 n += 1
164 return n
165
167 """
168 If the given directory does not exist, then attempt to create it.
169 @rtype: C{None}
170 """
171 if not os.path.isdir(directory):
172 if os.path.exists(directory):
173 raise OSError('%r is not a directory' % directory)
174 os.mkdir(directory)
175
176
177
178
179
181 self.write_header(out, 'Include File')
182 self.write_preamble(out)
183 out('\n\\begin{document}\n\n')
184 self.write_start_of(out, 'Header')
185
186
187 self.write_start_of(out, 'Title')
188 out('\\title{%s}\n' % plaintext_to_latex(self._prj_name, 1))
189 out('\\author{API Documentation}\n')
190 out('\\maketitle\n')
191
192
193 self.write_start_of(out, 'Table of Contents')
194 out('\\addtolength{\\parskip}{-1ex}\n')
195 out('\\tableofcontents\n')
196 out('\\addtolength{\\parskip}{1ex}\n')
197
198
199 self.write_start_of(out, 'Includes')
200 for val_doc in self.valdocs:
201 if isinstance(val_doc, ModuleDoc):
202 out('\\include{%s-module}\n' % val_doc.canonical_name)
203
204
205
206 if self._list_classes_separately:
207 for val_doc in self.valdocs:
208 if isinstance(val_doc, ClassDoc):
209 out('\\include{%s-class}\n' % val_doc.canonical_name)
210
211
212 if self._index:
213 self.write_start_of(out, 'Index')
214 out('\\printindex\n\n')
215
216
217 self.write_start_of(out, 'Footer')
218 out('\\end{document}\n\n')
219
221 out('\n'.join(self.PREAMBLE))
222 out('\n')
223
224
225 out('\\usepackage[%s]{inputenc}' % self._encoding)
226
227
228 if self._hyperref:
229 out('\\usepackage[usenames]{color}\n')
230 out('\\definecolor{UrlColor}{rgb}{0,0.08,0.45}\n')
231 out('\\usepackage[dvips, pagebackref, pdftitle={%s}, '
232 'pdfcreator={epydoc %s}, bookmarks=true, '
233 'bookmarksopen=false, pdfpagemode=UseOutlines, '
234 'colorlinks=true, linkcolor=black, anchorcolor=black, '
235 'citecolor=black, filecolor=black, menucolor=black, '
236 'pagecolor=black, urlcolor=UrlColor]{hyperref}\n' %
237 (self._prj_name or '', epydoc.__version__))
238
239
240 if self._index:
241 out("\\makeindex\n")
242
243
244
245 if 'restructuredtext' in epydoc.markup.MARKUP_LANGUAGES_USED:
246 from epydoc.markup import restructuredtext
247 rst_head = restructuredtext.latex_head_prefix()
248 for line in rst_head[1:]:
249 m = re.match(r'\\usepackage(\[.*?\])?{(.*?)}', line)
250 if m and m.group(2) in (
251 'babel', 'hyperref', 'color', 'alltt', 'parskip',
252 'fancyheadings', 'boxedminipage', 'makeidx',
253 'multirow', 'longtable', 'tocbind', 'assymb',
254 'fullpage'):
255 pass
256 else:
257 out(line)
258
259
260
261
262
263
265 self.write_header(out, doc)
266 self.write_start_of(out, 'Module Description')
267
268
269 out(' ' + self.indexterm(doc, 'start'))
270
271
272 out(self.section('%s %s' % (self.doc_kind(doc),
273 doc.canonical_name)))
274
275
276 out(' \\label{%s}\n' % self.label(doc))
277
278
279 if doc.descr not in (None, UNKNOWN):
280 out(self.docstring_to_latex(doc.descr))
281
282
283 self.write_standard_fields(out, doc)
284
285
286 if doc.submodules != UNKNOWN and doc.submodules:
287 self.write_module_list(out, doc)
288
289
290 if self._list_classes_separately:
291 self.write_class_list(out, doc)
292 self.write_func_list(out, 'Functions', doc, 'function')
293 self.write_var_list(out, 'Variables', doc, 'other')
294
295
296 if not self._list_classes_separately:
297 classes = doc.select_variables(imported=False, value_type='class',
298 public=self._public_filter)
299 for var_doc in classes:
300 self.write_class(out, var_doc.value)
301
302
303 out(' ' + self.indexterm(doc, 'end'))
304
306 if self._list_classes_separately:
307 self.write_header(out, doc)
308 self.write_start_of(out, 'Class Description')
309
310
311 out(' ' + self.indexterm(doc, 'start'))
312
313
314 if self._list_classes_separately:
315 seclevel = 0
316 out(self.section('%s %s' % (self.doc_kind(doc),
317 doc.canonical_name), seclevel))
318 else:
319 seclevel = 1
320 out(self.section('%s %s' % (self.doc_kind(doc),
321 doc.canonical_name[-1]), seclevel))
322
323
324 out(' \\label{%s}\n' % self.label(doc))
325
326
327 if doc.bases not in (UNKNOWN, None) and len(doc.bases) > 0:
328 out(self.base_tree(doc))
329
330
331 if doc.subclasses not in (UNKNOWN, None) and len(doc.subclasses) > 0:
332 sc_items = [plaintext_to_latex('%s' % sc.canonical_name)
333 for sc in doc.subclasses]
334 out(self._descrlist(sc_items, 'Known Subclasses', short=1))
335
336
337 if doc.descr not in (None, UNKNOWN):
338 out(self.docstring_to_latex(doc.descr))
339
340
341 self.write_standard_fields(out, doc)
342
343
344 self.write_func_list(out, 'Methods', doc, 'method',
345 seclevel+1)
346 self.write_var_list(out, 'Properties', doc,
347 'property', seclevel+1)
348 self.write_var_list(out, 'Class Variables', doc,
349 'classvariable', seclevel+1)
350 self.write_var_list(out, 'Instance Variables', doc,
351 'instancevariable', seclevel+1)
352
353
354 out(' ' + self.indexterm(doc, 'end'))
355
356
357
358
359
361 modules = [doc for doc in self.valdocs
362 if isinstance(doc, ModuleDoc)]
363 if not modules: return
364
365
366 out('\\begin{itemize}\n')
367 out('\\setlength{\\parskip}{0ex}\n')
368 for doc in modules:
369 if (doc.package in (None, UNKNOWN) or
370 doc.package not in self.valdocs):
371 self.write_module_tree_item(out, doc)
372 return s +'\\end{itemize}\n'
373
375 if len(doc.submodules) == 0: return
376 self.write_start_of(out, 'Modules')
377
378 out(self.section('Modules', 1))
379 out('\\begin{itemize}\n')
380 out('\\setlength{\\parskip}{0ex}\n')
381
382 for group_name in doc.group_names():
383 if not doc.submodule_groups[group_name]: continue
384 if group_name:
385 out(' \\item \\textbf{%s}\n' % group_name)
386 out(' \\begin{itemize}\n')
387 for submodule in doc.submodule_groups[group_name]:
388 self.write_module_tree_item(out, submodule)
389 if group_name:
390 out(' \end{itemize}\n')
391
392 out('\\end{itemize}\n\n')
393
395 """
396 Helper function for L{_module_tree} and L{_module_list}.
397
398 @rtype: C{string}
399 """
400 out(' '*depth + '\\item \\textbf{')
401 out(plaintext_to_latex(doc.canonical_name[-1]) +'}')
402 if doc.summary not in (None, UNKNOWN):
403 out(': %s\n' % self.docstring_to_latex(doc.summary))
404 if self._crossref:
405 out('\n \\textit{(Section \\ref{%s}' % self.label(doc))
406 out(', p.~\\pageref{%s})}\n\n' % self.label(doc))
407 if doc.submodules != UNKNOWN and doc.submodules:
408 out(' '*depth + ' \\begin{itemize}\n')
409 out(' '*depth + '\\setlength{\\parskip}{0ex}\n')
410 for submodule in doc.submodules:
411 self.write_module_tree_item(out, submodule, depth+4)
412 out(' '*depth + ' \\end{itemize}\n')
413
414
415
416
417
418 - def base_tree(self, doc, width=None, linespec=None):
419 if width is None:
420 width = self._find_tree_width(doc)+2
421 linespec = []
422 s = ('&'*(width-4)+'\\multicolumn{2}{l}{\\textbf{%s}}\n' %
423 plaintext_to_latex('%s'%doc.canonical_name))
424 s += '\\end{tabular}\n\n'
425 top = 1
426 else:
427 s = self._base_tree_line(doc, width, linespec)
428 top = 0
429
430 if isinstance(doc, ClassDoc):
431 for i in range(len(doc.bases)-1, -1, -1):
432 base = doc.bases[i]
433 spec = (i > 0)
434 s = self.base_tree(base, width, [spec]+linespec) + s
435
436 if top:
437 s = '\\begin{tabular}{%s}\n' % (width*'c') + s
438
439 return s
440
442 if not isinstance(doc, ClassDoc): return 2
443 width = 2
444 for base in doc.bases:
445 width = max(width, self._find_tree_width(base)+2)
446 return width
447
449
450 s = '%% Line for %s, linespec=%s\n' % (doc.canonical_name, linespec)
451
452 labelwidth = width-2*len(linespec)-2
453
454
455 shortname = plaintext_to_latex('%s'%doc.canonical_name)
456 s += ('\\multicolumn{%s}{r}{' % labelwidth)
457 s += '\\settowidth{\\BCL}{%s}' % shortname
458 s += '\\multirow{2}{\\BCL}{%s}}\n' % shortname
459
460
461 for vbar in linespec:
462 if vbar: s += '&&\\multicolumn{1}{|c}{}\n'
463 else: s += '&&\n'
464
465
466 s += ' \\\\\\cline{%s-%s}\n' % (labelwidth+1, labelwidth+1)
467
468
469 s += ' ' + '&'*labelwidth
470 s += '\\multicolumn{1}{c|}{}\n'
471
472
473 for vbar in linespec:
474 if vbar: s += '&\\multicolumn{1}{|c}{}&\n'
475 else: s += '&&\n'
476 s += ' \\\\\n'
477
478 return s
479
480
481
482
483
485 groups = [(plaintext_to_latex(group_name),
486 doc.select_variables(group=group_name, imported=False,
487 value_type='class',
488 public=self._public_filter))
489 for group_name in doc.group_names()]
490
491
492 groups = [(g,vars) for (g,vars) in groups if vars]
493 if not groups: return
494
495
496 self.write_start_of(out, 'Classes')
497 out(self.section('Classes', 1))
498 out('\\begin{itemize}')
499 out(' \\setlength{\\parskip}{0ex}\n')
500
501 for name, var_docs in groups:
502 if name:
503 out(' \\item \\textbf{%s}\n' % name)
504 out(' \\begin{itemize}\n')
505
506 for var_doc in var_docs:
507 self.write_class_list_line(out, var_doc)
508 if name:
509 out(' \\end{itemize}\n')
510
511 out('\\end{itemize}\n')
512
523
524
525
526
527
529 groups = [(plaintext_to_latex(group_name),
530 doc.select_variables(group=group_name, imported=False,
531 value_type=value_type,
532 public=self._public_filter))
533 for group_name in doc.group_names()]
534
535
536 groups = [(g,vars) for (g,vars) in groups if vars]
537 if not groups: return
538
539
540 self.write_start_of(out, heading)
541 out(' '+self.section(heading, seclevel))
542
543 for name, var_docs in groups:
544 if name:
545 out('\n%s\\large{%s}\n' % (self.HRULE, name))
546 for var_doc in var_docs:
547 self.write_func_list_box(out, var_doc)
548
549
550
551
552
554 func_doc = var_doc.value
555 is_inherited = (var_doc.overrides not in (None, UNKNOWN))
556
557
558
559 if not is_inherited:
560 out(' \\label{%s}\n' % self.label(func_doc))
561 out(' %s\n' % self.indexterm(func_doc))
562
563
564 out(' \\vspace{0.5ex}\n\n')
565 out(' \\begin{boxedminipage}{\\textwidth}\n\n')
566
567
568 out(' %s\n\n' % self.function_signature(var_doc))
569
570 if (func_doc.docstring not in (None, UNKNOWN) and
571 func_doc.docstring.strip() != ''):
572 out(' \\vspace{-1.5ex}\n\n')
573 out(' \\rule{\\textwidth}{0.5\\fboxrule}\n')
574
575
576 if func_doc.descr not in (None, UNKNOWN):
577 out(self.docstring_to_latex(func_doc.descr, 4))
578 out(' \\vspace{1ex}\n\n')
579
580
581 if func_doc.arg_descrs or func_doc.arg_types:
582
583 longest = max([0]+[len(n) for n in func_doc.arg_types])
584 for names, descrs in func_doc.arg_descrs:
585 longest = max([longest]+[len(n) for n in names])
586
587 out(' '*6+'\\textbf{Parameters}\n')
588 out(' '*6+'\\begin{quote}\n')
589 out(' \\begin{Ventry}{%s}\n\n' % (longest*'x'))
590
591 unseen_types = set(func_doc.arg_types)
592
593 for (arg_names, arg_descr) in func_doc.arg_descrs:
594 arg_name = plaintext_to_latex(', '.join(arg_names))
595 out('%s\\item[%s]\n\n' % (' '*10, arg_name))
596 out(self.docstring_to_latex(arg_descr, 10))
597 for arg_name in arg_names:
598 arg_typ = func_doc.arg_types.get(arg_name)
599 if arg_typ is not None:
600 if len(arg_names) == 1:
601 lhs = 'type'
602 else:
603 lhs = 'type of %s' % arg_name
604 rhs = self.docstring_to_latex(arg_typ).strip()
605 out('%s\\textit{(%s=%s)}\n\n' % (' '*12, lhs, rhs))
606 out(' \\end{Ventry}\n\n')
607 out(' '*6+'\\end{quote}\n\n')
608 out(' \\vspace{1ex}\n\n')
609
610
611 rdescr = func_doc.return_descr
612 rtype = func_doc.return_type
613 if rdescr not in (None, UNKNOWN) or rtype not in (None, UNKNOWN):
614 out(' '*6+'\\textbf{Return Value}\n')
615 out(' '*6+'\\begin{quote}\n')
616 if rdescr not in (None, UNKNOWN):
617 out(self.docstring_to_latex(rdescr, 6))
618 if rtype not in (None, UNKNOWN):
619 out(' '*6+'\\textit{(type=%s)}\n\n' %
620 self.docstring_to_latex(rtype, 6).strip())
621 elif rtype not in (None, UNKNOWN):
622 out(self.docstring_to_latex(rtype, 6))
623 out(' '*6+'\\end{quote}\n\n')
624 out(' \\vspace{1ex}\n\n')
625
626
627 if func_doc.exception_descrs not in (None, UNKNOWN, [], ()):
628 out(' '*6+'\\textbf{Raises}\n')
629 out(' '*6+'\\begin{quote}\n')
630 out(' \\begin{description}\n\n')
631 for name, descr in func_doc.exception_descrs:
632 out(' '*10+'\\item[\\texttt{%s}]\n\n' %
633 plaintext_to_latex('%s' % name))
634 out(self.docstring_to_latex(descr, 10))
635 out(' \\end{description}\n\n')
636 out(' '*6+'\\end{quote}\n\n')
637 out(' \\vspace{1ex}\n\n')
638
639
640 if var_doc.overrides not in (None, UNKNOWN):
641 out(' Overrides: ' +
642 plaintext_to_latex('%s'%var_doc.overrides.canonical_name))
643 if (func_doc.docstring in (None, UNKNOWN) and
644 var_doc.overrides.value.docstring not in (None, UNKNOWN)):
645 out(' \textit{(inherited documentation)}')
646 out('\n\n')
647
648
649 self.write_standard_fields(out, func_doc)
650
651 out(' \\end{boxedminipage}\n\n')
652
678
689
691 if isinstance(arg, basestring):
692 return arg
693 elif len(arg) == 1:
694 return '(%s,)' % self._arg_name(arg[0])
695 else:
696 return '(%s)' % (', '.join([self._arg_name(a) for a in arg]))
697
698
699
700
701
702
704 groups = [(plaintext_to_latex(group_name),
705 doc.select_variables(group=group_name, imported=False,
706 value_type=value_type,
707 public=self._public_filter))
708 for group_name in doc.group_names()]
709
710
711 groups = [(g,vars) for (g,vars) in groups if vars]
712 if not groups: return
713
714
715 self.write_start_of(out, heading)
716 out(' '+self.section(heading, seclevel))
717
718 out('\\begin{longtable}')
719 out('{|p{.30\\textwidth}|')
720 out('p{.62\\textwidth}|l}\n')
721 out('\\cline{1-2}\n')
722
723
724
725 out('\\cline{1-2} ')
726 out('\\centering \\textbf{Name} & ')
727 out('\\centering \\textbf{Description}& \\\\\n')
728 out('\\cline{1-2}\n')
729 out('\\endhead')
730 out('\\cline{1-2}')
731 out('\\multicolumn{3}{r}{\\small\\textit{')
732 out('continued on next page}}\\\\')
733 out('\\endfoot')
734 out('\\cline{1-2}\n')
735 out('\\endlastfoot')
736
737 for name, var_docs in groups:
738 if name:
739 out('\\multicolumn{2}{|l|}{')
740 out('\\textbf{%s}}\\\\\n' % name)
741 out('\\cline{1-2}\n')
742 for var_doc in var_docs:
743 if isinstance(var_doc, PropertyDoc):
744 self.write_property_list_line(out, var_doc)
745 else:
746 self.write_var_list_line(out, var_doc)
747
748
749
750
751
752 out('\\end{longtable}\n\n')
753
755 out('\\raggedright ')
756 out(plaintext_to_latex(var_doc.name, nbsp=True, breakany=True))
757 out(' & ')
758 has_descr = var_doc.descr not in (None, UNKNOWN)
759 has_type = var_doc.type_descr not in (None, UNKNOWN)
760 has_repr = (var_doc.value not in (None, UNKNOWN) and
761 (var_doc.value.parse_repr is not UNKNOWN or
762 var_doc.value.pyval_repr() is not UNKNOWN))
763 if has_descr or has_type:
764 out('\\raggedright ')
765 if has_descr:
766 out(self.docstring_to_latex(var_doc.descr, 10).strip())
767 if has_type or has_repr: out('\n\n')
768 if has_repr:
769 out('\\textbf{Value:} \n')
770 pyval_repr = var_doc.value.pyval_repr()
771 if pyval_repr is not UNKNOWN:
772 out(self._pprint_var_value(pyval_repr, 80))
773 elif var_doc.value.parse_repr is not UNKNOWN:
774 out(self._pprint_var_value(var_doc.value.parse_repr, 80))
775 if has_type:
776 ptype = self.docstring_to_latex(var_doc.type_descr, 12).strip()
777 out('%s\\textit{(type=%s)}' % (' '*12, ptype))
778 out('&\\\\\n')
779 out('\\cline{1-2}\n')
780
782 if len(s) > maxwidth: s = s[:maxwidth-3] + '...'
783 if '\n' in s:
784 return ('\\begin{alltt}\n%s\\end{alltt}' %
785 plaintext_to_latex(s, nbsp=False, breakany=True))
786 else:
787 return '{\\tt %s}' % plaintext_to_latex(s, nbsp=True,
788 breakany=True)
789
791 prop_doc = var_doc.value
792 out('\\raggedright ')
793 out(plaintext_to_latex(var_doc.name, nbsp=True, breakany=True))
794 out(' & ')
795 has_descr = prop_doc.descr not in (None, UNKNOWN)
796 has_type = prop_doc.type_descr not in (None, UNKNOWN)
797 if has_descr or has_type:
798 out('\\raggedright ')
799 if has_descr:
800 out(self.docstring_to_latex(prop_doc.descr, 10).strip())
801 if has_type: out('\n\n')
802 if has_type:
803 ptype = self.docstring_to_latex(prop_doc.type_descr, 12).strip()
804 out('%s\\textit{(type=%s)}' % (' '*12, ptype))
805
806 out('&\\\\\n')
807 out('\\cline{1-2}\n')
808
809
810
811
812
813
815 fields = []
816 field_values = {}
817
818
819
820 for (field, arg, descr) in doc.metadata:
821 if field not in field_values:
822 fields.append(field)
823 if field.takes_arg:
824 subfields = field_values.setdefault(field,{})
825 subfields.setdefault(arg,[]).append(descr)
826 else:
827 field_values.setdefault(field,[]).append(descr)
828
829 for field in fields:
830 if field.takes_arg:
831 for arg, descrs in field_values[field].items():
832 self.write_standard_field(out, doc, field, descrs, arg)
833
834 else:
835 self.write_standard_field(out, doc, field, field_values[field])
836
838 singular = field.singular
839 plural = field.plural
840 if arg:
841 singular += ' (%s)' % arg
842 plural += ' (%s)' % arg
843 out(self._descrlist([self.docstring_to_latex(d) for d in descrs],
844 field.singular, field.plural, field.short))
845
846 - def _descrlist(self, items, singular, plural=None, short=0):
847 if plural is None: plural = singular
848 if len(items) == 0: return ''
849 if len(items) == 1 and singular is not None:
850 return '\\textbf{%s:} %s\n\n' % (singular, items[0])
851 if short:
852 s = '\\textbf{%s:}\n' % plural
853 items = [item.strip() for item in items]
854 return s + ',\n '.join(items) + '\n\n'
855 else:
856 s = '\\textbf{%s:}\n' % plural
857 s += '\\begin{quote}\n'
858 s += ' \\begin{itemize}\n\n \item\n'
859 s += ' \\setlength{\\parskip}{0.6ex}\n'
860 s += '\n\n \item '.join(items)
861 return s + '\n\n\\end{itemize}\n\n\\end{quote}\n\n'
862
863
864
865
866
867
868
871 indexstr = re.sub(r'["!|@]', r'"\1', indexterm.to_latex(self))
872 return ('\\index{%s}\\textit{%s}' % (indexstr, indexstr))
876 _docstring_linker = _LatexDocstringLinker()
877
882
883
884
885
886
888 out('%\n% API Documentation')
889 if self._prj_name: out(' for %s' % self._prj_name)
890 if isinstance(where, APIDoc):
891 out('\n%% %s %s' % (self.doc_kind(where), where.canonical_name))
892 else:
893 out('\n%% %s' % where)
894 out('\n%%\n%% Generated by epydoc %s\n' % epydoc.__version__)
895 out('%% [%s]\n%%\n' % time.asctime(time.localtime(time.time())))
896
898 out('\n' + 75*'%' + '\n')
899 out('%%' + ((71-len(section_name))/2)*' ')
900 out(section_name)
901 out(((72-len(section_name))/2)*' ' + '%%\n')
902 out(75*'%' + '\n\n')
903
904 - def section(self, title, depth=0):
907
911
913 if isinstance(doc, ModuleDoc) and doc.is_package == True:
914 return 'Package'
915 elif (isinstance(doc, ModuleDoc) and
916 doc.canonical_name[0].startswith('script')):
917 return 'Script'
918 elif isinstance(doc, ModuleDoc):
919 return 'Module'
920 elif isinstance(doc, ClassDoc):
921 return 'Class'
922 elif isinstance(doc, ClassMethodDoc):
923 return 'Class Method'
924 elif isinstance(doc, StaticMethodDoc):
925 return 'Static Method'
926 elif isinstance(doc, RoutineDoc):
927 if isinstance(self.docindex.container(doc), ClassDoc):
928 return 'Method'
929 else:
930 return 'Function'
931 else:
932 return 'Variable'
933
935 """Mark a term or section for inclusion in the index."""
936 if not self._index: return ''
937 if isinstance(doc, RoutineDoc) and not self._index_functions:
938 return ''
939
940 pieces = []
941 while doc is not None:
942 if doc.canonical_name == UNKNOWN:
943 return ''
944 pieces.append('%s \\textit{(%s)}' %
945 (plaintext_to_latex('%s'%doc.canonical_name),
946 self.doc_kind(doc).lower()))
947 doc = self.docindex.container(doc)
948 if doc == UNKNOWN:
949 return ''
950
951 pieces.reverse()
952 if pos == 'only':
953 return '\\index{%s}\n' % '!'.join(pieces)
954 elif pos == 'start':
955 return '\\index{%s|(}\n' % '!'.join(pieces)
956 elif pos == 'end':
957 return '\\index{%s|)}\n' % '!'.join(pieces)
958 else:
959 raise AssertionError('Bad index position %s' % pos)
960
963