[Epydoc-commits] SF.net SVN: epydoc: [1734] trunk/epydoc/src/epydoc
Brought to you by:
edloper
From: <ed...@us...> - 2008-02-23 00:55:53
|
Revision: 1734 http://epydoc.svn.sourceforge.net/epydoc/?rev=1734&view=rev Author: edloper Date: 2008-02-22 16:55:52 -0800 (Fri, 22 Feb 2008) Log Message: ----------- - Incorporated (and extended) patches from Jonathan Guyer, to move formatting decisions for the latex writer into a separate stylesheet. The new version is not compatible with Jonathan Guyer's original patch -- I redesigned the interface between epydoc.docwriter.latex and the stylesheet somewhat. At present, three style files are available: 'base', 'boxes', and 'shaded'. 'boxes' resembles the old (3.0) output. Modified Paths: -------------- trunk/epydoc/src/epydoc/cli.py trunk/epydoc/src/epydoc/docwriter/latex.py Added Paths: ----------- trunk/epydoc/src/epydoc/docwriter/latex_sty.py Modified: trunk/epydoc/src/epydoc/cli.py =================================================================== --- trunk/epydoc/src/epydoc/cli.py 2008-02-23 00:52:21 UTC (rev 1733) +++ trunk/epydoc/src/epydoc/cli.py 2008-02-23 00:55:52 UTC (rev 1734) @@ -325,6 +325,11 @@ help="The CSS stylesheet. STYLESHEET can be either a " "builtin stylesheet or the name of a CSS file.") + output_group.add_option("--sty", + dest="sty", metavar="LATEXSTYLE", + help="The LaTeX style file. LATEXSTYLE can be either a " + "builtin style file or the name of a .sty file.") + output_group.add_option("--url", "-u", dest="prj_url", metavar="URL", help="The documented project's URL (for the navigation bar).") @@ -698,13 +703,13 @@ if options.load_pickle: stages = [30] # Loading pickled documentation if 'html' in options.actions: stages += [100] - if 'text' in options.actions: stages += [30] if 'check' in options.actions: stages += [10] if 'pickle' in options.actions: stages += [10] if 'latex' in options.actions: stages += [60] if 'pdf' in options.actions: stages += [50] - elif 'ps' in options.actions: stages += [40] - elif 'dvi' in options.actions: stages += [30] + elif 'ps' in options.actions: stages += [40] # implied by pdf + elif 'dvi' in options.actions: stages += [30] # implied by ps + if 'text' in options.actions: stages += [30] if options.parse and not options.introspect: del stages[1] # no merging @@ -828,13 +833,15 @@ if profile_stats is not None: docindex.read_profiling_info(profile_stats) - # Perform the specified action. + # Perform the specified action. NOTE: It is important that these + # are performed in the same order that the 'stages' list was + # constructed, at the top of this function. + if 'html' in options.actions: + write_html(docindex, options) if 'check' in options.actions: check_docs(docindex, options) if 'pickle' in options.actions: write_pickle(docindex, options) - if 'html' in options.actions: - write_html(docindex, options) if ('latex' in options.actions or 'dvi' in options.actions or 'ps' in options.actions or 'pdf' in options.actions): write_latex(docindex, options) Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2008-02-23 00:52:21 UTC (rev 1733) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2008-02-23 00:55:52 UTC (rev 1734) @@ -23,100 +23,16 @@ from epydoc import markup from epydoc.util import plaintext_to_latex import epydoc.markup +from epydoc.docwriter.dotgraph import * +from epydoc.docwriter.latex_sty import STYLESHEETS class LatexWriter: + #: Expects (options,) PREAMBLE = [ "\\documentclass{article}", - "\\usepackage{alltt, parskip, fancyhdr, boxedminipage}", - "\\usepackage{makeidx, multirow, longtable, tocbibind, amssymb}", - "\\usepackage{fullpage}", - "\\usepackage[usenames]{color}", - # Fix the heading position -- without this, the headings generated - # by the fancyheadings package sometimes overlap the text. - "\\setlength{\\headheight}{16pt}", - "\\setlength{\\headsep}{24pt}", - "\\setlength{\\topmargin}{-\\headsep}", - # By default, do not indent paragraphs. - "\\setlength{\\parindent}{0ex}", - "\\setlength{\\parskip}{2ex}", - # Double the standard size boxedminipage outlines. - "\\setlength{\\fboxrule}{2\\fboxrule}", - # Create a 'base class' length named BCL for use in base trees. - "\\newlength{\\BCL} % base class length, for base trees.", - # Display the section & subsection names in a header. - "\\pagestyle{fancy}", - "\\renewcommand{\\sectionmark}[1]{\\markboth{#1}{}}", - "\\renewcommand{\\subsectionmark}[1]{\\markright{#1}}", - # Colorization for python source code - "\\definecolor{py@keywordcolour}{rgb}{1,0.45882,0}", - "\\definecolor{py@stringcolour}{rgb}{0,0.666666,0}", - "\\definecolor{py@commentcolour}{rgb}{1,0,0}", - "\\definecolor{py@ps1colour}{rgb}{0.60784,0,0}", - "\\definecolor{py@ps2colour}{rgb}{0.60784,0,1}", - "\\definecolor{py@inputcolour}{rgb}{0,0,0}", - "\\definecolor{py@outputcolour}{rgb}{0,0,1}", - "\\definecolor{py@exceptcolour}{rgb}{1,0,0}", - "\\definecolor{py@defnamecolour}{rgb}{1,0.5,0.5}", - "\\definecolor{py@builtincolour}{rgb}{0.58039,0,0.58039}", - "\\definecolor{py@identifiercolour}{rgb}{0,0,0}", - "\\definecolor{py@linenumcolour}{rgb}{0.4,0.4,0.4}", - "\\definecolor{py@inputcolour}{rgb}{0,0,0}", - "% Prompt", - "\\newcommand{\\pysrcprompt}[1]{\\textcolor{py@ps1colour}" - "{\\small\\textbf{#1}}}", - "\\newcommand{\\pysrcmore}[1]{\\textcolor{py@ps2colour}" - "{\\small\\textbf{#1}}}", - "% Source code", - "\\newcommand{\\pysrckeyword}[1]{\\textcolor{py@keywordcolour}" - "{\\small\\textbf{#1}}}", - "\\newcommand{\\pysrcbuiltin}[1]{\\textcolor{py@builtincolour}" - "{\\small\\textbf{#1}}}", - "\\newcommand{\\pysrcstring}[1]{\\textcolor{py@stringcolour}" - "{\\small\\textbf{#1}}}", - "\\newcommand{\\pysrcdefname}[1]{\\textcolor{py@defnamecolour}" - "{\\small\\textbf{#1}}}", - "\\newcommand{\\pysrcother}[1]{\\small\\textbf{#1}}", - "% Comments", - "\\newcommand{\\pysrccomment}[1]{\\textcolor{py@commentcolour}" - "{\\small\\textbf{#1}}}", - "% Output", - "\\newcommand{\\pysrcoutput}[1]{\\textcolor{py@outputcolour}" - "{\\small\\textbf{#1}}}", - "% Exceptions", - "\\newcommand{\\pysrcexcept}[1]{\\textcolor{py@exceptcolour}" - "{\\small\\textbf{#1}}}", - # Size of the function description boxes. - "\\newlength{\\funcindent}", - "\\newlength{\\funcwidth}", - "\\setlength{\\funcindent}{1cm}", - "\\setlength{\\funcwidth}{\\textwidth}", - "\\addtolength{\\funcwidth}{-2\\funcindent}", - # Size of the var description tables. - "\\newlength{\\varindent}", - "\\newlength{\\varnamewidth}", - "\\newlength{\\vardescrwidth}", - "\\newlength{\\varwidth}", - "\\setlength{\\varindent}{1cm}", - "\\setlength{\\varnamewidth}{.3\\textwidth}", - "\\setlength{\\varwidth}{\\textwidth}", - "\\addtolength{\\varwidth}{-4\\tabcolsep}", - "\\addtolength{\\varwidth}{-3\\arrayrulewidth}", - "\\addtolength{\\varwidth}{-2\\varindent}", - "\\setlength{\\vardescrwidth}{\\varwidth}", - "\\addtolength{\\vardescrwidth}{-\\varnamewidth}", - # Define new environment for displaying parameter lists. - textwrap.dedent("""\ - \\newenvironment{Ventry}[1]% - {\\begin{list}{}{% - \\renewcommand{\\makelabel}[1]{\\texttt{##1:}\\hfil}% - \\settowidth{\\labelwidth}{\\texttt{#1:}}% - \\setlength{\\leftmargin}{\\labelsep}% - \\addtolength{\\leftmargin}{\\labelwidth}}}% - {\\end{list}}"""), + "\\usepackage[%s]{epydoc}", ] - HRULE = '\\rule{\\textwidth}{0.5\\fboxrule}\n\n' - SECTIONS = ['\\part{%s}', '\\chapter{%s}', '\\section{%s}', '\\subsection{%s}', '\\subsubsection{%s}', '\\textbf{%s}'] @@ -130,14 +46,23 @@ # Process keyword arguments self._show_private = kwargs.get('show_private', 0) self._prj_name = kwargs.get('prj_name', None) or 'API Documentation' - self._crossref = kwargs.get('crossref', 1) + self._show_crossrefs = kwargs.get('crossref', 1) self._index = kwargs.get('index', 1) + self._hyperlink = kwargs.get('hyperlink', True) self._list_classes_separately=kwargs.get('list_classes_separately',0) self._inheritance = kwargs.get('inheritance', 'listed') self._exclude = kwargs.get('exclude', 1) + self._list_submodules = kwargs.get('list_submodules', 1) + self._sty = kwargs.get('sty') self._top_section = 2 self._index_functions = 1 self._hyperref = 1 + + # [xx] check into this: + self._pdflatex = kwargs.get('action', '') == "pdflatex" + + self._graph_types = kwargs.get('graphs', ()) or () + """Graphs that we should include in our output.""" #: The Python representation of the encoding. #: Update L{latex_encodings} in case of mismatch between it and @@ -156,6 +81,10 @@ """The list of L{ClassDoc}s for the documented classes.""" self.class_set = set(self.class_list) """The set of L{ClassDoc}s for the documented classes.""" + self.module_list = [d for d in valdocs if isinstance(d, ModuleDoc)] + """The list of L{ModuleDoc}s for the documented modules.""" + self.module_set = set(self.module_list) + """The set of L{ModuleDoc}s for the documented modules.""" def write(self, directory=None): """ @@ -186,6 +115,9 @@ if not directory: directory = os.curdir self._mkdir(directory) self._directory = directory + + # Write the style file. + self._write_sty(directory, self._sty) # Write the top-level file. self._write(self.write_topfile, directory, 'api.tex') @@ -203,6 +135,35 @@ # Restore defaults that we changed. (ValueDoc.SUMMARY_REPR_LINELEN, ValueDoc.REPR_LINELEN, ValueDoc.REPR_MAXLINES) = orig_valdoc_defaults + + def _write_sty(self, directory, stylesheet, filename='epydoc.sty'): + """ + Copy the requested LaTeX stylesheet to the target directory. + The stylesheet can be specified as a name (i.e., a key from + the STYLESHEETS directory); a filename; or None for the default + stylesheet. If any stylesheet *other* than the default + stylesheet is selected, then the default stylesheet will be + copied to 'epydoc-default.sty', which makes it possible to + reference it via \RequirePackage. + """ + if stylesheet is None: + sty = STYLESHEETS['base'] + elif os.path.exists(stylesheet): + try: sty = open(stylesheet, 'rb').read() + except: raise IOError("Can't open LaTeX style file: %r" % + stylesheet) + self._write_sty(directory, None, 'epydoc-default.sty') + elif stylesheet in STYLESHEETS: + sty = STYLESHEETS[stylesheet] + if sty != STYLESHEETS['base']: + self._write_sty(directory, None, 'epydoc-default.sty') + else: + raise IOError("Can't find LaTeX style file: %r" % stylesheet) + + # Write the stylesheet. + out = open(os.path.join(directory, filename), 'wb') + out.write(sty) + out.close() def _write(self, write_func, directory, filename, *args): # Display our progress. @@ -273,9 +234,9 @@ # Add a table of contents. self.write_start_of(out, 'Table of Contents') - out('\\addtolength{\\parskip}{-2ex}\n') + out('\\addtolength{\\parskip}{-1ex}\n') out('\\tableofcontents\n') - out('\\addtolength{\\parskip}{2ex}\n') + out('\\addtolength{\\parskip}{1ex}\n') # Include documentation files. self.write_start_of(out, 'Includes') @@ -300,27 +261,35 @@ out('\\end{document}\n\n') def write_preamble(self, out): - out('\n'.join(self.PREAMBLE)) - out('\n') + # If we're generating an index, add it to the preamble. + options = [] + if self._index: options.append('index') + if self._hyperlink: options.append('hyperlink') + out('\n'.join(self.PREAMBLE) % (','.join(options),) + '\n') # Set the encoding. out('\\usepackage[%s]{inputenc}\n' % self.get_latex_encoding()) # If we're generating hyperrefs, add the appropriate packages. + # !!!!!!!!!!!!!!!!!!!!!! + # !!! JEG - this needs to be the last thing in the preamble + # !!!!!!!!!!!!!!!!!!!!!! if self._hyperref: out('\\definecolor{UrlColor}{rgb}{0,0.08,0.45}\n') - out('\\usepackage[dvips, pagebackref, pdftitle={%s}, ' + + if self._pdflatex: + driver = 'pdftex' + else: + driver = 'dvips' + + out('\\usepackage[%s, pagebackref, pdftitle={%s}, ' 'pdfcreator={epydoc %s}, bookmarks=true, ' 'bookmarksopen=false, pdfpagemode=UseOutlines, ' 'colorlinks=true, linkcolor=black, anchorcolor=black, ' 'citecolor=black, filecolor=black, menucolor=black, ' 'pagecolor=black, urlcolor=UrlColor]{hyperref}\n' % - (self._prj_name or '', epydoc.__version__)) + (driver, self._prj_name or '', epydoc.__version__)) - # If we're generating an index, add it to the preamble. - if self._index: - out("\\makeindex\n") - # If restructuredtext was used, then we need to extend # the prefix to include LatexTranslator.head_prefix. if 'restructuredtext' in epydoc.markup.MARKUP_LANGUAGES_USED: @@ -352,27 +321,28 @@ # Add a section marker. out(self.section('%s %s' % (self.doc_kind(doc), - doc.canonical_name))) + _dotted(doc.canonical_name)), + ref=doc)) - # Label our current location. - out(' \\label{%s}\n' % self.label(doc)) - # Add the module's description. if doc.descr not in (None, UNKNOWN): - out(self.docstring_to_latex(doc.descr)) + out(' '*4 + '\\begin{EpydocModuleDescription}%\n') + out(self.docstring_to_latex(doc.descr, 4)) + out(' '*4 + '\\end{EpydocModuleDescription}\n') # Add version, author, warnings, requirements, notes, etc. self.write_standard_fields(out, doc) # If it's a package, list the sub-modules. - if doc.submodules != UNKNOWN and doc.submodules: + if self._list_submodules and doc.submodules != UNKNOWN and doc.submodules: self.write_module_list(out, doc) # Contents. if self._list_classes_separately: self.write_class_list(out, doc) - self.write_func_list(out, 'Functions', doc, 'function') - self.write_var_list(out, 'Variables', doc, 'other') + self.write_list(out, 'Functions', doc, 'EpydocFunctionList', + 'function') + self.write_list(out, 'Variables', doc, 'EpydocVariableList', 'other') # Class list. if not self._list_classes_separately: @@ -384,6 +354,19 @@ # Mark the end of the module (for the index) out(' ' + self.indexterm(doc, 'end')) + def render_graph(self, graph): + if graph is None: return '' + graph.caption = graph.title = None + if self._pdflatex: + return graph.to_dot2tex() +## image_url = '%s.ps' % graph.uid +## image_file = os.path.join(self._directory, image_url) +## return graph.to_pdf(image_file, image_url) + else: + image_url = '%s.eps' % graph.uid + image_file = os.path.join(self._directory, image_url) + return graph.to_latex(image_file, image_url) + def write_class(self, out, doc): if self._list_classes_separately: self.write_header(out, doc) @@ -396,41 +379,60 @@ if self._list_classes_separately: seclevel = 0 out(self.section('%s %s' % (self.doc_kind(doc), - doc.canonical_name), seclevel)) + _dotted(doc.canonical_name)), + seclevel, ref=doc)) else: seclevel = 1 out(self.section('%s %s' % (self.doc_kind(doc), - doc.canonical_name[-1]), seclevel)) + _dotted(doc.canonical_name[-1])), + seclevel, ref=doc)) - # Label our current location. - out(' \\label{%s}\n' % self.label(doc)) + if ((doc.bases not in (UNKNOWN, None) and len(doc.bases) > 0) or + (doc.subclasses not in (UNKNOWN,None) and len(doc.subclasses)>0)): + # Display bases graphically, if requested. + if 'umlclasstree' in self._graph_types: +## linker = self._LatexDocstringLinker() + graph = uml_class_tree_graph(doc, self._docstring_linker, doc) + out(self.render_graph(graph)) + + elif 'classtree' in self._graph_types: +## linker = self._LatexDocstringLinker() + graph = class_tree_graph([doc], self._docstring_linker, doc) + out(self.render_graph(graph)) - # Add our base list. - if doc.bases not in (UNKNOWN, None) and len(doc.bases) > 0: - out(self.base_tree(doc)) + # Otherwise, use ascii-art. + else: + + # Add our base list. + if doc.bases not in (UNKNOWN, None) and len(doc.bases) > 0: + out(self.base_tree(doc)) - # The class's known subclasses - if doc.subclasses not in (UNKNOWN, None) and len(doc.subclasses) > 0: - sc_items = [plaintext_to_latex('%s' % sc.canonical_name) - for sc in doc.subclasses] - out(self._descrlist(sc_items, 'Known Subclasses', short=1)) + # The class's known subclasses + if doc.subclasses not in (UNKNOWN, None) and len(doc.subclasses) > 0: + sc_items = [_hyperlink(sc, '%s' % sc.canonical_name) + for sc in doc.subclasses] + out(self._descrlist(sc_items, 'Known Subclasses', short=1)) # The class's description. if doc.descr not in (None, UNKNOWN): + out(' '*4 + '\\begin{EpydocClassDescription}\n') out(self.docstring_to_latex(doc.descr)) + out(' '*4 + '\\end{EpydocClassDescription}\n') # Version, author, warnings, requirements, notes, etc. self.write_standard_fields(out, doc) # Contents. - self.write_func_list(out, 'Methods', doc, 'method', - seclevel+1) - self.write_var_list(out, 'Properties', doc, - 'property', seclevel+1) - self.write_var_list(out, 'Class Variables', doc, - 'classvariable', seclevel+1) - self.write_var_list(out, 'Instance Variables', doc, - 'instancevariable', seclevel+1) + self.write_list(out, 'Methods', doc, 'EpydocFunctionList', + 'method', seclevel+1) + self.write_list(out, 'Properties', doc, 'EpydocPropertyList', + 'property', seclevel+1) + self.write_list(out, 'Class Variables', doc, + 'EpydocClassVariableList', + 'classvariable', seclevel+1) + self.write_list(out, 'Instance Variables', doc, + 'EpydocInstanceVariableList', + 'instancevariable', seclevel+1) # Mark the end of the class (for the index) out(' ' + self.indexterm(doc, 'end')) @@ -455,23 +457,22 @@ def write_module_list(self, out, doc): if len(doc.submodules) == 0: return - self.write_start_of(out, 'Modules') + self.write_start_of(out, 'Submodules') - out(self.section('Modules', 1)) - out('\\begin{itemize}\n') - out('\\setlength{\\parskip}{0ex}\n') + out(self.section('Submodules', 1)) + out('\\begin{EpydocModuleList}\n') for group_name in doc.group_names(): if not doc.submodule_groups[group_name]: continue if group_name: - out(' \\item \\textbf{%s}\n' % group_name) - out(' \\begin{itemize}\n') + out(' \\EpydocGroup{%s}\n' % group_name) + out(' \\begin{EpydocModuleList}\n') for submodule in doc.submodule_groups[group_name]: self.write_module_tree_item(out, submodule) if group_name: - out(' \end{itemize}\n') + out(' \end{EpydocModuleList}\n') - out('\\end{itemize}\n\n') + out('\\end{EpydocModuleList}\n\n') def write_module_tree_item(self, out, doc, depth=0): """ @@ -479,19 +480,16 @@ @rtype: C{string} """ - out(' '*depth + '\\item \\textbf{') - out(plaintext_to_latex(doc.canonical_name[-1]) +'}') + out(' '*depth + '\\item[%s]' % _hyperlink(doc, doc.canonical_name[-1])) + if doc.summary not in (None, UNKNOWN): - out(': %s\n' % self.docstring_to_latex(doc.summary)) - if self._crossref: - out('\n \\textit{(Section \\ref{%s}' % self.label(doc)) - out(', p.~\\pageref{%s})}\n\n' % self.label(doc)) + out(' %s\n' % self.docstring_to_latex(doc.summary)) + out(self.crossref(doc) + '\n\n') if doc.submodules != UNKNOWN and doc.submodules: - out(' '*depth + ' \\begin{itemize}\n') - out(' '*depth + '\\setlength{\\parskip}{0ex}\n') + out(' '*depth + ' \\begin{EpydocModuleList}\n') for submodule in doc.submodules: self.write_module_tree_item(out, submodule, depth+4) - out(' '*depth + ' \\end{itemize}\n') + out(' '*depth + ' \\end{EpydocModuleList}\n') #//////////////////////////////////////////////////////////// #{ Base class trees @@ -502,7 +500,7 @@ width = self._find_tree_width(doc)+2 linespec = [] s = ('&'*(width-4)+'\\multicolumn{2}{l}{\\textbf{%s}}\n' % - plaintext_to_latex('%s'%self._base_name(doc))) + _dotted('%s'%self._base_name(doc))) s += '\\end{tabular}\n\n' top = 1 else: @@ -537,7 +535,7 @@ return width def _base_tree_line(self, doc, width, linespec): - base_name = plaintext_to_latex(self._base_name(doc)) + base_name = _dotted(self._base_name(doc)) # linespec is a list of booleans. s = '%% Line for %s, linespec=%s\n' % (base_name, linespec) @@ -546,8 +544,8 @@ # The base class name. s += ('\\multicolumn{%s}{r}{' % labelwidth) - s += '\\settowidth{\\BCL}{%s}' % base_name - s += '\\multirow{2}{\\BCL}{%s}}\n' % base_name + s += '\\settowidth{\\EpydocBCL}{%s}' % base_name + s += '\\multirow{2}{\\EpydocBCL}{%s}}\n' % _hyperlink(doc, self._base_name(doc)) # The vertical bars for other base classes (top half) for vbar in linespec: @@ -587,38 +585,36 @@ # Write a header. self.write_start_of(out, 'Classes') out(self.section('Classes', 1)) - out('\\begin{itemize}') - out(' \\setlength{\\parskip}{0ex}\n') + out('\\begin{EpydocClassList}\n') for name, var_docs in groups: if name: - out(' \\item \\textbf{%s}\n' % name) - out(' \\begin{itemize}\n') + out(' \\EpydocGroup{%s}\n' % name) + out(' \\begin{EpydocClassList}\n') # Add the lines for each class for var_doc in var_docs: self.write_class_list_line(out, var_doc) if name: - out(' \\end{itemize}\n') + out(' \\end{EpydocClassList}\n') - out('\\end{itemize}\n') + out('\\end{EpydocClassList}\n') def write_class_list_line(self, out, var_doc): if var_doc.value in (None, UNKNOWN): return # shouldn't happen doc = var_doc.value - out(' ' + '\\item \\textbf{') - out(plaintext_to_latex(var_doc.name) + '}') + out(' ' + '\\item[%s]' % _hyperlink(var_doc.target, + var_doc.name)) if doc.summary not in (None, UNKNOWN): out(': %s\n' % self.docstring_to_latex(doc.summary)) - if self._crossref: - out(('\n \\textit{(Section \\ref{%s}' % self.label(doc))) - out((', p.~\\pageref{%s})}\n\n' % self.label(doc))) + out(self.crossref(doc) + '\n\n') #//////////////////////////////////////////////////////////// - #{ Function List + #{ Details Lists #//////////////////////////////////////////////////////////// - _FUNC_GROUP_HEADER = '\n\\large{\\textbf{\\textit{%s}}}\n\n' - def write_func_list(self, out, heading, doc, value_type, seclevel=1): + # Also used for the property list. + def write_list(self, out, heading, doc, list_type, + value_type, seclevel=1): # Divide all public variables of the given type into groups. groups = [(plaintext_to_latex(group_name), doc.select_variables(group=group_name, imported=False, @@ -634,10 +630,12 @@ self.write_start_of(out, heading) out(' '+self.section(heading, seclevel)) + out('\\begin{%s}\n' % list_type) + # Write a section for each group. grouped_inh_vars = {} for name, var_docs in groups: - self.write_func_group(out, doc, name, var_docs, grouped_inh_vars) + self.write_list_group(out, doc, name, var_docs, grouped_inh_vars) # Write a section for each inheritance pseudo-group (used if # inheritance=='grouped') @@ -646,14 +644,19 @@ if base in grouped_inh_vars: hdr = ('Inherited from %s' % plaintext_to_latex('%s' % base.canonical_name)) - if self._crossref and base in self.class_set: - hdr += ('\\textit{(Section \\ref{%s})}' % - self.label(base)) - out(self._FUNC_GROUP_HEADER % (hdr)) + out(self.crossref(base) + '\n\n') + out('\\EpydocGroup{%s}\n' % hdr) for var_doc in grouped_inh_vars[base]: - self.write_func_list_box(out, var_doc) + if isinstance(var_doc.value, RoutineDoc): + self.write_function(out, var_doc) + elif isinstance(var_doc.value, PropertyDoc): + self.write_property(out, var_doc) + else: + self.write_var(out, var_doc) + + out('\\end{%s}\n\n' % list_type) - def write_func_group(self, out, doc, name, var_docs, grouped_inh_vars): + def write_list_group(self, out, doc, name, var_docs, grouped_inh_vars): # Split up the var_docs list, according to the way each var # should be displayed: # - listed_inh_vars -- for listed inherited variables. @@ -678,15 +681,20 @@ # Write a header for the group. if name: - out(self._FUNC_GROUP_HEADER % name) - # Write an entry for each normal var: + out('\\EpydocGroup{%s}\n' % name) + # Write an entry for each object in the group: for var_doc in normal_vars: - self.write_func_list_box(out, var_doc) - # Write a subsection for inherited vars: + if isinstance(var_doc.value, RoutineDoc): + self.write_function(out, var_doc) + elif isinstance(var_doc.value, PropertyDoc): + self.write_property(out, var_doc) + else: + self.write_var(out, var_doc) + # Write a subsection for inherited objects: if listed_inh_vars: - self.write_func_inheritance_list(out, doc, listed_inh_vars) - - def write_func_inheritance_list(self, out, doc, listed_inh_vars): + self.write_inheritance_list(out, doc, listed_inh_vars) + + def write_inheritance_list(self, out, doc, listed_inh_vars): for base in doc.mro(): if base not in listed_inh_vars: continue #if str(base.canonical_name) == 'object': continue @@ -694,333 +702,324 @@ if self._public_filter: var_docs = [v for v in var_docs if v.is_public] if var_docs: - hdr = ('Inherited from %s' % - plaintext_to_latex('%s' % base.canonical_name)) - if self._crossref and base in self.class_set: - hdr += ('\\textit{(Section \\ref{%s})}' % - self.label(base)) - out(self._FUNC_GROUP_HEADER % hdr) - out('\\begin{quote}\n') - out('%s\n' % ', '.join( - ['%s()' % plaintext_to_latex(var_doc.name) - for var_doc in var_docs])) - out('\\end{quote}\n') - - def write_func_list_box(self, out, var_doc): + out('\\EpydocInheritanceList{') + out(plaintext_to_latex('%s' % base.canonical_name)) + out(self.crossref(base)) + out('}{') + out(', '.join(['%s' % plaintext_to_latex(var_doc.name) + + self._parens_if_func(var_doc) + for var_doc in var_docs])) + out('}\n') + + def _parens_if_func(self, var_doc): + if isinstance(var_doc.value, RoutineDoc): return '()' + else: return '' + + #//////////////////////////////////////////////////////////// + #{ Function Details + #//////////////////////////////////////////////////////////// + + def write_function(self, out, var_doc): func_doc = var_doc.value is_inherited = (var_doc.overrides not in (None, UNKNOWN)) - # nb: this gives the containing section, not a reference + # Add the function to the index. Note: this will actually + # select the containing section, and won't give a reference # directly to the function. if not is_inherited: - out(' \\label{%s}\n' % self.label(func_doc)) - out(' %s\n' % self.indexterm(func_doc)) + out(' %s%%\n' % self.indexterm(func_doc)) - # Start box for this function. - out(' \\vspace{0.5ex}\n\n') - out('\\hspace{.8\\funcindent}') - out('\\begin{boxedminipage}{\\funcwidth}\n\n') + # This latex command takes 8 arguments. + out('\\EpydocFunction{%\n') - # Function signature. - out(' %s\n\n' % self.function_signature(var_doc)) + # Argument 1: the function signature + out(self.function_signature(var_doc)) + out('}{%\n') - if (func_doc.docstring not in (None, UNKNOWN) and - func_doc.docstring.strip() != ''): - out(' \\vspace{-1.5ex}\n\n') - out(' \\rule{\\textwidth}{0.5\\fboxrule}\n') - - # Description - out("\\setlength{\\parskip}{2ex}\n") + # Argument 2: the function description if func_doc.descr not in (None, UNKNOWN): out(self.docstring_to_latex(func_doc.descr, 4)) + out('}{%\n') - # Parameters - out("\\setlength{\\parskip}{1ex}\n") + # Argument 3: the function parameter descriptions if func_doc.arg_descrs or func_doc.arg_types: - # Find the longest name. - longest = max([0]+[len(n) for n in func_doc.arg_types]) - for names, descrs in func_doc.arg_descrs: - longest = max([longest]+[len(n) for n in names]) - # Table header. - out(' '*6+'\\textbf{Parameters}\n') - out(' \\vspace{-1ex}\n\n') - out(' '*6+'\\begin{quote}\n') - out(' \\begin{Ventry}{%s}\n\n' % (longest*'x')) - # Add params that have @type but not @param info: - arg_descrs = list(func_doc.arg_descrs) - args = set() - for arg_names, arg_descr in arg_descrs: - args.update(arg_names) - for arg in var_doc.value.arg_types: - if arg not in args: - arg_descrs.append( ([arg],None) ) - # Display params - for (arg_names, arg_descr) in arg_descrs: - arg_name = plaintext_to_latex(', '.join(arg_names)) - out('%s\\item[%s]\n\n' % (' '*10, arg_name)) - if arg_descr: - out(self.docstring_to_latex(arg_descr, 10)) - for arg_name in arg_names: - arg_typ = func_doc.arg_types.get(arg_name) - if arg_typ is not None: - if len(arg_names) == 1: - lhs = 'type' - else: - lhs = 'type of %s' % arg_name - rhs = self.docstring_to_latex(arg_typ).strip() - out('%s{\\it (%s=%s)}\n\n' % (' '*12, lhs, rhs)) - out(' \\end{Ventry}\n\n') - out(' '*6+'\\end{quote}\n\n') - - # Returns - rdescr = func_doc.return_descr - rtype = func_doc.return_type - if rdescr not in (None, UNKNOWN) or rtype not in (None, UNKNOWN): - out(' '*6+'\\textbf{Return Value}\n') - out(' \\vspace{-1ex}\n\n') - out(' '*6+'\\begin{quote}\n') - if rdescr not in (None, UNKNOWN): - out(self.docstring_to_latex(rdescr, 6)) - if rtype not in (None, UNKNOWN): - out(' '*6+'{\\it (type=%s)}\n\n' % - self.docstring_to_latex(rtype, 6).strip()) - elif rtype not in (None, UNKNOWN): - out(self.docstring_to_latex(rtype, 6)) - out(' '*6+'\\end{quote}\n\n') + self.write_function_parameters(out, var_doc) + out('}{%\n') - # Raises + # Argument 4: The return description + if func_doc.return_descr not in (None, UNKNOWN): + out(self.docstring_to_latex(func_doc.return_descr, 6)) + out('}{%\n') + + # Argument 5: The return type + if func_doc.return_type not in (None, UNKNOWN): + out(self.docstring_to_latex(func_doc.return_type, 6).strip()) + out('}{%\n') + + # Argument 6: The raises section if func_doc.exception_descrs not in (None, UNKNOWN, [], ()): - out(' '*6+'\\textbf{Raises}\n') - out(' \\vspace{-1ex}\n\n') - out(' '*6+'\\begin{quote}\n') - out(' \\begin{description}\n\n') + out(' '*6+'\\begin{EpydocFunctionRaises}\n') for name, descr in func_doc.exception_descrs: - out(' '*10+'\\item[\\texttt{%s}]\n\n' % + out(' '*10+'\\item[%s]\n\n' % plaintext_to_latex('%s' % name)) out(self.docstring_to_latex(descr, 10)) - out(' \\end{description}\n\n') - out(' '*6+'\\end{quote}\n\n') + out(' '*6+'\\end{EpydocFunctionRaises}\n\n') + out('}{%\n') - ## Overrides + # Argument 7: The overrides section if var_doc.overrides not in (None, UNKNOWN): - out(' Overrides: ' + - plaintext_to_latex('%s'%var_doc.overrides.canonical_name)) + out('\\EpydocFunctionOverrides') if (func_doc.docstring in (None, UNKNOWN) and var_doc.overrides.value.docstring not in (None, UNKNOWN)): - out(' \textit{(inherited documentation)}') - out('\n\n') + out('[1]') + out('{%s}\n\n' + % _hyperlink(var_doc.overrides, + '%s' % var_doc.overrides.canonical_name)) + out('}{%\n') - # Add version, author, warnings, requirements, notes, etc. + # Argument 8: The metadata section self.write_standard_fields(out, func_doc) + out('}\n') + - out(' \\end{boxedminipage}\n\n') - + def write_function_parameters(self, out, var_doc): + func_doc = var_doc.value + # Find the longest name. + longest = max([0]+[len(n) for n in func_doc.arg_types]) + for names, descrs in func_doc.arg_descrs: + longest = max([longest]+[len(n) for n in names]) + # Table header. + out(' '*6+'\\begin{EpydocFunctionParameters}{%s}\n' % (longest*'x')) + # Add params that have @type but not @param info: + arg_descrs = list(func_doc.arg_descrs) + args = set() + for arg_names, arg_descr in arg_descrs: + args.update(arg_names) + for arg in var_doc.value.arg_types: + if arg not in args: + arg_descrs.append( ([arg],None) ) + # Display params + for (arg_names, arg_descr) in arg_descrs: + arg_name = plaintext_to_latex(', '.join(arg_names)) + out('%s\\item[%s]\n\n' % (' '*10, arg_name)) + if arg_descr: + out(self.docstring_to_latex(arg_descr, 10)) + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + # !!! JEG - this loop needs abstracting + # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + for arg_name in arg_names: + arg_typ = func_doc.arg_types.get(arg_name) + if arg_typ is not None: + if len(arg_names) == 1: + lhs = 'type' + else: + lhs = 'type of %s' % arg_name + rhs = self.docstring_to_latex(arg_typ).strip() + out('%s{\\it (%s=%s)}\n\n' % (' '*12, lhs, rhs)) + out(' '*6+'\\end{EpydocFunctionParameters}\n\n') + def function_signature(self, var_doc): func_doc = var_doc.value func_name = var_doc.name - + + s = ('\\begin{EpydocFunctionSignature}{%s}%%\n' % + _hypertarget(var_doc, func_name)) + # This should never happen, but just in case: - if func_doc in (None, UNKNOWN): - return ('\\raggedright \\textbf{%s}(...)' % - plaintext_to_latex(func_name)) - - if func_doc.posargs == UNKNOWN: - args = ['...'] - else: - args = [self.func_arg(name, default) for (name, default) - in zip(func_doc.posargs, func_doc.posarg_defaults)] - if func_doc.vararg: - if func_doc.vararg == '...': - args.append('\\textit{...}') + if func_doc not in (None, UNKNOWN): + if func_doc.posargs == UNKNOWN: + args = ['\\GenericArg{}'] else: - args.append('*\\textit{%s}' % - plaintext_to_latex(func_doc.vararg)) - if func_doc.kwarg: - args.append('**\\textit{%s}' % - plaintext_to_latex(func_doc.kwarg)) - return ('\\raggedright \\textbf{%s}(%s)' % - (plaintext_to_latex(func_name), ', '.join(args))) + args = [self.func_arg(name, default) for (name, default) + in zip(func_doc.posargs, func_doc.posarg_defaults)] + if func_doc.vararg: + if func_doc.vararg == '...': + args.append('\\GenericArg{}') + else: + args.append('\\VarArg{%s}' % + plaintext_to_latex(func_doc.vararg)) + if func_doc.kwarg: + args.append('\\KWArg{%s}' % plaintext_to_latex(func_doc.kwarg)) + + s += ' '+'%\n \\and'.join(args)+'%\n' + s += '\\end{EpydocFunctionSignature}%\n' + + return s def func_arg(self, name, default): - s = '\\textit{%s}' % plaintext_to_latex(self._arg_name(name)) + s = '\\Param' + if default is not None: - s += '={\\tt %s}' % default.summary_pyval_repr().to_latex(None) + s += "[%s]" % default.summary_pyval_repr().to_latex(None) + s += '{%s}' % self._arg_name(name) + return s - + def _arg_name(self, arg): if isinstance(arg, basestring): - return arg - elif len(arg) == 1: - return '(%s,)' % self._arg_name(arg[0]) + return plaintext_to_latex(arg) else: - return '(%s)' % (', '.join([self._arg_name(a) for a in arg])) + return '\\TupleArg{%s}' % '\\and '.join([self._arg_name(a) + for a in arg]) - #//////////////////////////////////////////////////////////// - #{ Variable List - #//////////////////////////////////////////////////////////// - _VAR_GROUP_HEADER = '\\multicolumn{2}{|l|}{\\textit{%s}}\\\\\n' + +# def write_func_list_box(self, out, var_doc): +# func_doc = var_doc.value +# is_inherited = (var_doc.overrides not in (None, UNKNOWN)) - # Also used for the property list. - def write_var_list(self, out, heading, doc, value_type, seclevel=1): - groups = [(plaintext_to_latex(group_name), - doc.select_variables(group=group_name, imported=False, - value_type=value_type, - public=self._public_filter)) - for group_name in doc.group_names()] +# out('\\begin{EpydocFunction}%\n') +# # Function signature. +# out(self.function_signature(var_doc)) - # Discard any empty groups; and return if they're all empty. - groups = [(g,vars) for (g,vars) in groups if vars] - if not groups: return +# # nb: this gives the containing section, not a reference +# # directly to the function. +# if not is_inherited: +# out(' %s%%\n' % self.indexterm(func_doc)) - # Write a header. - self.write_start_of(out, heading) - out(' '+self.section(heading, seclevel)) - - # [xx] without this, there's a huge gap before the table -- why?? - out(' \\vspace{-1cm}\n') +# # If we have nothing else to say, then don't create an +# # \EpydocFunctionInfo environment. +# if not (func_doc.descr not in (None, UNKNOWN) or +# func_doc.arg_descrs or func_doc.arg_types or +# func_doc.return_descr not in (None, UNKNOWN) or +# func_doc.return_type not in (None, UNKNOWN) or +# func_doc.exception_descrs not in (None, UNKNOWN, [], ()) or +# var_doc.overrides not in (None, UNKNOWN) or +# func_doc.metadata not in (None, UNKNOWN, [], ())): +# out(' \\end{EpydocFunction}\n\n') +# return - out('\\hspace{\\varindent}') - out('\\begin{longtable}') - out('{|p{\\varnamewidth}|') - out('p{\\vardescrwidth}|l}\n') - out('\\cline{1-2}\n') +# out('\\begin{EpydocFunctionInfo}%\n') + +# # Description +# if func_doc.descr not in (None, UNKNOWN): +# out(' '*4 + '\\begin{EpydocFunctionDescription}\n') +# out(self.docstring_to_latex(func_doc.descr, 4)) +# out(' '*4 + '\\end{EpydocFunctionDescription}\n') - # Set up the headers & footer (this makes the table span - # multiple pages in a happy way). - out('\\cline{1-2} ') - out('\\centering \\textbf{Name} & ') - out('\\centering \\textbf{Description}& \\\\\n') - out('\\cline{1-2}\n') - out('\\endhead') - out('\\cline{1-2}') - out('\\multicolumn{3}{r}{\\small\\textit{') - out('continued on next page}}\\\\') - out('\\endfoot') - out('\\cline{1-2}\n') - out('\\endlastfoot') +# # Parameters +# if func_doc.arg_descrs or func_doc.arg_types: +# # Find the longest name. +# longest = max([0]+[len(n) for n in func_doc.arg_types]) +# for names, descrs in func_doc.arg_descrs: +# longest = max([longest]+[len(n) for n in names]) +# # Table header. +# out(' '*6+'\\begin{EpydocFunctionParameters}{%s}\n' % (longest*'x')) +# # Add params that have @type but not @param info: +# arg_descrs = list(func_doc.arg_descrs) +# args = set() +# for arg_names, arg_descr in arg_descrs: +# args.update(arg_names) +# for arg in var_doc.value.arg_types: +# if arg not in args: +# arg_descrs.append( ([arg],None) ) +# # Display params +# for (arg_names, arg_descr) in arg_descrs: +# arg_name = plaintext_to_latex(', '.join(arg_names)) +# out('%s\\item[%s]\n\n' % (' '*10, arg_name)) +# if arg_descr: +# out(self.docstring_to_latex(arg_descr, 10)) +# # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# # !!! JEG - this loop needs abstracting +# # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# for arg_name in arg_names: +# arg_typ = func_doc.arg_types.get(arg_name) +# if arg_typ is not None: +# if len(arg_names) == 1: +# lhs = 'type' +# else: +# lhs = 'type of %s' % arg_name +# rhs = self.docstring_to_latex(arg_typ).strip() +# out('%s{\\it (%s=%s)}\n\n' % (' '*12, lhs, rhs)) +# out(' '*6+'\\end{EpydocFunctionParameters}\n\n') + +# # Returns +# rdescr = func_doc.return_descr +# rtype = func_doc.return_type +# if rdescr not in (None, UNKNOWN) or rtype not in (None, UNKNOWN): +# out(' '*6+'\\EpydocFunctionReturns') +# if rtype not in (None, UNKNOWN): +# out('[%s]' % self.docstring_to_latex(rtype, 6).strip()) +# if rdescr not in (None, UNKNOWN): +# out('{%s}' % self.docstring_to_latex(rdescr, 6)) +# else: +# out('{}') +# out('\n\n') - # Write a section for each group. - grouped_inh_vars = {} - for name, var_docs in groups: - self.write_var_group(out, doc, name, var_docs, grouped_inh_vars) +# # Raises +# if func_doc.exception_descrs not in (None, UNKNOWN, [], ()): +# out(' '*6+'\\begin{EpydocFunctionRaises}\n') +# for name, descr in func_doc.exception_descrs: +# out(' '*10+'\\item[%s]\n\n' % +# plaintext_to_latex('%s' % name)) +# out(self.docstring_to_latex(descr, 10)) +# out(' '*6+'\\end{EpydocFunctionRaises}\n\n') - # Write a section for each inheritance pseudo-group (used if - # inheritance=='grouped') - if grouped_inh_vars: - for base in doc.mro(): - if base in grouped_inh_vars: - hdr = ('Inherited from %s' % - plaintext_to_latex('%s' % base.canonical_name)) - if self._crossref and base in self.class_set: - hdr += (' \\textit{(Section \\ref{%s})}' % - self.label(base)) - out(self._VAR_GROUP_HEADER % (hdr)) - out('\\cline{1-2}\n') - for var_doc in grouped_inh_vars[base]: - if isinstance(var_doc.value3, PropertyDoc): - self.write_property_list_line(out, var_doc) - else: - self.write_var_list_line(out, var_doc) - - out('\\end{longtable}\n\n') - - def write_var_group(self, out, doc, name, var_docs, grouped_inh_vars): - # Split up the var_docs list, according to the way each var - # should be displayed: - # - listed_inh_vars -- for listed inherited variables. - # - grouped_inh_vars -- for grouped inherited variables. - # - normal_vars -- for all other variables. - listed_inh_vars = {} - normal_vars = [] - for var_doc in var_docs: - if var_doc.container != doc: - base = var_doc.container - if (base not in self.class_set or - self._inheritance == 'listed'): - listed_inh_vars.setdefault(base,[]).append(var_doc) - elif self._inheritance == 'grouped': - grouped_inh_vars.setdefault(base,[]).append(var_doc) - elif self._inheritance == 'hidden': - pass - else: - normal_vars.append(var_doc) - else: - normal_vars.append(var_doc) - - # Write a header for the group. - if name: - out(self._VAR_GROUP_HEADER % name) - out('\\cline{1-2}\n') - # Write an entry for each normal var: - for var_doc in normal_vars: - if isinstance(var_doc.value, PropertyDoc): - self.write_property_list_line(out, var_doc) - else: - self.write_var_list_line(out, var_doc) - # Write a subsection for inherited vars: - if listed_inh_vars: - self.write_var_inheritance_list(out, doc, listed_inh_vars) +# ## Overrides +# if var_doc.overrides not in (None, UNKNOWN): +# out('\\EpydocFunctionOverrides') +# if (func_doc.docstring in (None, UNKNOWN) and +# var_doc.overrides.value.docstring not in (None, UNKNOWN)): +# out('[1]') +# out('{%s}\n\n' +# % _hyperlink(var_doc.overrides, +# '%s' % var_doc.overrides.canonical_name)) - def write_var_inheritance_list(self, out, doc, listed_inh_vars): - for base in doc.mro(): - if base not in listed_inh_vars: continue - #if str(base.canonical_name) == 'object': continue - var_docs = listed_inh_vars[base] - if self._public_filter: - var_docs = [v for v in var_docs if v.is_public] - if var_docs: - hdr = ('Inherited from %s' % - plaintext_to_latex('%s' % base.canonical_name)) - if self._crossref and base in self.class_set: - hdr += (' \\textit{(Section \\ref{%s})}' % - self.label(base)) - out(self._VAR_GROUP_HEADER % hdr) - out('\\multicolumn{2}{|p{\\varwidth}|}{' - '\\raggedright %s}\\\\\n' % - ', '.join(['%s' % plaintext_to_latex(var_doc.name) - for var_doc in var_docs])) - out('\\cline{1-2}\n') +# # Add version, author, warnings, requirements, notes, etc. +# self.write_standard_fields(out, func_doc) - - def write_var_list_line(self, out, var_doc): - out('\\raggedright ') - out(plaintext_to_latex(var_doc.name, nbsp=True, breakany=True)) - out(' & ') +# out(' \\end{EpydocFunctionInfo}\n') +# out(' \\end{EpydocFunction}\n\n') + + #//////////////////////////////////////////////////////////// + #{ Variable Details + #//////////////////////////////////////////////////////////// + + def write_var(self, out, var_doc): has_descr = var_doc.descr not in (None, UNKNOWN) has_type = var_doc.type_descr not in (None, UNKNOWN) - has_value = var_doc.value is not UNKNOWN - if has_type or has_value: - out('\\raggedright ') + has_repr = (var_doc.value not in (None, UNKNOWN) and + (var_doc.value.parse_repr is not UNKNOWN or + var_doc.value.pyval_repr() is not UNKNOWN)) + + out('\\EpydocVariable{%s}{' % _hypertarget(var_doc, var_doc.name)) if has_descr: out(self.docstring_to_latex(var_doc.descr, 10).strip()) - if has_type or has_value: out('\n\n') - if has_value: - out('\\textbf{Value:} \n{\\tt %s}' % - var_doc.value.summary_pyval_repr().to_latex(None)) + out('}{') if has_type: - ptype = self.docstring_to_latex(var_doc.type_descr, 12).strip() - out('%s{\\it (type=%s)}' % (' '*12, ptype)) - out('&\\\\\n') - out('\\cline{1-2}\n') + out(self.docstring_to_latex(var_doc.type_descr, 12).strip()) + out('}{') + if has_repr: + out(var_doc.value.summary_pyval_repr().to_latex(None)) + out('}\n') - def write_property_list_line(self, out, var_doc): + #//////////////////////////////////////////////////////////// + #{ Property Details + #//////////////////////////////////////////////////////////// + + def write_property(self, out, var_doc): prop_doc = var_doc.value - out('\\raggedright ') - out(plaintext_to_latex(var_doc.name, nbsp=True, breakany=True)) - out(' & ') has_descr = prop_doc.descr not in (None, UNKNOWN) has_type = prop_doc.type_descr not in (None, UNKNOWN) - if has_descr or has_type: - out('\\raggedright ') + out('\\EpydocProperty{%s}{' % _hypertarget(var_doc, var_doc.name)) if has_descr: out(self.docstring_to_latex(prop_doc.descr, 10).strip()) - if has_type: out('\n\n') + out('}{') if has_type: - ptype = self.docstring_to_latex(prop_doc.type_descr, 12).strip() - out('%s{\\it (type=%s)}' % (' '*12, ptype)) - # [xx] List the fget/fset/fdel functions? - out('&\\\\\n') - out('\\cline{1-2}\n') + out(self.docstring_to_latex(prop_doc.type_descr, 12).strip()) + out('}{') + # [xx] What if the accessor is private and show_private=False? + if (prop_doc.fget not in (None, UNKNOWN) and + not prop_doc.fget.canonical_name[0].startswith('??')): + out(_dotted(prop_doc.fget.canonical_name)) + out('}{') + if (prop_doc.fset not in (None, UNKNOWN) and + not prop_doc.fset.canonical_name[0].startswith('??')): + out(_dotted(prop_doc.fset.canonical_name)) + out('}{') + if (prop_doc.fdel not in (None, UNKNOWN) and + not prop_doc.fdel.canonical_name[0].startswith('??')): + out(_dotted(prop_doc.fdel.canonical_name)) + out('}\n') #//////////////////////////////////////////////////////////// #{ Standard Fields @@ -1063,18 +1062,18 @@ if plural is None: plural = singular if len(items) == 0: return '' if len(items) == 1 and singular is not None: - return '\\textbf{%s:} %s\n\n' % (singular, items[0]) + return ('\\EpydocMetadataSingleValue{%s}{%s}\n\n' % + (singular, items[0])) if short: - s = '\\textbf{%s:}\n' % plural - items = [item.strip() for item in items] - return s + ',\n '.join(items) + '\n\n' + s = '\\begin{EpydocMetadataShortList}{%s}%%\n ' % plural + s += '%\n \\and '.join([item.strip() for item in items]) + s += '%\n\\end{EpydocMetadataShortList}\n\n' + return s else: - s = '\\textbf{%s:}\n' % plural - s += '\\begin{quote}\n' - s += ' \\begin{itemize}\n\n \item\n' - s += ' \\setlength{\\parskip}{0.6ex}\n' - s += '\n\n \item '.join(items) - return s + '\n\n\\end{itemize}\n\n\\end{quote}\n\n' + s = '\\begin{EpydocMetadataLongList}{%s}%%\n' % plural + s += '\n\n'.join([' \item %s%%' % item for item in items]) + s += '\n\\end{EpydocMetadataLongList}\n\n' + return s #//////////////////////////////////////////////////////////// @@ -1089,12 +1088,32 @@ def translate_identifier_xref(self, identifier, label=None): if label is None: label = markup.plaintext_to_latex(identifier) return '\\texttt{%s}' % label + # [xx] Should this be added to the DocstringLinker interface??? + # Currently, this is *only* used by dotgraph. + def url_for(self, identifier): + return None +## if isinstance(identifier, (basestring, DottedName)): +## doc = self.docindex.find(identifier, self.container) +## if doc: +## return identifier +## else: +## return None +## +## elif isinstance(identifier, APIDoc): +## return ':'.join(identifier.canonical_name) +## doc = identifier +## +## else: +## raise TypeError('Expected string or APIDoc') _docstring_linker = _LatexDocstringLinker() def docstring_to_latex(self, docstring, indent=0, breakany=0): if docstring is None: return '' - return docstring.to_latex(self._docstring_linker, indent=indent, - hyperref=self._hyperref) + s = docstring.to_latex(self._docstring_linker, indent=indent, + hyperref=self._hyperref) + return (' '*indent + '\\begin{EpydocDescription}%\n' + + s.strip() + '%\n' + + ' '*indent + '\\end{EpydocDescription}\n\n') #//////////////////////////////////////////////////////////// #{ Helpers @@ -1112,18 +1131,23 @@ def write_start_of(self, out, section_name): out('\n' + 75*'%' + '\n') - out('%%' + ((71-len(section_name))/2)*' ') - out(section_name) - out(((72-len(section_name))/2)*' ' + '%%\n') + out('%%' + section_name.center(71) + '%%\n') out(75*'%' + '\n\n') - def section(self, title, depth=0): + def section(self, title, depth=0, ref=None): sec = self.SECTIONS[depth+self._top_section] - return (('%s\n\n' % sec) % plaintext_to_latex(title)) - - def sectionstar(self, title, depth): + text = (sec % title) + '%\n' + if ref: + text += _hypertarget(ref, "") + '%\n' + return text + + # [xx] not used: + def sectionstar(self, title, depth, ref=None): sec = self.STARSECTIONS[depth+self._top_section] - return (('%s\n\n' % sec) % plaintext_to_latex(title)) + text = (sec % title) + '%\n' + if ref: + text += _hypertarget(ref, "") + '%\n' + return text def doc_kind(self, doc): if isinstance(doc, ModuleDoc) and doc.is_package == True: @@ -1154,28 +117... [truncated message content] |