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