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