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 "\\setlength{\\parskip}{2ex}",
42
43 "\\setlength{\\fboxrule}{2\\fboxrule}",
44
45 "\\newlength{\\BCL} % base class length, for base trees.",
46
47 "\\pagestyle{fancy}",
48 "\\renewcommand{\\sectionmark}[1]{\\markboth{#1}{}}",
49 "\\renewcommand{\\subsectionmark}[1]{\\markright{#1}}",
50
51 "\\definecolor{py@keywordcolour}{rgb}{1,0.45882,0}",
52 "\\definecolor{py@stringcolour}{rgb}{0,0.666666,0}",
53 "\\definecolor{py@commentcolour}{rgb}{1,0,0}",
54 "\\definecolor{py@ps1colour}{rgb}{0.60784,0,0}",
55 "\\definecolor{py@ps2colour}{rgb}{0.60784,0,1}",
56 "\\definecolor{py@inputcolour}{rgb}{0,0,0}",
57 "\\definecolor{py@outputcolour}{rgb}{0,0,1}",
58 "\\definecolor{py@exceptcolour}{rgb}{1,0,0}",
59 "\\definecolor{py@defnamecolour}{rgb}{1,0.5,0.5}",
60 "\\definecolor{py@builtincolour}{rgb}{0.58039,0,0.58039}",
61 "\\definecolor{py@identifiercolour}{rgb}{0,0,0}",
62 "\\definecolor{py@linenumcolour}{rgb}{0.4,0.4,0.4}",
63 "\\definecolor{py@inputcolour}{rgb}{0,0,0}",
64 "% Prompt",
65 "\\newcommand{\\pysrcprompt}[1]{\\textcolor{py@ps1colour}"
66 "{\\small\\textbf{#1}}}",
67 "\\newcommand{\\pysrcmore}[1]{\\textcolor{py@ps2colour}"
68 "{\\small\\textbf{#1}}}",
69 "% Source code",
70 "\\newcommand{\\pysrckeyword}[1]{\\textcolor{py@keywordcolour}"
71 "{\\small\\textbf{#1}}}",
72 "\\newcommand{\\pysrcbuiltin}[1]{\\textcolor{py@builtincolour}"
73 "{\\small\\textbf{#1}}}",
74 "\\newcommand{\\pysrcstring}[1]{\\textcolor{py@stringcolour}"
75 "{\\small\\textbf{#1}}}",
76 "\\newcommand{\\pysrcdefname}[1]{\\textcolor{py@defnamecolour}"
77 "{\\small\\textbf{#1}}}",
78 "\\newcommand{\\pysrcother}[1]{\\small\\textbf{#1}}",
79 "% Comments",
80 "\\newcommand{\\pysrccomment}[1]{\\textcolor{py@commentcolour}"
81 "{\\small\\textbf{#1}}}",
82 "% Output",
83 "\\newcommand{\\pysrcoutput}[1]{\\textcolor{py@outputcolour}"
84 "{\\small\\textbf{#1}}}",
85 "% Exceptions",
86 "\\newcommand{\\pysrcexcept}[1]{\\textcolor{py@exceptcolour}"
87 "{\\small\\textbf{#1}}}",
88
89 "\\newlength{\\funcindent}",
90 "\\newlength{\\funcwidth}",
91 "\\setlength{\\funcindent}{1cm}",
92 "\\setlength{\\funcwidth}{\\textwidth}",
93 "\\addtolength{\\funcwidth}{-2\\funcindent}",
94
95 "\\newlength{\\varindent}",
96 "\\newlength{\\varnamewidth}",
97 "\\newlength{\\vardescrwidth}",
98 "\\newlength{\\varwidth}",
99 "\\setlength{\\varindent}{1cm}",
100 "\\setlength{\\varnamewidth}{.3\\textwidth}",
101 "\\setlength{\\varwidth}{\\textwidth}",
102 "\\addtolength{\\varwidth}{-4\\tabcolsep}",
103 "\\addtolength{\\varwidth}{-3\\arrayrulewidth}",
104 "\\addtolength{\\varwidth}{-2\\varindent}",
105 "\\setlength{\\vardescrwidth}{\\varwidth}",
106 "\\addtolength{\\vardescrwidth}{-\\varnamewidth}",
107
108 textwrap.dedent("""\
109 \\newenvironment{Ventry}[1]%
110 {\\begin{list}{}{%
111 \\renewcommand{\\makelabel}[1]{\\texttt{##1:}\\hfil}%
112 \\settowidth{\\labelwidth}{\\texttt{#1:}}%
113 \\setlength{\\leftmargin}{\\labelsep}%
114 \\addtolength{\\leftmargin}{\\labelwidth}}}%
115 {\\end{list}}"""),
116 ]
117
118 HRULE = '\\rule{\\textwidth}{0.5\\fboxrule}\n\n'
119
120 SECTIONS = ['\\part{%s}', '\\chapter{%s}', '\\section{%s}',
121 '\\subsection{%s}', '\\subsubsection{%s}',
122 '\\textbf{%s}']
123
124 STAR_SECTIONS = ['\\part*{%s}', '\\chapter*{%s}', '\\section*{%s}',
125 '\\subsection*{%s}', '\\subsubsection*{%s}',
126 '\\textbf{%s}']
127
128 - def __init__(self, docindex, **kwargs):
129 self.docindex = docindex
130
131 self._show_private = kwargs.get('private', 0)
132 self._prj_name = kwargs.get('prj_name', None) or 'API Documentation'
133 self._crossref = kwargs.get('crossref', 1)
134 self._index = kwargs.get('index', 1)
135 self._list_classes_separately=kwargs.get('list_classes_separately',0)
136 self._inheritance = kwargs.get('inheritance', 'listed')
137 self._exclude = kwargs.get('exclude', 1)
138 self._top_section = 2
139 self._index_functions = 1
140 self._hyperref = 1
141
142
143
144
145 self._encoding = kwargs.get('encoding', 'utf-8')
146
147 self.valdocs = valdocs = sorted(docindex.reachable_valdocs(
148 imports=False, packages=False, bases=False, submodules=False,
149 subclasses=False, private=self._show_private))
150 self._num_files = self.num_files()
151
152 if self._show_private: self._public_filter = None
153 else: self._public_filter = True
154
155 self.class_list = [d for d in valdocs if isinstance(d, ClassDoc)]
156 """The list of L{ClassDoc}s for the documented classes."""
157 self.class_set = set(self.class_list)
158 """The set of L{ClassDoc}s for the documented classes."""
159
160 - def write(self, directory=None):
161 """
162 Write the API documentation for the entire project to the
163 given directory.
164
165 @type directory: C{string}
166 @param directory: The directory to which output should be
167 written. If no directory is specified, output will be
168 written to the current directory. If the directory does
169 not exist, it will be created.
170 @rtype: C{None}
171 @raise OSError: If C{directory} cannot be created,
172 @raise OSError: If any file cannot be created or written to.
173 """
174
175 self._files_written = 0.
176
177
178 orig_valdoc_defaults = (ValueDoc.SUMMARY_REPR_LINELEN,
179 ValueDoc.REPR_LINELEN,
180 ValueDoc.REPR_MAXLINES)
181 ValueDoc.SUMMARY_REPR_LINELEN = 60
182 ValueDoc.REPR_LINELEN = 52
183 ValueDoc.REPR_MAXLINES = 5
184
185
186 if not directory: directory = os.curdir
187 self._mkdir(directory)
188 self._directory = directory
189
190
191 self._write(self.write_topfile, directory, 'api.tex')
192
193
194 for val_doc in self.valdocs:
195 if isinstance(val_doc, ModuleDoc):
196 filename = '%s-module.tex' % val_doc.canonical_name
197 self._write(self.write_module, directory, filename, val_doc)
198 elif (isinstance(val_doc, ClassDoc) and
199 self._list_classes_separately):
200 filename = '%s-class.tex' % val_doc.canonical_name
201 self._write(self.write_class, directory, filename, val_doc)
202
203
204 (ValueDoc.SUMMARY_REPR_LINELEN, ValueDoc.REPR_LINELEN,
205 ValueDoc.REPR_MAXLINES) = orig_valdoc_defaults
206
207 - def _write(self, write_func, directory, filename, *args):
208
209 self._files_written += 1
210 log.progress(self._files_written/self._num_files, filename)
211
212 path = os.path.join(directory, filename)
213 if self._encoding == 'utf-8':
214 f = codecs.open(path, 'w', 'utf-8')
215 write_func(f.write, *args)
216 f.close()
217 else:
218 result = []
219 write_func(result.append, *args)
220 s = u''.join(result)
221 try:
222 s = s.encode(self._encoding)
223 except UnicodeError:
224 log.error("Output could not be represented with the "
225 "given encoding (%r). Unencodable characters "
226 "will be displayed as '?'. It is recommended "
227 "that you use a different output encoding (utf-8, "
228 "if it's supported by latex on your system)."
229 % self._encoding)
230 s = s.encode(self._encoding, 'replace')
231 f = open(path, 'w')
232 f.write(s)
233 f.close()
234
236 """
237 @return: The number of files that this C{LatexFormatter} will
238 generate.
239 @rtype: C{int}
240 """
241 n = 1
242 for doc in self.valdocs:
243 if isinstance(doc, ModuleDoc): n += 1
244 if isinstance(doc, ClassDoc) and self._list_classes_separately:
245 n += 1
246 return n
247
249 """
250 If the given directory does not exist, then attempt to create it.
251 @rtype: C{None}
252 """
253 if not os.path.isdir(directory):
254 if os.path.exists(directory):
255 raise OSError('%r is not a directory' % directory)
256 os.mkdir(directory)
257
258
259
260
261
263 self.write_header(out, 'Include File')
264 self.write_preamble(out)
265 out('\n\\begin{document}\n\n')
266 self.write_start_of(out, 'Header')
267
268
269 self.write_start_of(out, 'Title')
270 out('\\title{%s}\n' % plaintext_to_latex(self._prj_name, 1))
271 out('\\author{API Documentation}\n')
272 out('\\maketitle\n')
273
274
275 self.write_start_of(out, 'Table of Contents')
276 out('\\addtolength{\\parskip}{-2ex}\n')
277 out('\\tableofcontents\n')
278 out('\\addtolength{\\parskip}{2ex}\n')
279
280
281 self.write_start_of(out, 'Includes')
282 for val_doc in self.valdocs:
283 if isinstance(val_doc, ModuleDoc):
284 out('\\include{%s-module}\n' % val_doc.canonical_name)
285
286
287
288 if self._list_classes_separately:
289 for val_doc in self.valdocs:
290 if isinstance(val_doc, ClassDoc):
291 out('\\include{%s-class}\n' % val_doc.canonical_name)
292
293
294 if self._index:
295 self.write_start_of(out, 'Index')
296 out('\\printindex\n\n')
297
298
299 self.write_start_of(out, 'Footer')
300 out('\\end{document}\n\n')
301
303 out('\n'.join(self.PREAMBLE))
304 out('\n')
305
306
307 out('\\usepackage[%s]{inputenc}\n' % self.get_latex_encoding())
308
309
310 if self._hyperref:
311 out('\\definecolor{UrlColor}{rgb}{0,0.08,0.45}\n')
312 out('\\usepackage[dvips, pagebackref, pdftitle={%s}, '
313 'pdfcreator={epydoc %s}, bookmarks=true, '
314 'bookmarksopen=false, pdfpagemode=UseOutlines, '
315 'colorlinks=true, linkcolor=black, anchorcolor=black, '
316 'citecolor=black, filecolor=black, menucolor=black, '
317 'pagecolor=black, urlcolor=UrlColor]{hyperref}\n' %
318 (self._prj_name or '', epydoc.__version__))
319
320
321 if self._index:
322 out("\\makeindex\n")
323
324
325
326 if 'restructuredtext' in epydoc.markup.MARKUP_LANGUAGES_USED:
327 from epydoc.markup import restructuredtext
328 rst_head = restructuredtext.latex_head_prefix()
329 rst_head = ''.join(rst_head).split('\n')
330 for line in rst_head[1:]:
331 m = re.match(r'\\usepackage(\[.*?\])?{(.*?)}', line)
332 if m and m.group(2) in (
333 'babel', 'hyperref', 'color', 'alltt', 'parskip',
334 'fancyhdr', 'boxedminipage', 'makeidx',
335 'multirow', 'longtable', 'tocbind', 'assymb',
336 'fullpage', 'inputenc'):
337 pass
338 else:
339 out(line+'\n')
340
341
342
343
344
345
347 self.write_header(out, doc)
348 self.write_start_of(out, 'Module Description')
349
350
351 out(' ' + self.indexterm(doc, 'start'))
352
353
354 out(self.section('%s %s' % (self.doc_kind(doc),
355 doc.canonical_name)))
356
357
358 out(' \\label{%s}\n' % self.label(doc))
359
360
361 if doc.descr not in (None, UNKNOWN):
362 out(self.docstring_to_latex(doc.descr))
363
364
365 self.write_standard_fields(out, doc)
366
367
368 if doc.submodules != UNKNOWN and doc.submodules:
369 self.write_module_list(out, doc)
370
371
372 if self._list_classes_separately:
373 self.write_class_list(out, doc)
374 self.write_func_list(out, 'Functions', doc, 'function')
375 self.write_var_list(out, 'Variables', doc, 'other')
376
377
378 if not self._list_classes_separately:
379 classes = doc.select_variables(imported=False, value_type='class',
380 public=self._public_filter)
381 for var_doc in classes:
382 self.write_class(out, var_doc.value)
383
384
385 out(' ' + self.indexterm(doc, 'end'))
386
388 if self._list_classes_separately:
389 self.write_header(out, doc)
390 self.write_start_of(out, 'Class Description')
391
392
393 out(' ' + self.indexterm(doc, 'start'))
394
395
396 if self._list_classes_separately:
397 seclevel = 0
398 out(self.section('%s %s' % (self.doc_kind(doc),
399 doc.canonical_name), seclevel))
400 else:
401 seclevel = 1
402 out(self.section('%s %s' % (self.doc_kind(doc),
403 doc.canonical_name[-1]), seclevel))
404
405
406 out(' \\label{%s}\n' % self.label(doc))
407
408
409 if doc.bases not in (UNKNOWN, None) and len(doc.bases) > 0:
410 out(self.base_tree(doc))
411
412
413 if doc.subclasses not in (UNKNOWN, None) and len(doc.subclasses) > 0:
414 sc_items = [plaintext_to_latex('%s' % sc.canonical_name)
415 for sc in doc.subclasses]
416 out(self._descrlist(sc_items, 'Known Subclasses', short=1))
417
418
419 if doc.descr not in (None, UNKNOWN):
420 out(self.docstring_to_latex(doc.descr))
421
422
423 self.write_standard_fields(out, doc)
424
425
426 self.write_func_list(out, 'Methods', doc, 'method',
427 seclevel+1)
428 self.write_var_list(out, 'Properties', doc,
429 'property', seclevel+1)
430 self.write_var_list(out, 'Class Variables', doc,
431 'classvariable', seclevel+1)
432 self.write_var_list(out, 'Instance Variables', doc,
433 'instancevariable', seclevel+1)
434
435
436 out(' ' + self.indexterm(doc, 'end'))
437
438
439
440
441
443 modules = [doc for doc in self.valdocs
444 if isinstance(doc, ModuleDoc)]
445 if not modules: return
446
447
448 out('\\begin{itemize}\n')
449 out('\\setlength{\\parskip}{0ex}\n')
450 for doc in modules:
451 if (doc.package in (None, UNKNOWN) or
452 doc.package not in self.valdocs):
453 self.write_module_tree_item(out, doc)
454 return s +'\\end{itemize}\n'
455
457 if len(doc.submodules) == 0: return
458 self.write_start_of(out, 'Modules')
459
460 out(self.section('Modules', 1))
461 out('\\begin{itemize}\n')
462 out('\\setlength{\\parskip}{0ex}\n')
463
464 for group_name in doc.group_names():
465 if not doc.submodule_groups[group_name]: continue
466 if group_name:
467 out(' \\item \\textbf{%s}\n' % group_name)
468 out(' \\begin{itemize}\n')
469 for submodule in doc.submodule_groups[group_name]:
470 self.write_module_tree_item(out, submodule)
471 if group_name:
472 out(' \end{itemize}\n')
473
474 out('\\end{itemize}\n\n')
475
477 """
478 Helper function for L{write_module_tree} and L{write_module_list}.
479
480 @rtype: C{string}
481 """
482 out(' '*depth + '\\item \\textbf{')
483 out(plaintext_to_latex(doc.canonical_name[-1]) +'}')
484 if doc.summary not in (None, UNKNOWN):
485 out(': %s\n' % self.docstring_to_latex(doc.summary))
486 if self._crossref:
487 out('\n \\textit{(Section \\ref{%s}' % self.label(doc))
488 out(', p.~\\pageref{%s})}\n\n' % self.label(doc))
489 if doc.submodules != UNKNOWN and doc.submodules:
490 out(' '*depth + ' \\begin{itemize}\n')
491 out(' '*depth + '\\setlength{\\parskip}{0ex}\n')
492 for submodule in doc.submodules:
493 self.write_module_tree_item(out, submodule, depth+4)
494 out(' '*depth + ' \\end{itemize}\n')
495
496
497
498
499
500 - def base_tree(self, doc, width=None, linespec=None):
501 if width is None:
502 width = self._find_tree_width(doc)+2
503 linespec = []
504 s = ('&'*(width-4)+'\\multicolumn{2}{l}{\\textbf{%s}}\n' %
505 plaintext_to_latex('%s'%self._base_name(doc)))
506 s += '\\end{tabular}\n\n'
507 top = 1
508 else:
509 s = self._base_tree_line(doc, width, linespec)
510 top = 0
511
512 if isinstance(doc, ClassDoc):
513 for i in range(len(doc.bases)-1, -1, -1):
514 base = doc.bases[i]
515 spec = (i > 0)
516 s = self.base_tree(base, width, [spec]+linespec) + s
517
518 if top:
519 s = '\\begin{tabular}{%s}\n' % (width*'c') + s
520
521 return s
522
531
533 if not isinstance(doc, ClassDoc): return 2
534 width = 2
535 for base in doc.bases:
536 width = max(width, self._find_tree_width(base)+2)
537 return width
538
540 base_name = plaintext_to_latex(self._base_name(doc))
541
542
543 s = '%% Line for %s, linespec=%s\n' % (base_name, linespec)
544
545 labelwidth = width-2*len(linespec)-2
546
547
548 s += ('\\multicolumn{%s}{r}{' % labelwidth)
549 s += '\\settowidth{\\BCL}{%s}' % base_name
550 s += '\\multirow{2}{\\BCL}{%s}}\n' % base_name
551
552
553 for vbar in linespec:
554 if vbar: s += '&&\\multicolumn{1}{|c}{}\n'
555 else: s += '&&\n'
556
557
558 s += ' \\\\\\cline{%s-%s}\n' % (labelwidth+1, labelwidth+1)
559
560
561 s += ' ' + '&'*labelwidth
562 s += '\\multicolumn{1}{c|}{}\n'
563
564
565 for vbar in linespec:
566 if vbar: s += '&\\multicolumn{1}{|c}{}&\n'
567 else: s += '&&\n'
568 s += ' \\\\\n'
569
570 return s
571
572
573
574
575
577 groups = [(plaintext_to_latex(group_name),
578 doc.select_variables(group=group_name, imported=False,
579 value_type='class',
580 public=self._public_filter))
581 for group_name in doc.group_names()]
582
583
584 groups = [(g,vars) for (g,vars) in groups if vars]
585 if not groups: return
586
587
588 self.write_start_of(out, 'Classes')
589 out(self.section('Classes', 1))
590 out('\\begin{itemize}')
591 out(' \\setlength{\\parskip}{0ex}\n')
592
593 for name, var_docs in groups:
594 if name:
595 out(' \\item \\textbf{%s}\n' % name)
596 out(' \\begin{itemize}\n')
597
598 for var_doc in var_docs:
599 self.write_class_list_line(out, var_doc)
600 if name:
601 out(' \\end{itemize}\n')
602
603 out('\\end{itemize}\n')
604
615
616
617
618
619 _FUNC_GROUP_HEADER = '\n\\large{\\textbf{\\textit{%s}}}\n\n'
620
622
623 groups = [(plaintext_to_latex(group_name),
624 doc.select_variables(group=group_name, imported=False,
625 value_type=value_type,
626 public=self._public_filter))
627 for group_name in doc.group_names()]
628
629
630 groups = [(g,vars) for (g,vars) in groups if vars]
631 if not groups: return
632
633
634 self.write_start_of(out, heading)
635 out(' '+self.section(heading, seclevel))
636
637
638 grouped_inh_vars = {}
639 for name, var_docs in groups:
640 self.write_func_group(out, doc, name, var_docs, grouped_inh_vars)
641
642
643
644 if grouped_inh_vars:
645 for base in doc.mro():
646 if base in grouped_inh_vars:
647 hdr = ('Inherited from %s' %
648 plaintext_to_latex('%s' % base.canonical_name))
649 if self._crossref and base in self.class_set:
650 hdr += ('\\textit{(Section \\ref{%s})}' %
651 self.label(base))
652 out(self._FUNC_GROUP_HEADER % (hdr))
653 for var_doc in grouped_inh_vars[base]:
654 self.write_func_list_box(out, var_doc)
655
657
658
659
660
661
662 listed_inh_vars = {}
663 normal_vars = []
664 for var_doc in var_docs:
665 if var_doc.container != doc:
666 base = var_doc.container
667 if (base not in self.class_set or
668 self._inheritance == 'listed'):
669 listed_inh_vars.setdefault(base,[]).append(var_doc)
670 elif self._inheritance == 'grouped':
671 grouped_inh_vars.setdefault(base,[]).append(var_doc)
672 else:
673 normal_vars.append(var_doc)
674 else:
675 normal_vars.append(var_doc)
676
677
678 if name:
679 out(self._FUNC_GROUP_HEADER % name)
680
681 for var_doc in normal_vars:
682 self.write_func_list_box(out, var_doc)
683
684 if listed_inh_vars:
685 self.write_func_inheritance_list(out, doc, listed_inh_vars)
686
688 for base in doc.mro():
689 if base not in listed_inh_vars: continue
690
691 var_docs = listed_inh_vars[base]
692 if self._public_filter:
693 var_docs = [v for v in var_docs if v.is_public]
694 if var_docs:
695 hdr = ('Inherited from %s' %
696 plaintext_to_latex('%s' % base.canonical_name))
697 if self._crossref and base in self.class_set:
698 hdr += ('\\textit{(Section \\ref{%s})}' %
699 self.label(base))
700 out(self._FUNC_GROUP_HEADER % hdr)
701 out('\\begin{quote}\n')
702 out('%s\n' % ', '.join(
703 ['%s()' % plaintext_to_latex(var_doc.name)
704 for var_doc in var_docs]))
705 out('\\end{quote}\n')
706
708 func_doc = var_doc.value
709 is_inherited = (var_doc.overrides not in (None, UNKNOWN))
710
711
712
713 if not is_inherited:
714 out(' \\label{%s}\n' % self.label(func_doc))
715 out(' %s\n' % self.indexterm(func_doc))
716
717
718 out(' \\vspace{0.5ex}\n\n')
719 out('\\hspace{.8\\funcindent}')
720 out('\\begin{boxedminipage}{\\funcwidth}\n\n')
721
722
723 out(' %s\n\n' % self.function_signature(var_doc))
724
725 if (func_doc.docstring not in (None, UNKNOWN) and
726 func_doc.docstring.strip() != ''):
727 out(' \\vspace{-1.5ex}\n\n')
728 out(' \\rule{\\textwidth}{0.5\\fboxrule}\n')
729
730
731 out("\\setlength{\\parskip}{2ex}\n")
732 if func_doc.descr not in (None, UNKNOWN):
733 out(self.docstring_to_latex(func_doc.descr, 4))
734
735
736 out("\\setlength{\\parskip}{1ex}\n")
737 if func_doc.arg_descrs or func_doc.arg_types:
738
739 longest = max([0]+[len(n) for n in func_doc.arg_types])
740 for names, descrs in func_doc.arg_descrs:
741 longest = max([longest]+[len(n) for n in names])
742
743 out(' '*6+'\\textbf{Parameters}\n')
744 out(' \\vspace{-1ex}\n\n')
745 out(' '*6+'\\begin{quote}\n')
746 out(' \\begin{Ventry}{%s}\n\n' % (longest*'x'))
747
748 arg_descrs = list(func_doc.arg_descrs)
749 args = set()
750 for arg_names, arg_descr in arg_descrs:
751 args.update(arg_names)
752 for arg in var_doc.value.arg_types:
753 if arg not in args:
754 arg_descrs.append( ([arg],None) )
755
756 for (arg_names, arg_descr) in arg_descrs:
757 arg_name = plaintext_to_latex(', '.join(arg_names))
758 out('%s\\item[%s]\n\n' % (' '*10, arg_name))
759 if arg_descr:
760 out(self.docstring_to_latex(arg_descr, 10))
761 for arg_name in arg_names:
762 arg_typ = func_doc.arg_types.get(arg_name)
763 if arg_typ is not None:
764 if len(arg_names) == 1:
765 lhs = 'type'
766 else:
767 lhs = 'type of %s' % arg_name
768 rhs = self.docstring_to_latex(arg_typ).strip()
769 out('%s{\\it (%s=%s)}\n\n' % (' '*12, lhs, rhs))
770 out(' \\end{Ventry}\n\n')
771 out(' '*6+'\\end{quote}\n\n')
772
773
774 rdescr = func_doc.return_descr
775 rtype = func_doc.return_type
776 if rdescr not in (None, UNKNOWN) or rtype not in (None, UNKNOWN):
777 out(' '*6+'\\textbf{Return Value}\n')
778 out(' \\vspace{-1ex}\n\n')
779 out(' '*6+'\\begin{quote}\n')
780 if rdescr not in (None, UNKNOWN):
781 out(self.docstring_to_latex(rdescr, 6))
782 if rtype not in (None, UNKNOWN):
783 out(' '*6+'{\\it (type=%s)}\n\n' %
784 self.docstring_to_latex(rtype, 6).strip())
785 elif rtype not in (None, UNKNOWN):
786 out(self.docstring_to_latex(rtype, 6))
787 out(' '*6+'\\end{quote}\n\n')
788
789
790 if func_doc.exception_descrs not in (None, UNKNOWN, [], ()):
791 out(' '*6+'\\textbf{Raises}\n')
792 out(' \\vspace{-1ex}\n\n')
793 out(' '*6+'\\begin{quote}\n')
794 out(' \\begin{description}\n\n')
795 for name, descr in func_doc.exception_descrs:
796 out(' '*10+'\\item[\\texttt{%s}]\n\n' %
797 plaintext_to_latex('%s' % name))
798 out(self.docstring_to_latex(descr, 10))
799 out(' \\end{description}\n\n')
800 out(' '*6+'\\end{quote}\n\n')
801
802
803 if var_doc.overrides not in (None, UNKNOWN):
804 out(' Overrides: ' +
805 plaintext_to_latex('%s'%var_doc.overrides.canonical_name))
806 if (func_doc.docstring in (None, UNKNOWN) and
807 var_doc.overrides.value.docstring not in (None, UNKNOWN)):
808 out(' \textit{(inherited documentation)}')
809 out('\n\n')
810
811
812 self.write_standard_fields(out, func_doc)
813
814 out(' \\end{boxedminipage}\n\n')
815
841
847
849 if isinstance(arg, basestring):
850 return arg
851 elif len(arg) == 1:
852 return '(%s,)' % self._arg_name(arg[0])
853 else:
854 return '(%s)' % (', '.join([self._arg_name(a) for a in arg]))
855
856
857
858
859 _VAR_GROUP_HEADER = '\\multicolumn{2}{|l|}{\\textit{%s}}\\\\\n'
860
861
863 groups = [(plaintext_to_latex(group_name),
864 doc.select_variables(group=group_name, imported=False,
865 value_type=value_type,
866 public=self._public_filter))
867 for group_name in doc.group_names()]
868
869
870 groups = [(g,vars) for (g,vars) in groups if vars]
871 if not groups: return
872
873
874 self.write_start_of(out, heading)
875 out(' '+self.section(heading, seclevel))
876
877
878 out(' \\vspace{-1cm}\n')
879
880 out('\\hspace{\\varindent}')
881 out('\\begin{longtable}')
882 out('{|p{\\varnamewidth}|')
883 out('p{\\vardescrwidth}|l}\n')
884 out('\\cline{1-2}\n')
885
886
887
888 out('\\cline{1-2} ')
889 out('\\centering \\textbf{Name} & ')
890 out('\\centering \\textbf{Description}& \\\\\n')
891 out('\\cline{1-2}\n')
892 out('\\endhead')
893 out('\\cline{1-2}')
894 out('\\multicolumn{3}{r}{\\small\\textit{')
895 out('continued on next page}}\\\\')
896 out('\\endfoot')
897 out('\\cline{1-2}\n')
898 out('\\endlastfoot')
899
900
901 grouped_inh_vars = {}
902 for name, var_docs in groups:
903 self.write_var_group(out, doc, name, var_docs, grouped_inh_vars)
904
905
906
907 if grouped_inh_vars:
908 for base in doc.mro():
909 if base in grouped_inh_vars:
910 hdr = ('Inherited from %s' %
911 plaintext_to_latex('%s' % base.canonical_name))
912 if self._crossref and base in self.class_set:
913 hdr += (' \\textit{(Section \\ref{%s})}' %
914 self.label(base))
915 out(self._VAR_GROUP_HEADER % (hdr))
916 out('\\cline{1-2}\n')
917 for var_doc in grouped_inh_vars[base]:
918 if isinstance(var_doc.value3, PropertyDoc):
919 self.write_property_list_line(out, var_doc)
920 else:
921 self.write_var_list_line(out, var_doc)
922
923 out('\\end{longtable}\n\n')
924
926
927
928
929
930
931 listed_inh_vars = {}
932 normal_vars = []
933 for var_doc in var_docs:
934 if var_doc.container != doc:
935 base = var_doc.container
936 if (base not in self.class_set or
937 self._inheritance == 'listed'):
938 listed_inh_vars.setdefault(base,[]).append(var_doc)
939 elif self._inheritance == 'grouped':
940 grouped_inh_vars.setdefault(base,[]).append(var_doc)
941 else:
942 normal_vars.append(var_doc)
943 else:
944 normal_vars.append(var_doc)
945
946
947 if name:
948 out(self._VAR_GROUP_HEADER % name)
949 out('\\cline{1-2}\n')
950
951 for var_doc in normal_vars:
952 if isinstance(var_doc.value, PropertyDoc):
953 self.write_property_list_line(out, var_doc)
954 else:
955 self.write_var_list_line(out, var_doc)
956
957 if listed_inh_vars:
958 self.write_var_inheritance_list(out, doc, listed_inh_vars)
959
961 for base in doc.mro():
962 if base not in listed_inh_vars: continue
963
964 var_docs = listed_inh_vars[base]
965 if self._public_filter:
966 var_docs = [v for v in var_docs if v.is_public]
967 if var_docs:
968 hdr = ('Inherited from %s' %
969 plaintext_to_latex('%s' % base.canonical_name))
970 if self._crossref and base in self.class_set:
971 hdr += (' \\textit{(Section \\ref{%s})}' %
972 self.label(base))
973 out(self._VAR_GROUP_HEADER % hdr)
974 out('\\multicolumn{2}{|p{\\varwidth}|}{'
975 '\\raggedright %s}\\\\\n' %
976 ', '.join(['%s' % plaintext_to_latex(var_doc.name)
977 for var_doc in var_docs]))
978 out('\\cline{1-2}\n')
979
980
982 out('\\raggedright ')
983 out(plaintext_to_latex(var_doc.name, nbsp=True, breakany=True))
984 out(' & ')
985 has_descr = var_doc.descr not in (None, UNKNOWN)
986 has_type = var_doc.type_descr not in (None, UNKNOWN)
987 has_value = var_doc.value is not UNKNOWN
988 if has_type or has_value:
989 out('\\raggedright ')
990 if has_descr:
991 out(self.docstring_to_latex(var_doc.descr, 10).strip())
992 if has_type or has_value: out('\n\n')
993 if has_value:
994 out('\\textbf{Value:} \n{\\tt %s}' %
995 var_doc.value.summary_pyval_repr().to_latex(None))
996 if has_type:
997 ptype = self.docstring_to_latex(var_doc.type_descr, 12).strip()
998 out('%s{\\it (type=%s)}' % (' '*12, ptype))
999 out('&\\\\\n')
1000 out('\\cline{1-2}\n')
1001
1003 prop_doc = var_doc.value
1004 out('\\raggedright ')
1005 out(plaintext_to_latex(var_doc.name, nbsp=True, breakany=True))
1006 out(' & ')
1007 has_descr = prop_doc.descr not in (None, UNKNOWN)
1008 has_type = prop_doc.type_descr not in (None, UNKNOWN)
1009 if has_descr or has_type:
1010 out('\\raggedright ')
1011 if has_descr:
1012 out(self.docstring_to_latex(prop_doc.descr, 10).strip())
1013 if has_type: out('\n\n')
1014 if has_type:
1015 ptype = self.docstring_to_latex(prop_doc.type_descr, 12).strip()
1016 out('%s{\\it (type=%s)}' % (' '*12, ptype))
1017
1018 out('&\\\\\n')
1019 out('\\cline{1-2}\n')
1020
1021
1022
1023
1024
1025
1027 fields = []
1028 field_values = {}
1029
1030
1031
1032 for (field, arg, descr) in doc.metadata:
1033 if field not in field_values:
1034 fields.append(field)
1035 if field.takes_arg:
1036 subfields = field_values.setdefault(field,{})
1037 subfields.setdefault(arg,[]).append(descr)
1038 else:
1039 field_values.setdefault(field,[]).append(descr)
1040
1041 for field in fields:
1042 if field.takes_arg:
1043 for arg, descrs in field_values[field].items():
1044 self.write_standard_field(out, doc, field, descrs, arg)
1045
1046 else:
1047 self.write_standard_field(out, doc, field, field_values[field])
1048
1050 singular = field.singular
1051 plural = field.plural
1052 if arg:
1053 singular += ' (%s)' % arg
1054 plural += ' (%s)' % arg
1055 out(self._descrlist([self.docstring_to_latex(d) for d in descrs],
1056 field.singular, field.plural, field.short))
1057
1058 - def _descrlist(self, items, singular, plural=None, short=0):
1059 if plural is None: plural = singular
1060 if len(items) == 0: return ''
1061 if len(items) == 1 and singular is not None:
1062 return '\\textbf{%s:} %s\n\n' % (singular, items[0])
1063 if short:
1064 s = '\\textbf{%s:}\n' % plural
1065 items = [item.strip() for item in items]
1066 return s + ',\n '.join(items) + '\n\n'
1067 else:
1068 s = '\\textbf{%s:}\n' % plural
1069 s += '\\begin{quote}\n'
1070 s += ' \\begin{itemize}\n\n \item\n'
1071 s += ' \\setlength{\\parskip}{0.6ex}\n'
1072 s += '\n\n \item '.join(items)
1073 return s + '\n\n\\end{itemize}\n\n\\end{quote}\n\n'
1074
1075
1076
1077
1078
1079
1080
1083 indexstr = re.sub(r'["!|@]', r'"\1', indexterm.to_latex(self))
1084 return ('\\index{%s}\\textit{%s}' % (indexstr, indexstr))
1088 _docstring_linker = _LatexDocstringLinker()
1089
1094
1095
1096
1097
1098
1100 out('%\n% API Documentation')
1101 if self._prj_name: out(' for %s' % self._prj_name)
1102 if isinstance(where, APIDoc):
1103 out('\n%% %s %s' % (self.doc_kind(where), where.canonical_name))
1104 else:
1105 out('\n%% %s' % where)
1106 out('\n%%\n%% Generated by epydoc %s\n' % epydoc.__version__)
1107 out('%% [%s]\n%%\n' % time.asctime(time.localtime(time.time())))
1108
1110 out('\n' + 75*'%' + '\n')
1111 out('%%' + ((71-len(section_name))/2)*' ')
1112 out(section_name)
1113 out(((72-len(section_name))/2)*' ' + '%%\n')
1114 out(75*'%' + '\n\n')
1115
1116 - def section(self, title, depth=0):
1119
1123
1125 if isinstance(doc, ModuleDoc) and doc.is_package == True:
1126 return 'Package'
1127 elif (isinstance(doc, ModuleDoc) and
1128 doc.canonical_name[0].startswith('script')):
1129 return 'Script'
1130 elif isinstance(doc, ModuleDoc):
1131 return 'Module'
1132 elif isinstance(doc, ClassDoc):
1133 return 'Class'
1134 elif isinstance(doc, ClassMethodDoc):
1135 return 'Class Method'
1136 elif isinstance(doc, StaticMethodDoc):
1137 return 'Static Method'
1138 elif isinstance(doc, RoutineDoc):
1139 if isinstance(self.docindex.container(doc), ClassDoc):
1140 return 'Method'
1141 else:
1142 return 'Function'
1143 else:
1144 return 'Variable'
1145
1147 """Mark a term or section for inclusion in the index."""
1148 if not self._index: return ''
1149 if isinstance(doc, RoutineDoc) and not self._index_functions:
1150 return ''
1151
1152 pieces = []
1153 while doc is not None:
1154 if doc.canonical_name == UNKNOWN:
1155 return ''
1156 pieces.append('%s \\textit{(%s)}' %
1157 (plaintext_to_latex('%s'%doc.canonical_name),
1158 self.doc_kind(doc).lower()))
1159 doc = self.docindex.container(doc)
1160 if doc == UNKNOWN:
1161 return ''
1162
1163 pieces.reverse()
1164 if pos == 'only':
1165 return '\\index{%s}\n' % '!'.join(pieces)
1166 elif pos == 'start':
1167 return '\\index{%s|(}\n' % '!'.join(pieces)
1168 elif pos == 'end':
1169 return '\\index{%s|)}\n' % '!'.join(pieces)
1170 else:
1171 raise AssertionError('Bad index position %s' % pos)
1172
1175
1176
1177 latex_encodings = {
1178 'utf-8': 'utf8',
1179 }
1180
1182 """
1183 @return: The LaTeX representation of the selected encoding.
1184 @rtype: C{str}
1185 """
1186 enc = self._encoding.lower()
1187 return self.latex_encodings.get(enc, enc)
1188