Thread: [Epydoc-commits] SF.net SVN: epydoc: [1161] trunk/epydoc/src/epydoc/docwriter
Brought to you by:
edloper
From: <ed...@us...> - 2006-04-05 01:52:00
|
Revision: 1161 Author: edloper Date: 2006-04-04 18:51:56 -0700 (Tue, 04 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1161&view=rev Log Message: ----------- - Removed sorted_by_name arg from reachable_valdocs; use sorted() on the result instead Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/latex.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-05 01:51:34 UTC (rev 1160) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-05 01:51:56 UTC (rev 1161) @@ -369,8 +369,8 @@ # Precompute lists & sets of APIDoc objects that we're # interested in. self.valdocs = valdocs = sorted(docindex.reachable_valdocs( - sorted_by_name=True, imports=False, packages=False, bases=False, - submodules=False, subclasses=False, private=self._show_private)) + imports=False, packages=False, bases=False, submodules=False, + subclasses=False, private=self._show_private)) 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) Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2006-04-05 01:51:34 UTC (rev 1160) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2006-04-05 01:51:56 UTC (rev 1161) @@ -80,9 +80,9 @@ self._index_functions = 1 self._hyperref = 1 self._encoding = kwargs.get('encoding', 'latin1') - self.valdocs = docindex.reachable_valdocs( - sorted_by_name=True, imports=False, packages=False, bases=False, - submodules=False, subclasses=False, private=self._show_private) + self.valdocs = sorted(docindex.reachable_valdocs( + imports=False, packages=False, bases=False, submodules=False, + subclasses=False, private=self._show_private)) self._num_files = self.num_files() # For use with select_variables(): if self._show_private: self._public_filter = None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-06 04:33:12
|
Revision: 1177 Author: edloper Date: 2006-04-05 21:33:06 -0700 (Wed, 05 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1177&view=rev Log Message: ----------- - PythonSourceColorizer now generates links back into the documentation for all identifiers in the source whose short name is equal to at least one documented object. If multiple documented objects have the same short name, then pop up a little box which lets the user select which item they're interested in. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/html_colorize.py trunk/epydoc/src/epydoc/docwriter/html_css.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-06 04:29:04 UTC (rev 1176) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-06 04:33:06 UTC (rev 1177) @@ -652,7 +652,8 @@ self.href(doc, label='%s %s' % (self.doc_kind(doc), name))) out('<div class="py-src">\n') out('<pre class="py-src">\n') - out(PythonSourceColorizer(filename, name).colorize()) + out(PythonSourceColorizer(filename, name, self.docindex, + self.indexed_docs, self.url).colorize()) out('</pre>\n</div>\n<br />\n') # Footer Modified: trunk/epydoc/src/epydoc/docwriter/html_colorize.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-04-06 04:29:04 UTC (rev 1176) +++ trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-04-06 04:33:06 UTC (rev 1177) @@ -20,6 +20,7 @@ from epydoc import log from epydoc.util import decode_with_backslashreplace, plaintext_to_html from epydoc.util import py_src_filename +from epydoc.apidoc import * ###################################################################### ## Regular expression colorizer @@ -433,8 +434,7 @@ var s = ""; if (linenumpadding != "") s = "<span class=\'lineno\'>" + linenumpadding + "</span>" - s = s + "<span class=\'pysrc-toggle\'> </span>" + - "<span class=\'py-line\'>" + indent + + s = s + " <span class=\'py-line\'>" + indent + "<a href=\'#\' onclick=\'expand(\\"" + id + "\\");return false\'>...</a></span><br />"; elt.innerHTML = s; @@ -498,6 +498,69 @@ } } +function kill_doclink() { + if (!this.contains(event.toElement)) { + var parent = document.getElementById(this.parentID); + parent.removeChild(parent.childNodes.item(0)); + } +} + +function doclink(id, name, targets) { + var elt = document.getElementById(id); + + // If we already opened the box, then destroy it. + // (This case should never occur, but leave it in just in case.) + if (elt.childNodes.length > 1) { + elt.removeChild(elt.childNodes.item(0)); + } + else { + // The outer box: relative + inline positioning. + var box1 = document.createElement("div"); + box1.style.position = "relative"; + box1.style.display = "inline"; + box1.style.top = 0; + box1.style.left = 0; + + // A shadow for fun + var shadow = document.createElement("div"); + shadow.style.position = "absolute"; + shadow.style.left = "-1.3em"; + shadow.style.top = "-1.3em"; + shadow.style.background = "#404040"; + + // The inner box: absolute positioning. + var box2 = document.createElement("div"); + box2.style.position = "relative"; + box2.style.border = "1px solid #a0a0a0"; + box2.style.left = "-.2em"; + box2.style.top = "-.2em"; + box2.style.background = "white"; + box2.style.padding = ".3em .4em .3em .4em"; + box2.style.fontStyle = "normal"; + box2.onmouseout=kill_doclink; + box2.parentID = id; + + var links = ""; + target_list = targets.split(","); + for (var i=0; i<target_list.length; i++) { + var target = target_list[i].split("="); + links += "<li><a href=\'" + target[1] + + "\' style=\'text-decoration:none\'>" + + target[0] + "</a></li>"; + } + + // Put it all together. + elt.insertBefore(box1, elt.childNodes.item(0)); + //box1.appendChild(box2); + box1.appendChild(shadow); + shadow.appendChild(box2); + box2.innerHTML = "Which <b>"+name+"</b> do you want to see "+ + "documentation for?" + + "<ul style=\'margin-bottom: 0;\'>" + + links + "</ul>"; + } +} + expandto(location.href); // --> </script> @@ -544,12 +607,7 @@ - Unicode input is supported (including automatic detection of C{'coding:'} declarations). - Still to do: - - cross-referencing within the code..? - - """ - #: A look-up table that is used to determine which CSS class #: should be used to colorize a given token. The following keys #: may be used: @@ -612,7 +670,10 @@ #: add line numbers. ADD_LINE_NUMBERS = True - def __init__(self, module_filename, module_name): + ADD_TOOLTIPS = False + + def __init__(self, module_filename, module_name, + docindex=None, api_docs=None, url_func=None): """ Create a new HTML colorizer for the specified module. @@ -632,6 +693,19 @@ #: The dotted name of the module we're colorizing. self.module_name = module_name + self.docindex = docindex + + #: A mapping from short names to lists of ValueDoc. + self.name_to_docs = {} + for api_doc in api_docs: + if (api_doc.canonical_name is not None and + url_func(api_doc) is not None): + name = api_doc.canonical_name[-1] + self.name_to_docs.setdefault(name,set()).add(api_doc) + + #: A function that maps APIDoc -> URL + self.url_func = url_func + #: The index in C{text} of the last character of the last #: token we've processed. self.pos = 0 @@ -668,6 +742,7 @@ #: on the previous logical line, or C{None} if the previous #: logical line was not a class or function definition. self.def_name = None + def find_line_offsets(self): """ @@ -741,9 +816,6 @@ html += PYSRC_JAVASCRIPTS return html - - # Add header/footer and return - #return PYSRC_TEMPLATE % (self.module_name, html) def tokeneater(self, toktype, toktext, (srow,scol), (erow,ecol), line): """ @@ -776,6 +848,8 @@ self.handle_line(self.cur_line) self.cur_line = [] + _next_uid = 0 + def handle_line(self, line): """ Render a single logical line from the module, and write the @@ -797,18 +871,21 @@ ended_def_blocks = 0 # The html output. - s = '<span class="pysrc-toggle"> </span>' if self.ADD_LINE_NUMBERS: - s = self.lineno_to_html() + s + s = self.lineno_to_html() self.lineno += 1 - s += '<span class="py-line">' + else: + s = '' + s += ' <span class="py-line">' # Loop through each token, and colorize it appropriately. for i, (toktype, toktext) in enumerate(line): # For each token, determine its css class and whether it - # should link to an href. + # should link to a url. css_class = None - href = None + url = None + tooltip = None + onclick = uid = None # these 3 are used together. # Is this token the class name in a class definition? If # so, then make it a link back into the API docs. @@ -818,7 +895,7 @@ def_name = toktext if None not in self.context: cls_name = '.'.join(self.context+[def_name]) - href = self.name2href(cls_name) + url = self.name2url(cls_name) s = self.mark_def(s, cls_name) # Is this token the function name in a function def? If @@ -830,7 +907,7 @@ if None not in self.context: cls_name = '.'.join(self.context) func_name = '.'.join(self.context+[def_name]) - href = self.name2href(cls_name, def_name) + url = self.name2url(cls_name, def_name) s = self.mark_def(s, func_name) # For each indent, update the indents list (which we use @@ -882,8 +959,32 @@ ((i>0 and line[i-1][1]=='@') or (i>1 and line[i-1][0]==None and line[i-2][1] == '@'))): css_class = self.CSS_CLASSES['DECORATOR'] - + # If it's a name, try to link it. + elif toktype == token.NAME: + css_class = self.CSS_CLASSES['NAME'] + # If we have a variable named `toktext` in the current + # context, then link to that. Note that if we're inside + # a function, then that function is our context, not + # the namespace that contains it. [xx] this isn't always + # the right thing to do. + if None not in self.context: + container = DottedName(self.module_name, *self.context) + doc = self.docindex.get_vardoc(container+toktext) + if doc is not None: + url = self.url_func(doc) + # Otherwise, check the name_to_docs index to see what + # else this name might refer to. + if url is None: + docs = sorted(self.name_to_docs.get(toktext, [])) + if docs: + if len(docs) == 1: + url = self.url_func(docs[0]) + tooltip='%s' % docs[0].canonical_name + else: + uid, onclick = self.doclink(toktext, docs) + tooltip='*.%s' % toktext + # For all other tokens, look up the CSS class to use # based on the token's type. else: @@ -905,20 +1006,32 @@ if toktext in (')',']','}'): in_param_default -= 1 if toktext == ',' and in_param_default == 1: in_param_default = 0 - # Write this token, with appropriate colorization. - if href: s += '<a href="%s" class="%s">' % (href, css_class) - elif css_class: s += '<span class="%s">' % css_class + if tooltip and self.ADD_TOOLTIPS: + tooltip_html = ' title="%s"' % tooltip + else: tooltip_html = '' + if css_class: css_class_html = ' class="%s"' % css_class + else: css_class_html = '' + if onclick: + s += ('<span id="%s"%s><a%s%s href="#" onclick="%s">' % + (uid, css_class_html, tooltip_html, + css_class_html, onclick)) + elif url: + s += ('<a%s%s href="%s">' % + (tooltip_html, css_class_html, url)) + elif css_class_html or tooltip_html: + s += '<span%s%s>' % (tooltip_html, css_class_html) if i == len(line)-1: s += ' </span>' # Closes <span class="py-line"> s += cgi.escape(toktext) else: s += self.add_line_numbers(cgi.escape(toktext), css_class) - - if href: s += '</a>' - elif css_class: s += '</span>' + if onclick: s += "</a></span>" + if url: s += '</a>' + elif css_class_html or tooltip_html: s += '</span>' + if self.ADD_DEF_BLOCKS: for i in range(ended_def_blocks): self.out(self.END_DEF_BLOCK) @@ -929,7 +1042,7 @@ if def_name and None not in self.context: self.out('</div>') - # Add divs if we're starting a def block. + # Add div's if we're starting a def block. if (self.ADD_DEF_BLOCKS and def_name and (line[-2][1] == ':') and None not in self.context): indentation = (''.join(self.indents)+' ').replace(' ', ' ') @@ -940,13 +1053,56 @@ self.def_name = def_name + def doclink(self, name, docs): + uid = 'link-%s' % self._next_uid + self._next_uid += 1 + if None not in self.context: + container = DottedName(self.module_name, *self.context) + else: + container = None + targets = ['%s=%s' % (self.doc_descr(d,container), self.url_func(d)) + for d in docs] + onclick = ("doclink('%s', '%s', '%s'); return false;" % + (uid, name, ','.join(targets))) + return uid, onclick + + def doc_descr(self, doc, context): + name = doc.canonical_name.contextualize(context) + descr = '%s %s' % (self.doc_kind(doc), name) + if isinstance(doc, RoutineDoc): + descr += '()' + return descr + + # [XX] copied streight from html.py; this should be consolidated, + # probably into apidoc. + def doc_kind(self, doc): + if isinstance(doc, ModuleDoc) and doc.is_package == True: + return 'Package' + elif (isinstance(doc, ModuleDoc) and + doc.canonical_name[0].startswith('script')): + return 'Script' + elif isinstance(doc, ModuleDoc): + return 'Module' + elif isinstance(doc, ClassDoc): + return 'Class' + elif isinstance(doc, ClassMethodDoc): + return 'Class Method' + elif isinstance(doc, StaticMethodDoc): + return 'Static Method' + elif isinstance(doc, RoutineDoc): + if isinstance(self.docindex.container(doc), ClassDoc): + return 'Method' + else: + return 'Function' + else: + return 'Variable' + def mark_def(self, s, name): replacement = ('<a name="%s"></a><div id="%s-def">\\1' '<a class="pysrc-toggle" href="#" id="%s-toggle" ' 'onclick="toggle(\'%s\'); return false;">-</a>\\2' % (name, name, name, name)) - return re.sub('(.*<span class="pysrc-toggle">) (</span>.*)\Z', - replacement, s) + return re.sub('(.*) (<span class="py-line">.*)\Z', replacement, s) def is_docstring(self, line, i): if line[i][0] != token.STRING: return False @@ -967,8 +1123,7 @@ result += '\n' if self.ADD_LINE_NUMBERS: result += self.lineno_to_html() - result += '<span class="pysrc-toggle"> </span>' - result += '<span class="py-line">' + result += ' <span class="py-line">' if css_class: result += '<span class="%s">' % css_class start = end end = s.find('\n', end)+1 @@ -976,7 +1131,7 @@ result += s[start:] return result - def name2href(self, class_name, func_name=None): + def name2url(self, class_name, func_name=None): if class_name: class_name = '%s.%s' % (self.module_name, class_name) if func_name: Modified: trunk/epydoc/src/epydoc/docwriter/html_css.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-06 04:29:04 UTC (rev 1176) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-06 04:33:06 UTC (rev 1177) @@ -119,8 +119,7 @@ .continue { border-top: 0; } /* Links */ -a.navbar:link { text-decoration: none; } -a.navbar:visited { text-decoration: none; } +a.navbar { text-decoration: none; } /* Source Code Listings */ pre.py-src { border: 2px solid black; } @@ -128,12 +127,11 @@ border-bottom: 1px solid black; } div.highlight { border-bottom: 2px solid black; } a.pysrc-toggle { text-decoration: none; } -span.pysrc-toggle { font-size: 80%; font-style: normal; - padding-left: .4em; } .py-line { border-left: 2px solid black; margin-left: .2em; padding-left: .4em; } .lineno { font-style: italic; font-size: 90%; padding-left: .5em; } +a.py-name { text-decoration: none; } /* For Graphs */ .graph-without-title { border: none; } @@ -157,7 +155,6 @@ h2 span.codelink { font-size: 58%; font-weight: normal; } span.codelink { font-size: 85%; font-weight; normal; } """ -#(* (/ 1. 1.2) .7) # Black on white, with blue highlights. This is similar to how # javadoc looks. @@ -202,6 +199,8 @@ .py-keyword { background: transparent; color: #600000; } .py-output { background: transparent; color: #404040; } .py-name { background: transparent; color: #000050; } +.py-name:link { background: transparent; color: #000050; } +.py-name:visited { background: transparent; color: #000050; } .py-number { background: transparent; color: #005000; } .py-def-name { background: transparent; color: #000060; font-weight: bold; } @@ -297,6 +296,8 @@ .py-keyword { background: transparent; color: #600000; } .py-output { background: transparent; color: #404040; } .py-name { background: transparent; color: #000050; } +.py-name:link { background: transparent; color: #000050; } +.py-name:visited { background: transparent; color: #000050; } .py-number { background: transparent; color: #005000; } .py-def-name { background: transparent; color: #000060; font-weight: bold; } @@ -391,6 +392,8 @@ .py-keyword { background: transparent; color: #800000; } .py-output { background: transparent; color: #484848; } .py-name { background: transparent; color: #000050; } +.py-name:link { background: transparent; color: #000050; } +.py-name:visited { background: transparent; color: #000050; } .py-number { background: transparent; color: #005000; } .py-def-name { background: transparent; color: #000060; font-weight: bold; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-07 23:34:48
|
Revision: 1188 Author: edloper Date: 2006-04-07 16:34:41 -0700 (Fri, 07 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1188&view=rev Log Message: ----------- - Include the javascripts from html_colorize in epydoc.js - In PythonSourceColorizer: - Fixed bug in spacing of collapsed divs - Made some changes that decrease the size of the generated html file (without changing functionality) Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/html_colorize.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-07 23:32:37 UTC (rev 1187) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-07 23:34:41 UTC (rev 1188) @@ -19,7 +19,7 @@ import time, epydoc, epydoc.markup from epydoc.docwriter.html_colorize import colorize_re from epydoc.docwriter.html_colorize import PythonSourceColorizer -from epydoc.docwriter.html_colorize import colorize_re +from epydoc.docwriter import html_colorize from epydoc.docwriter.html_css import STYLESHEETS from epydoc.docwriter.html_help import HTML_HELP from epydoc.docwriter.dotgraph import * @@ -1216,6 +1216,7 @@ print >> jsfile, self.SET_FRAME_JS print >> jsfile, self.HIDE_PRIVATE_JS print >> jsfile, self.TOGGLE_CALLGRAPH_JS + print >> jsfile, html_colorize.PYSRC_JAVASCRIPTS jsfile.close() #: A javascript that is used to show or hide the API documentation @@ -1338,7 +1339,7 @@ 'class="%s"/>\n' % (cmapx, uid, uid, uid, css)) def render_callgraph(self, callgraph): - graph_html = self.render_graph(callgraph, css='callgraph') + graph_html = self.render_graph(callgraph, css='graph-with-title') if graph_html == '': return '' return ('<div style="display:none" id="%s-div"><center>\n' '<table border="0" cellpadding="0" cellspacing="0">\n' Modified: trunk/epydoc/src/epydoc/docwriter/html_colorize.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-04-07 23:32:37 UTC (rev 1187) +++ trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-04-07 23:34:41 UTC (rev 1188) @@ -401,8 +401,6 @@ #: Javascript code for the PythonSourceColorizer PYSRC_JAVASCRIPTS = '''\ -<script type="text/javascript"> -<!-- function expand(id) { var elt = document.getElementById(id+"-expanded"); if (elt) elt.style.display = "block"; @@ -430,13 +428,14 @@ elt.style.display = "block"; var indent = elt.indent; - var linenumpadding = elt.linenumpadding; - var s = ""; - if (linenumpadding != "") - s = "<span class=\'lineno\'>" + linenumpadding + "</span>" - s = s + " <span class=\'py-line\'>" + indent + - "<a href=\'#\' onclick=\'expand(\\"" + id + - "\\");return false\'>...</a></span><br />"; + var pad = elt.pad; + var s = "<span class=\'lineno\'>"; + for (var i=0; i<pad.length; i++) { s += " " } + s += "</span>"; + s += " <span class=\'py-line\'>"; + for (var i=0; i<indent.length; i++) { s += " " } + s += "<a href=\'#\' onclick=\'expand(\\"" + id; + s += "\\");return false\'>...</a></span><br />"; elt.innerHTML = s; } } @@ -560,7 +559,11 @@ links + "</ul>"; } } +''' +PYSRC_EXPANDTO_JAVASCRIPT = '''\ +<script type="text/javascript"> +<!-- expandto(location.href); // --> </script> @@ -651,7 +654,7 @@ #: ellipsis marker in the collapsed version. START_DEF_BLOCK = ( '<div id="%s-collapsed" style="display:none;" ' - 'linenumpadding="%s" indent="%s"></div>' + 'pad="%s" indent="%s"></div>' '<div id="%s-expanded">') #: HTML code for the end of a collapsable function or class @@ -814,8 +817,8 @@ coding = 'iso-8859-1' html = html.decode(coding).encode('ascii', 'xmlcharrefreplace') - # Add on the javascripts. - html += PYSRC_JAVASCRIPTS + # Call expandto. + html += PYSRC_EXPANDTO_JAVASCRIPT return html @@ -1038,6 +1041,9 @@ for i in range(ended_def_blocks): self.out(self.END_DEF_BLOCK) + # Strip any empty <span>s. + s = re.sub(r'<span class="[\w+]"></span>', '', s) + # Write the line. self.out(s) @@ -1047,8 +1053,8 @@ # Add div's if we're starting a def block. if (self.ADD_DEF_BLOCKS and def_name and (line[-2][1] == ':') and None not in self.context): - indentation = (''.join(self.indents)+' ').replace(' ', ' ') - linenum_padding = ' '*self.linenum_size + indentation = (''.join(self.indents)+' ').replace(' ', '+') + linenum_padding = '+'*self.linenum_size name='.'.join(self.context+[def_name]) self.out(self.START_DEF_BLOCK % (name, linenum_padding, indentation, name)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-13 07:14:53
|
Revision: 1228 Author: edloper Date: 2006-04-13 00:14:46 -0700 (Thu, 13 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1228&view=rev Log Message: ----------- - Revamped index page - Added bug index - Added todo index - split into 4 pages - improved formatting - Cleaned up css a little (more left to do) Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/html_css.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-12 21:01:16 UTC (rev 1227) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-13 07:14:46 UTC (rev 1228) @@ -390,8 +390,11 @@ if not isinstance(d, GenericValueDoc)] for doc in valdocs: if isinstance(doc, NamespaceDoc): - self.indexed_docs += [doc for doc in doc.variables.values() if - isinstance(doc.value, GenericValueDoc)] + # add any vars with generic vlaues; but don't include + # inherited vars. + self.indexed_docs += [d for d in doc.variables.values() if + isinstance(d.value, GenericValueDoc) + and d.container == doc] self.indexed_docs.sort() # Figure out the url for the top page. @@ -403,7 +406,7 @@ for doc in self.module_list: if isinstance(doc, ModuleDoc) and is_src_filename(doc.filename): self.modules_with_sourcecode.add(doc) - self._num_files = len(self.class_list) + 2*len(self.module_list) + 9 + self._num_files = len(self.class_list) + 2*len(self.module_list) + 12 if self._incl_sourcecode: self._num_files += len(self.modules_with_sourcecode) @@ -499,7 +502,27 @@ self.write_javascript(directory) # Write the term & identifier indices - self._write(self.write_indices, directory, 'indices.html') + indices = {'ident': self.build_identifier_index(), + 'term': self.build_term_index(), + 'bug': self.build_metadata_index('bug'), + 'todo': self.build_metadata_index('todo')} + self._write(self.write_identifier_index, directory, + 'identifier-index.html', indices) + if indices['term']: + self._write(self.write_term_index, directory, + 'term-index.html', indices) + else: + self._files_written += 1 # (skipped) + if indices['bug']: + self._write(self.write_metadata_index, directory, + 'bug-index.html', indices, 'bug', 'Bug List') + else: + self._files_written += 1 # (skipped) + if indices['todo']: + self._write(self.write_metadata_index, directory, + 'todo-index.html', indices, 'todo', 'To Do List') + else: + self._files_written += 1 # (skipped) # Write the trees file (package & class hierarchies) self._write(self.write_trees, directory, 'trees.html') @@ -549,6 +572,9 @@ estr += ' (from %s)\n' % name log.docstring_warning(estr) + # [xx] testing: + assert self._num_files == self._files_written + def _write(self, write_func, directory, filename, *args): # Display our progress. self._files_written += 1 @@ -772,8 +798,6 @@ """ Write an HTML page containing the module and class hierarchies to the given streams. - @param public: The output stream for the public version of the page. - @param private: The output stream for the private version of the page. """ # Header material. self.write_header(out, 'Trees') @@ -801,135 +825,159 @@ self.write_footer(out) #//////////////////////////////////////////////////////////// - #{ 2.4. Indices page + #{ 2.4. Index pages #//////////////////////////////////////////////////////////// - def write_indices(self, out): + def write_identifier_index(self, out, indices): """ - Write an HTML page containing the term and identifier indices - to the given streams. - @bug: If there are private indexed terms, but no public - indexed terms, then this function will still write a - header for the Term Index to the public stream. - @param public: The output stream for the public version of the page. - @param private: The output stream for the private version of the page. + Write an HTML page containing the identifier index. """ # Header material. - self.write_header(out, 'Index') + self.write_header(out, 'Identifier Index') self.write_navbar(out, 'indices') - self.write_breadcrumbs(out, 'indices', 'indices.html') - out('<br />\n') + self.write_breadcrumbs(out, 'indices', 'identifier-index.html') + self.write_index_pointers(out, indices) - terms = self._extract_term_index() - if terms: - self.write_term_index(out, terms) + # Write a header with the page name and links to all available + # letters. + out('<table border="0" width="100%">\n' + '<tr valign="bottom"><td width="100%">\n' + '<a name="identifiers"><h2 class="index">' + 'Identifier Index</h2></a>\n' + '</td><td>\n') + out('[') + for letter in 'ABCDEFGHIJKLMNOPQRSTUVWZYZ_': + if letter in indices['ident']: + out(' <a href="#identifiers-%s">%s</a>' % + (letter, letter)) + else: + out(' %s' % letter) + out(' ]\n') - # [xx] this will only find variables if they have values. - # (e.g., it won't list any instance variables.) - identifiers = [] - for doc in self.indexed_docs: - name = doc.canonical_name - if self.url(doc) is None: continue - key = name[-1].lower() - key = (key[:1] in 'abcdefghijklmnopqrstuvwxyz', key) - identifiers.append( (key, name, doc) ) - - identifiers.sort() - if identifiers: - self.write_identifier_index(out, identifiers) + # Write the identifier index itself. + out('</td></table>\n') + out('<table border="0" width="100%"><tr valign="top">\n') + for letter in sorted(indices['ident'].iterkeys()): + out('<td valign="top" width="1%">') + out('<a name="identifiers-%s"><h2>%s</h2></a></td>\n' % + (letter, letter)) + out('<td valign="top">\n') + section = sorted(indices['ident'][letter]) + self.write_index_section(out, section, True) + out('</td></tr>\n') + out('</table>\n</br />') # Footer material. + out('<br />') self.write_navbar(out, 'indices') self.write_footer(out) - write_identifier_index_header = compile_template( + def write_term_index(self, out, indices): """ - write_identifier_index_header(self, out) - """, - # /------------------------- Template -------------------------\ - ''' - <!-- ==================== IDENTIFIER INDEX ==================== --> - <table class="index" border="1" cellpadding="3" - cellspacing="0" width="100%" bgcolor="white"> - <tr bgcolor="#70b0f0" class="index"><th colspan="2"> - <table border="0" cellpadding="0" cellspacing="0" width="100%"> - <tr><th class="index">Identifier Index</th> - <td width="100%" align="right"> [ - <a href="#_">_</a> - >>> for c in "abcdefghijklmnopqrstuvwxyz": - <a href="#$c$">$c$</a> - >>> #endfor - ] </td> - </tr></table> - </th></tr> - ''') - # \------------------------------------------------------------/ - - write_identifier_index = compile_template( + Write an HTML page containing the term index. """ - write_identifier_index(self, out, index) - """, - # /------------------------- Template -------------------------\ - ''' - >>> #self.write_table_header(out, "index", "Identifier Index") - >>> self.write_identifier_index_header(out) - >>> letters = "abcdefghijklmnopqrstuvwxyz" - <a name="_"></a> - >>> for sortkey, name, doc in index: - >>> if self._doc_or_ancestor_is_private(doc): - >>> if not self._show_private: continue - <tr class="private"><td width="15%"> - >>> else: - <tr><td width="15%"> - >>> #endif - >>> while letters and letters[0] <= name[-1][:1].lower(): - <a name="$letters[0]$"></a> - >>> letters = letters[1:] - >>> #endif - $self.href(doc, name[-1])$ - </td> - <td>$self.doc_kind(doc)$ - >>> container_name = name.container() - >>> if container_name is not None: - >>> container = self.docindex.get_valdoc(container_name) - >>> if container is not None: - in $self.doc_kind(container)$ $self.href(container)$ - >>> #endif - >>> #endif - </td> - </tr> - >>> #endfor - </table> - >>> for letter in letters: - <a name="$letter$"></a> - >>> #endfor - <br /> - ''') - # \------------------------------------------------------------/ + # Header material. + self.write_header(out, 'Term Index') + self.write_navbar(out, 'indices') + self.write_breadcrumbs(out, 'indices', 'term-index.html') + self.write_index_pointers(out, indices) - write_term_index = compile_template( + out('<a name="term"><h2 class="index">Term Definition Index</h2></a>') + self.write_index_section(out, sorted(indices['term'], + key=lambda v:v[0].lower())) + + # Footer material. + out('<br />') + self.write_navbar(out, 'indices') + self.write_footer(out) + + def write_metadata_index(self, out, indices, field, title): """ - write_term_index(self, out, index) - """, - # /------------------------- Template -------------------------\ - ''' - >>> if not index: return - >>> self.write_table_header(out, "index", "Term Index") - >>> for (key, term, links) in index: - <tr><td width="15%">$term.to_plaintext(None)$</td> - <td> - >>> for link in links[:-1]: - <em>$self.href(link)$</em>, - >>> #endfor - <em>$self.href(links[-1])$</em> - </td> - </tr> - >>> #endfor - </table> - <br /> - ''') - # \------------------------------------------------------------/ + Write an HTML page containing a metadata index. + """ + # Header material. + self.write_header(out, title) + self.write_navbar(out, 'indices') + self.write_breadcrumbs(out, 'indices', '%s-index.html' % field) + self.write_index_pointers(out, indices) + index = indices[field] + # [XX} FIXME + out('<a name="%s"><h2 class="index">%s</h2></a>' % + (field, title)) + + for arg in sorted(index): + # Write a section title. + if arg is not None: + if len([1 for (doc, descrs) in index[arg] if + not self._doc_or_ancestor_is_private(doc)]) == 0: + out('<div class="private">') + else: + out('<div>') + self.write_table_header(out, 'index', arg) + out('</table>') + # List every descr for this arg. + for (doc, descrs) in index[arg]: + if self._doc_or_ancestor_is_private(doc): + out('<div class="private">\n') + else: + out('<div>\n') + out('<table width="100%" class="details" ' + 'bgcolor="#e0e0e0"><tr><td>') + out('<b>In %s</b>' % self.href(doc)) + out(' <ul>\n') + for descr in descrs: + out(' <li>%s</li>\n' % + self.docstring_to_html(descr,doc,4)) + out(' </ul>\n') + out('</table></div>\n') + out('</dl>\n') + + # Footer material. + out('<br />') + self.write_navbar(out, 'indices') + self.write_footer(out) + + def write_index_pointers(self, out, indices): + """ + A helper for the index page generation functions, which + generates a header that can be used to navigate between the + different indices. + """ + if len(indices) > 1: + out('<center><b>[\n') + out(' <a href="identifier-index.html">Identifier Index</a>\n') + if indices['term']: + out('| <a href="term-index.html">Term Definition Index</a>\n') + if indices['bug']: + out('| <a href="bug-index.html">Bug List</a>\n') + if indices['todo']: + out('| <a href="todo-index.html">To Do List</a>\n') + out(']</b></center>\n') + + def write_index_section(self, out, items, add_blankline=False): + out('<table class="index" width="100%" border="1">\n') + num_rows = (len(items)+2)/3 + for row in range(num_rows): + out(' <tr>\n') + for col in range(3): + out(' <td width="33%" class="index">') + i = col*num_rows+row + if i < len(items): + name, url, container = items[col*num_rows+row] + out('<a href="%s">%s</a>' % (url, name)) + if container is not None: + out('<br />\n ') + out('<font size="-2">(in %s)</font>' % + self.href(container)) + else: + out(' ') + out('</td>\n') + out(' </tr>\n') + if add_blankline and num_rows == 1: + out(' <tr>'+3*'<td class="index"> </td>'+'</tr>\n') + out('</table>\n') + #//////////////////////////////////////////////////////////// #{ 2.5. Help Page #//////////////////////////////////////////////////////////// @@ -940,9 +988,6 @@ C{self._helpfile} contains a help file, then use it; otherwise, use the default helpfile from L{epydoc.docwriter.html_help}. - - @param public: The output stream for the public version of the page. - @param private: The output stream for the private version of the page. """ # todo: optionally parse .rst etc help files? @@ -1085,8 +1130,6 @@ the given module to the given streams. This page lists the modules, classes, exceptions, functions, and variables defined by the module. - @param public: The output stream for the public version of the page. - @param private: The output stream for the private version of the page. """ name = doc.canonical_name[-1] self.write_header(out, name) @@ -1454,7 +1497,7 @@ <table class="navbar" border="0" width="100%" cellpadding="0" bgcolor="#a0c0ff" cellspacing="0"> <tr valign="middle"> - >>> if self._top_page_url not in ("trees.html", "indices.html", "help.html"): + >>> if self._top_page_url not in ("trees.html", "identifier-index.html", "help.html"): <!-- Home link --> >>> if (isinstance(context, ValueDoc) and >>> self._top_page_url == self.url(context.canonical_name)): @@ -1480,7 +1523,7 @@ > Index </th> >>> else: <th class="navbar"> <a class="navbar" - href="indices.html">Index</a> </th> + href="identifier-index.html">Index</a> </th> >>> #endif <!-- Help link --> @@ -1686,7 +1729,7 @@ self.write_inheritance_list(out, doc, listed_inh_vars) def write_inheritance_list(self, out, doc, listed_inh_vars): - out(' <tr>\n <td colspan="2">\n') + out(' <tr>\n <td colspan="2" class="summary">\n') for base in doc.mro(): if base not in listed_inh_vars: continue public_vars = [v for v in listed_inh_vars[base] @@ -1761,10 +1804,12 @@ # /------------------------- Template -------------------------\ ''' <tr$tr_class$> - <td width="15%" align="right" valign="top" class="rtype"> - $self.rtype(var_doc, indent=6) or " "$ + <td width="15%" align="right" valign="top" class="summary"> + <span class="rtype"> + $self.rtype(var_doc, indent=6) or " "$ + </span> </td> - <td> + <td class="summary"> $self.function_signature(var_doc, link_name=True)$ $summary$ </td> @@ -1779,9 +1824,9 @@ # /------------------------- Template -------------------------\ ''' <tr$tr_class$> - <td width="15%"> + <td width="15%" class="summary"> <strong>$self.href(var_doc)$</strong></td> - <td>$summary or " "$</td> + <td class="summary">$summary or " "$</td> </tr> ''') # \------------------------------------------------------------/ @@ -1911,7 +1956,7 @@ >>> func_doc = var_doc.value <a name="$var_doc.name$"></a> <div$div_class$> - <table width="100%" class="func-details" bgcolor="#e0e0e0"><tr><td> + <table width="100%" class="details" bgcolor="#e0e0e0"><tr><td> <table width="100%" cellpadding="0" cellspacing="0" border="0"> <tr valign="top"><td> <h3>$self.function_signature(var_doc)$ @@ -2017,7 +2062,7 @@ >>> prop_doc = var_doc.value <a name="$var_doc.name$"></a> <div$div_class$> - <table width="100%" class="prop-details" bgcolor="#e0e0e0"><tr><td> + <table width="100%" class="details" bgcolor="#e0e0e0"><tr><td> <h3>$var_doc.name$</h3> $descr$ <dl><dt></dt><dd> @@ -2047,7 +2092,7 @@ ''' <a name="$var_doc.name$"></a> <div$div_class$> - <table width="100%" class="var-details" bgcolor="#e0e0e0"><tr><td> + <table width="100%" class="details" bgcolor="#e0e0e0"><tr><td> <h3>$var_doc.name$</h3> $descr$ <dl><dt></dt><dd> @@ -2069,9 +2114,9 @@ ''') # \------------------------------------------------------------/ - _variable_linelen = 70 + _variable_linelen = 80 _variable_maxlines = 3 - _variable_tooltip_linelen = 70 + _variable_tooltip_linelen = 80 def variable_tooltip(self, var_doc): if var_doc.value in (None, UNKNOWN): return '' @@ -2094,10 +2139,10 @@ summary_linelen) elif val_doc.parse_repr is not UNKNOWN: s = plaintext_to_html(val_doc.parse_repr) - return self._linewrap_html(s, self._variable_linelen, - self._variable_maxlines) else: - return self.href(val_doc) + s = self.href(val_doc) + return self._linewrap_html(s, self._variable_linelen, + self._variable_maxlines) def pprint_pyval(self, pyval, multiline=True, summary_linelen=0): # Handle the most common cases first. The following types @@ -2257,7 +2302,7 @@ @rtype: C{string} """ if context is None: - context = doc + context = doc.defining_module if width == None: width = self.find_tree_width(doc, context) if isinstance(doc, ClassDoc) and doc.bases != UNKNOWN: bases = doc.bases @@ -2278,9 +2323,9 @@ ' |'+postfix+'\n' + s) if i != 0: - s = (self.base_tree(base, width-4, ' |'+postfix)+s) + s = (self.base_tree(base, width-4, ' |'+postfix, context)+s) else: - s = (self.base_tree(base, width-4, ' '+postfix)+s) + s = (self.base_tree(base, width-4, ' '+postfix, context)+s) return s def find_tree_width(self, doc, context): @@ -2303,11 +2348,14 @@ """ Return the label for L{doc} to be shown in C{context}. """ - context = context.canonical_name - if context is not UNKNOWN: - context = context.container() - - return str(doc.canonical_name.contextualize(context)) + if doc.canonical_name is None: + if doc.parse_repr is not None: + return doc.parse_repr + else: + return '??' + else: + context_name = context.canonical_name + return str(doc.canonical_name.contextualize(context_name)) #//////////////////////////////////////////////////////////// #{ Function Signatures @@ -2598,9 +2646,71 @@ # \------------------------------------------------------------/ #//////////////////////////////////////////////////////////// - #{ Term index generation + #{ Index generation #//////////////////////////////////////////////////////////// + def build_identifier_index(self): + items = [] + for doc in self.indexed_docs: + name = doc.canonical_name[-1] + url = self.url(doc) + if not url: continue + container = self.docindex.container(doc) + items.append( (name, url, container) ) + return self._group_by_letter(items) + + def _group_by_letter(self, items): + index = {} + for item in items: + first_letter = item[0][0].upper() + if not ("A" <= first_letter <= "Z"): + first_letter = '_' + index.setdefault(first_letter, []).append(item) + return index + + def build_term_index(self): + items = [] + for doc in self.indexed_docs: + url = self.url(doc) + items += self._terms_from_docstring(url, doc, doc.descr) + for (field, arg, descr) in doc.metadata: + items += self._terms_from_docstring(url, doc, descr) + if hasattr(doc, 'type_descr'): + items += self._terms_from_docstring(url, doc, + doc.type_descr) + if hasattr(doc, 'return_descr'): + items += self._terms_from_docstring(url, doc, + doc.return_descr) + if hasattr(doc, 'return_type'): + items += self._terms_from_docstring(url, doc, + doc.return_type) + return items + + def _terms_from_docstring(self, base_url, container, parsed_docstring): + if parsed_docstring in (None, UNKNOWN): return [] + terms = [] + for term in parsed_docstring.index_terms(): + anchor = self._term_index_to_anchor(term) + url = '%s#%s' % (base_url, anchor) + terms.append( (term.to_plaintext(None), url, container) ) + return terms + + def build_metadata_index(self, field_name): + # Build the index. + index = {} + for doc in self.indexed_docs: + if (not self._show_private and + self._doc_or_ancestor_is_private(doc)): + continue + descrs = {} + if doc.metadata is not UNKNOWN: + for (field, arg, descr) in doc.metadata: + if field.tags[0] == field_name: + descrs.setdefault(arg, []).append(descr) + for (arg, descr_list) in descrs.iteritems(): + index.setdefault(arg, []).append( (doc, descr_list) ) + return index + def _get_index_terms(self, parsed_docstring, link, terms, links): """ A helper function for L{_extract_term_index}. @@ -2629,48 +2739,6 @@ s = re.sub(r'\s\s+', '-', term.to_plaintext(None)) return "index-"+re.sub("[^a-zA-Z0-9]", "_", s) - def _extract_term_index(self): - """ - Extract the set of terms that should be indexed from all - documented docstrings. Return the extracted set as a - list of tuples of the form C{(key, term, [links])}. - This list is used by L{write_indices()} to construct the - term index. - @rtype: C{list} of C{(string, ParsedDocstring, list of ValueDoc)} - """ - terms = {} - links = {} - for doc in self.valdocs: - self._get_index_terms(doc.descr, doc, terms, links) - if doc.metadata not in (None, UNKNOWN): - for (field, arg, descr) in doc.metadata: - self._get_index_terms(descr, doc, terms, links) - # [xx] summary? type_descr? others? - if isinstance(doc, NamespaceDoc): - for var in doc.variables.values(): - self._get_index_terms(var.descr, var, terms, links) - for (field, arg, descr) in var.metadata: - self._get_index_terms(descr, var, terms, links) - elif isinstance(doc, RoutineDoc): - self._get_index_terms(doc.return_descr, doc, terms, links) - self._get_index_terms(doc.return_type, doc, terms, links) - if doc.arg_descrs not in (None, UNKNOWN): - for arg, descr in doc.arg_descrs: - self._get_index_terms(descr, doc, terms, links) - if doc.arg_types not in (None, UNKNOWN): - for arg, descr in doc.arg_types.items(): - self._get_index_terms(descr, doc, terms, links) - if doc.exception_descrs not in (None, UNKNOWN): - for excname, descr in doc.exception_descrs: - self._get_index_terms(descr, doc, terms, links) - elif isinstance(doc, PropertyDoc): - self._get_index_terms(doc.type_descr, doc, terms, links) - - # Combine terms & links into one list - keys = terms.keys() - keys.sort() - return [(k, terms[k], links[k]) for k in keys] - #//////////////////////////////////////////////////////////// #{ Helper functions #//////////////////////////////////////////////////////////// @@ -2681,7 +2749,7 @@ write_table_header = compile_template( ''' write_table_header(self, out, css_class, heading=None, \ - private_link=True) + private_link=True, colspan=2) ''', # /------------------------- Template -------------------------\ ''' @@ -2695,10 +2763,10 @@ >>> if heading is not None: <tr bgcolor="#70b0f0" class="$css_class$"> >>> if private_link: - <td colspan="2"> + <td colspan="$colspan$" class="$css_class$"> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr valign="top"> - <th align="left" class="$css_class$">$heading$</th> + <td align="left"><h3 class="$css_class$">$heading$</h3></th> <td align="right" valign="top" ><span class="options">[<a href="#$anchor$" class="privatelink" onclick="toggle_private();" @@ -2780,7 +2848,7 @@ return self.url(val_doc) # Special pages: elif obj == 'indices': - return 'indices.html' + return 'identifier-index.html' elif obj == 'help': return 'help.html' elif obj == 'trees': Modified: trunk/epydoc/src/epydoc/docwriter/html_css.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-12 21:01:16 UTC (rev 1227) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-13 07:14:46 UTC (rev 1228) @@ -41,21 +41,30 @@ # Should all epydoc css classes start with epydoc-? # -# Base stylesheet -- just the layout details +# Base stylesheet -- just the layout details (no color) _LAYOUT = """ /* Tables */ table.help { margin-left: auto; margin-right: auto; } -th.summary, th.details, th.index - { text-align: left; font-size: 120%; } -th.group { text-align: left; font-size: 120%; - font-style: italic; } +table.summary { border-collapse: collapse; + border-width: 1px; border-style: solid; } +table.details { border-collapse: collapse; + border-width: 1px; border-style: solid; + margin: .2em 0 0 0; } +table.index { border-collapse: collapse; + border-width: 1px; border-style: solid; } +td.summary { border-width: 1px; border-style: solid; } +td.details { border-width: 1px; border-style: solid; } +td.index { border-width: 0px; } +th.group { text-align: left; font-size: 115%; font-style: italic; + border-width: 1px; border-style: solid; } /* Documentation page titles */ h2.module { margin-top: 0.2em; } h2.class { margin-top: 0.2em; } h2.type { margin-top: 0.2em; } h2.py-src { margin-top: 0.2em; } +h2.index { margin-top: 0.2em; margin-bottom: 0; } /* Headings */ h1.help { text-align: center; } @@ -69,6 +78,8 @@ font-weight: bold; padding: 0; } h2.tocheading { font-size: 100%; margin: 0.5em 0 0 -0.3em; font-weight: bold; } +h3.summary, h3.details, h3.index /* used in table headers */ + { font-size: 120%; margin: 0; } /* Table of contents */ p.toc { margin: 0; padding: 0; } @@ -83,17 +94,6 @@ p.imports { padding: 0 0 0 7em; text-indent: -7em; } .imports-header { font-weight: bold; } -/* Details Sections */ -table.func-details { border-width: 2px; border-style: groove; - padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } -h3.func-detail { margin: 0 0 1em 0; } -table.var-details { border-width: 2px; border-style: groove; - padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } -h3.var-details { margin: 0 0 1em 0; } -table.prop-details { border-width: 2px; border-style: groove; - padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } -h3.prop-details { margin: 0 0 1em 0; } - /* Function signatures */ .sig { font-weight: bold; } @@ -133,7 +133,7 @@ padding-left: .5em; } /*a.py-name { text-decoration: none; }*/ -/* For Graphs */ +/* Graphs */ .graph-without-title { border: none; } .graph-with-title { border: 1px solid black; } .graph-title { font-weight: bold; } @@ -159,26 +159,22 @@ # javadoc looks. _WHITE = _LAYOUT + """ /* Body color */ -body { background: #ffffff; color: #000000; } +body { background: #ffffff; color: #000000; } /* Tables */ -table.summary, table.details, table.index - { background: #e8f0f8; color: #000000; } -tr.summary, tr.details, tr.index - { background: #70b0ff; color: #000000; } +table.summary { background: #e8f0f8; color: #000000; + border-color: #608090; } +table.details { background: #e8f0f8; color: #000000; + border-color: #608090; } +table.index { background: #e8f0f8; color: #000000; + border-color: #608090; } +tr.summary { background: #70b0ff; color: #000000; + border-color: #608090; } +tr.details { background: #70b0ff; color: #000000; + border-color: #608090; } +tr.index { background: #70b0ff; color: #000000; } th.group { background: #c0e0f8; color: #000000; } -/* Details Sections */ -table.func-details { background: #e8f0f8; color: #000000; - border-color: #c0d0d0; } -h3.func-detail { background: transparent; color: #000000; } -table.var-details { background: #e8f0f8; color: #000000; - border-color: #c0d0d0; } -h3.var-details { background: transparent; color: #000000; } -table.prop-details { background: #e8f0f8; color: #000000; - border-color: #c0d0d0; } -h3.prop-details { background: transparent; color: #000000; } - /* Function signatures */ .sig { background: transparent; color: #000000; } .sig-name { background: transparent; color: #006080; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-08-23 05:25:20
|
Revision: 1300 Author: edloper Date: 2006-08-22 22:25:13 -0700 (Tue, 22 Aug 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1300&view=rev Log Message: ----------- - Modified html_colorize.PythonSourceColorizer constructor to take a name_to_docs dictionary as an argument, rather than recomputing it each time. The name_to_docs dictionary is computed by HTMLWriter, and pre-sorted. This optimization should make source colorization faster. Based on a patch provided by Daniel von Dincklage. - In PythonSourceColorizer, check to make sure docindex, url_func, etc. exist before using them. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/html_colorize.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-08-23 02:04:55 UTC (rev 1299) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-08-23 05:25:13 UTC (rev 1300) @@ -565,9 +565,22 @@ # Write source code files. if self._incl_sourcecode: + # Build a map from short names to APIDocs, used when + # linking names in the source code. + name_to_docs = {} + for api_doc in self.indexed_docs: + if (api_doc.canonical_name is not None and + self.url(api_doc) is not None): + name = api_doc.canonical_name[-1] + name_to_docs.setdefault(name, []).append(api_doc) + # Sort each entry of the name_to_docs list. + for doc_list in name_to_docs.values(): + doc_list.sort() + # Write the source code for each module. for doc in self.modules_with_sourcecode: filename = urllib.unquote(self.pysrc_url(doc)) - self._write(self.write_sourcecode, directory, filename, doc) + self._write(self.write_sourcecode, directory, filename, doc, + name_to_docs) # Write the index.html files. # (this must be done last, since it might copy another file) @@ -682,7 +695,7 @@ #{ 2.??. Source Code Pages #//////////////////////////////////////////////////////////// - def write_sourcecode(self, out, doc): + def write_sourcecode(self, out, doc, name_to_docs): filename = doc.filename name = str(doc.canonical_name) @@ -696,7 +709,7 @@ self.href(doc, label='%s %s' % (self.doc_kind(doc), name))) out('<pre class="py-src">\n') out(PythonSourceColorizer(filename, name, self.docindex, - self.indexed_docs, self.url).colorize()) + self.url, name_to_docs).colorize()) out('</pre>\n<br />\n') # Footer Modified: trunk/epydoc/src/epydoc/docwriter/html_colorize.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-08-23 02:04:55 UTC (rev 1299) +++ trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-08-23 05:25:13 UTC (rev 1300) @@ -488,7 +488,6 @@ </script> ''' - import tokenize, sys, token, cgi, keyword try: from cStringIO import StringIO except: from StringIO import StringIO @@ -602,7 +601,7 @@ GUESS_LINK_TARGETS = True def __init__(self, module_filename, module_name, - docindex=None, api_docs=None, url_func=None): + docindex=None, url_func=None, name_to_docs=None): """ Create a new HTML colorizer for the specified module. @@ -622,17 +621,18 @@ #: The dotted name of the module we're colorizing. self.module_name = module_name + #: A docindex, used to create href links from identifiers to + #: the API documentation for their values. self.docindex = docindex - #: A mapping from short names to lists of ValueDoc. - self.name_to_docs = {} - for api_doc in api_docs: - if (api_doc.canonical_name is not None and - url_func(api_doc) is not None): - name = api_doc.canonical_name[-1] - self.name_to_docs.setdefault(name,set()).add(api_doc) + #: A mapping from short names to lists of ValueDoc, used to + #: decide which values an identifier might map to when creating + #: href links from identifiers to the API docs for their values. + self.name_to_docs = name_to_docs - #: A function that maps APIDoc -> URL + #: A function that maps APIDoc -> URL, used to create href + #: links from identifiers to the API documentation for their + #: values. self.url_func = url_func #: The index in C{text} of the last character of the last @@ -935,7 +935,8 @@ # a function, then that function is our context, not # the namespace that contains it. [xx] this isn't always # the right thing to do. - if self.GUESS_LINK_TARGETS: + if (self.GUESS_LINK_TARGETS and self.docindex is not None + and self.url_func is not None): context = [n for n in self.context if n is not None] container = DottedName(self.module_name, *context) doc = self.docindex.get_vardoc(container+toktext) @@ -943,8 +944,9 @@ url = self.url_func(doc) # Otherwise, check the name_to_docs index to see what # else this name might refer to. - if url is None: - docs = sorted(self.name_to_docs.get(toktext, [])) + if (url is None and self.name_to_docs is not None + and self.url_func is not None): + docs = self.name_to_docs.get(toktext, []) if docs: tooltip='\n'.join([str(d.canonical_name) for d in docs]) @@ -1074,7 +1076,8 @@ elif isinstance(doc, StaticMethodDoc): return 'Static Method' elif isinstance(doc, RoutineDoc): - if isinstance(self.docindex.container(doc), ClassDoc): + if (self.docindex is not None and + isinstance(self.docindex.container(doc), ClassDoc)): return 'Method' else: return 'Function' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-09-23 19:18:11
|
Revision: 1622 http://epydoc.svn.sourceforge.net/epydoc/?rev=1622&view=rev Author: edloper Date: 2007-09-23 12:18:08 -0700 (Sun, 23 Sep 2007) Log Message: ----------- - Fixed svn bug 1700614 -- private known subclasses are shown always. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/html_css.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2007-09-23 18:54:23 UTC (rev 1621) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2007-09-23 19:18:08 UTC (rev 1622) @@ -860,9 +860,15 @@ if (doc.subclasses not in (UNKNOWN, None) and len(doc.subclasses) > 0): out('<dl><dt>Known Subclasses:</dt>\n<dd>\n ') - out(',\n '.join([self.href(c, context=doc) - for c in doc.subclasses])) - out('\n</dd></dl>\n\n') + out(' <ul class="subclass-list">\n') + for i, subclass in enumerate(doc.subclasses): + href = self.href(subclass, context=doc) + if self._val_is_public(subclass): css = '' + else: css = ' class="private"' + if i > 0: href = ', '+href + out('<li%s>%s</li>' % (css, href)) + out(' </ul>\n') + out('</dd></dl>\n\n') out('<hr />\n') @@ -1444,7 +1450,7 @@ elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")?"none":"block"); } } - // Update all table rowss containing private objects. Note, we + // Update all table rows containing private objects. Note, we // use "" instead of "block" becaue IE & firefox disagree on what // this should be (block vs table-row), and "" just gives the // default for both browsers. @@ -1459,7 +1465,7 @@ for(var i=0; i<elts.length; i++) { if (elts[i].className == "private") { elts[i].style.display = ((cmd && cmd.substr(0,4)=="hide")? - "none":"list-item"); + "none":""); } } // Update all list items containing private objects. @@ -3028,6 +3034,16 @@ #{ Helper functions #//////////////////////////////////////////////////////////// + def _val_is_public(self, valdoc): + """Make a best-guess as to whether the given class is public.""" + container = self.docindex.container(valdoc) + if container is not None: + for vardoc in container.variables.values(): + if vardoc in (UNKNOWN, None): continue + if vardoc.value is valdoc: + return vardoc.is_public + return True + # [XX] Is it worth-while to pull the anchor tricks that I do here? # Or should I just live with the fact that show/hide private moves # stuff around? Modified: trunk/epydoc/src/epydoc/docwriter/html_css.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_css.py 2007-09-23 18:54:23 UTC (rev 1621) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2007-09-23 19:18:08 UTC (rev 1622) @@ -201,6 +201,11 @@ .summary-sig-arg { color: $summary_sig_arg; } .summary-sig-default { color: $summary_sig_default; } +/* Subclass list + */ +ul.subclass-list { display: inline; } +ul.subclass-list li { display: inline; } + /* To render variables, classes etc. like functions */ table.summary .summary-name { color: $summary_sig_name; font-weight: bold; font-family: monospace; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2008-02-23 18:31:15
|
Revision: 1757 http://epydoc.svn.sourceforge.net/epydoc/?rev=1757&view=rev Author: edloper Date: 2008-02-23 10:31:10 -0800 (Sat, 23 Feb 2008) Log Message: ----------- - Copy *all* of the epydoc builtin latex style files to the target directory. This ensures that custom style files (which are now copied to epydoc-custom.sty) can use \RequirePackage to extend any of the builtin latex style files; and they can extend one another as well. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/latex.py trunk/epydoc/src/epydoc/docwriter/latex_sty.py Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2008-02-23 17:47:49 UTC (rev 1756) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2008-02-23 18:31:10 UTC (rev 1757) @@ -27,10 +27,10 @@ from epydoc.docwriter.latex_sty import STYLESHEETS class LatexWriter: - #: Expects (options,) + #: Expects (options, epydoc_sty_package) PREAMBLE = [ "\\documentclass{article}", - "\\usepackage[%s]{epydoc}", + "\\usepackage[%s]{%s}", "\\usepackage{graphicx}", ] @@ -144,7 +144,39 @@ copied to 'epydoc-default.sty', which makes it possible to reference it via \RequirePackage. """ + # Write all the standard style files + for (name, sty) in STYLESHEETS.items(): + out = open(os.path.join(directory, 'epydoc-%s.sty' % name), 'wb') + out.write(sty) + out.close() + + # Default: use the 'epydoc-default' style. if stylesheet is None: + self._epydoc_sty_package = 'epydoc-default' + + # Stylesheet name: use the indicated style. + elif stylesheet in STYLESHEETS: + self._epydoc_sty_package = 'epydoc-%s' % stylesheet + + # Custom user stylesheet: copy the style to epydoc-custom. + elif os.path.exists(stylesheet): + try: sty = open(stylesheet, 'rb').read() + except: raise IOError("Can't open LaTeX style file: %r" % + stylesheet) + out = open(os.path.join(directory, 'epydoc-custom.sty'), 'wb') + out.write(sty) + out.close() + self._epydoc_sty_package = 'epydoc-custom' + + else: + raise IOError("Can't find LaTeX style file: %r" % stylesheet) + + self._write_sty(directory, None, 'epydoc-default.sty') + + + + + if stylesheet is None: sty = STYLESHEETS['base'] elif os.path.exists(stylesheet): try: sty = open(stylesheet, 'rb').read() @@ -263,7 +295,8 @@ options = [] if self._index: options.append('index') if self._hyperlink: options.append('hyperlink') - out('\n'.join(self.PREAMBLE) % (','.join(options),) + '\n') + out('\n'.join(self.PREAMBLE) % (','.join(options), + self._epydoc_sty_package) + '\n') # Set the encoding. out('\\usepackage[%s]{inputenc}\n' % self.get_latex_encoding()) Modified: trunk/epydoc/src/epydoc/docwriter/latex_sty.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex_sty.py 2008-02-23 17:47:49 UTC (rev 1756) +++ trunk/epydoc/src/epydoc/docwriter/latex_sty.py 2008-02-23 18:31:10 UTC (rev 1757) @@ -606,11 +606,11 @@ % $Id:$ \NeedsTeXFormat{LaTeX2e} \ProvidesClass{epydoc}[2007/04/06 v3.0beta1 Epydoc Python Documentation] -\DeclareOption{index}{\PassOptionsToPackage{index}{epydoc-default}} -\DeclareOption{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-default}} +\DeclareOption{index}{\PassOptionsToPackage{index}{epydoc-base}} +\DeclareOption{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-base}} \ProcessOptions\relax -\RequirePackage{epydoc-default} +\RequirePackage{epydoc-base} % Double the standard size boxedminipage outlines. \setlength{\fboxrule}{2\fboxrule} @@ -821,11 +821,11 @@ % $Id:$ \NeedsTeXFormat{LaTeX2e} \ProvidesClass{epydoc}[2007/04/06 v3.0beta1 Epydoc Python Documentation] -\DeclareOption{index}{\PassOptionsToPackage{index}{epydoc-default}} -\DeclareOption{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-default}} +\DeclareOption{index}{\PassOptionsToPackage{index}{epydoc-base}} +\DeclareOption{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-base}} \ProcessOptions\relax -\RequirePackage{epydoc-default} +\RequirePackage{epydoc-base} \definecolor{gray95}{gray}{0.95} \definecolor{gray90}{gray}{0.90} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2008-03-04 02:31:58
|
Revision: 1806 http://epydoc.svn.sourceforge.net/epydoc/?rev=1806&view=rev Author: edloper Date: 2008-03-03 18:31:57 -0800 (Mon, 03 Mar 2008) Log Message: ----------- - Assorted improvements to latex output - EpydocFunction, EpydocVariable, and EpydocProperty commands now use xkeyval to pass arguments in a more readable and extensible manner. - Adjusted the output to fix indentation, and make the generated latex easier to read - Always write classes to separate files; and use \input to read them in. - Added function to parse latex output & look for warnings Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/latex.py trunk/epydoc/src/epydoc/docwriter/latex_sty.py Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2008-02-27 20:24:06 UTC (rev 1805) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2008-03-04 02:31:57 UTC (rev 1806) @@ -45,7 +45,7 @@ self.docindex = docindex # Process keyword arguments self._show_private = kwargs.get('show_private', 0) - self._prj_name = kwargs.get('prj_name', None) or 'API Documentation' + self._prj_name = kwargs.get('prj_name', None) self._show_crossrefs = kwargs.get('crossref', 1) self._index = kwargs.get('index', 1) self._hyperlink = kwargs.get('hyperlink', True) @@ -124,8 +124,7 @@ if isinstance(val_doc, ModuleDoc): filename = '%s-module.tex' % val_doc.canonical_name self._write(self.write_module, directory, filename, val_doc) - elif (isinstance(val_doc, ClassDoc) and - self._list_classes_separately): + elif isinstance(val_doc, ClassDoc): filename = '%s-class.tex' % val_doc.canonical_name self._write(self.write_class, directory, filename, val_doc) @@ -204,12 +203,8 @@ generate. @rtype: C{int} """ - n = 1 - for doc in self.valdocs: - if isinstance(doc, ModuleDoc): n += 1 - if isinstance(doc, ClassDoc) and self._list_classes_separately: - n += 1 - return n + return 1 + len([doc for doc in self.valdocs + if isinstance(doc, (ClassDoc, ModuleDoc))]) def _mkdir(self, directory): """ @@ -229,22 +224,23 @@ self.write_header(out, 'Include File') self.write_preamble(out) out('\n\\begin{document}\n\n') - self.write_start_of(out, 'Header') + out(self.start_of('Header')) # Write the title. - self.write_start_of(out, 'Title') - out('\\title{%s}\n' % plaintext_to_latex(self._prj_name, 1)) + out(self.start_of('Title')) + out('\\title{%s}\n' % plaintext_to_latex( + self._prj_name or 'API Documentation', 1)) out('\\author{API Documentation}\n') out('\\maketitle\n') # Add a table of contents. - self.write_start_of(out, 'Table of Contents') + out(self.start_of('Table of Contents')) out('\\addtolength{\\parskip}{-1ex}\n') out('\\tableofcontents\n') out('\\addtolength{\\parskip}{1ex}\n') # Include documentation files. - self.write_start_of(out, 'Includes') + out(self.start_of('Includes')) for val_doc in self.valdocs: if isinstance(val_doc, ModuleDoc): out('\\include{%s-module}\n' % val_doc.canonical_name) @@ -258,11 +254,11 @@ # Add the index, if requested. if self._index: - self.write_start_of(out, 'Index') + out(self.start_of('Index')) out('\\printindex\n\n') # Add the footer. - self.write_start_of(out, 'Footer') + out(self.start_of('Footer')) out('\\end{document}\n\n') def write_preamble(self, out): @@ -307,10 +303,10 @@ def write_module(self, out, doc): self.write_header(out, doc) - self.write_start_of(out, 'Module Description') + out(self.start_of('Section Heading', doc)) # Add this module to the index. - out(' ' + self.indexterm(doc, 'start')) + out(self.indexterm(doc, 'start')) # Add a section marker. out(self.section('%s %s' % (self.doc_kind(doc), @@ -319,12 +315,13 @@ # Add the module's description. if doc.descr not in (None, UNKNOWN): - out(' '*4 + '\\begin{EpydocModuleDescription}%\n') + out(self.start_of('Description', doc)) + out('\\begin{EpydocModuleDescription}%\n') out(self.docstring_to_latex(doc.descr, doc, 4)) - out(' '*4 + '\\end{EpydocModuleDescription}\n') + out('\\end{EpydocModuleDescription}\n') # Add version, author, warnings, requirements, notes, etc. - self.write_standard_fields(out, doc) + out(self.metadata(doc)) # If it's a package, list the sub-modules. if (self._list_submodules and self._show_submodule_list and @@ -342,39 +339,49 @@ if not self._list_classes_separately: classes = doc.select_variables(imported=False, value_type='class', public=self._public_filter) - for var_doc in classes: - self.write_class(out, var_doc.value) + if classes: + out(self.start_of('Classes', doc)) + for var_doc in classes: + # don't use \include -- can't be nested. + out('\\input{%s-class}\n' % var_doc.value.canonical_name) # Mark the end of the module (for the index) - out(' ' + self.indexterm(doc, 'end')) + out(self.start_of('Footer', doc)) + out(self.indexterm(doc, 'end')) def render_graph(self, graph): if graph is None: return '' graph.caption = graph.title = None return graph.to_latex(self._directory) or '' - def write_class(self, out, doc, short_name=None): - if short_name is None: short_name = doc.canonical_name[-1] - - if self._list_classes_separately: - self.write_header(out, doc) - self.write_start_of(out, 'Class Description') + def write_class(self, out, doc): + self.write_header(out, doc) + out(self.start_of('Section Heading', doc)) # Add this class to the index. - out(' ' + self.indexterm(doc, 'start')) + out(self.indexterm(doc, 'start')) - # Add a section marker. + # Decide on our short (contextualized) name. if self._list_classes_separately: + short_name = doc.canonical_name + if doc.defining_module not in (None, UNKNOWN): + short_name = doc.canonical_name.contextualize( + doc.defining_module.canonical_name) + else: + short_name = doc.canonical_name[-1] + + # Decidie on our initial section level. + if self._list_classes_separately: seclevel = 0 - out(self.section('%s %s' % (self.doc_kind(doc), - _dotted(doc.canonical_name)), - seclevel, ref=doc)) else: seclevel = 1 - out(self.section('%s %s' % (self.doc_kind(doc), - _dotted(short_name)), - seclevel, ref=doc)) + # Add a section marker. + out(self.section('%s %s' % (self.doc_kind(doc), _dotted(short_name)), + seclevel, ref=doc)) + + # Display our base classes & subclasses + out(self.start_of('Class Tree', 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. @@ -402,12 +409,13 @@ # The class's description. if doc.descr not in (None, UNKNOWN): - out(' '*4 + '\\begin{EpydocClassDescription}\n') - out(self.docstring_to_latex(doc.descr, doc)) - out(' '*4 + '\\end{EpydocClassDescription}\n') + out(self.start_of('Description', doc)) + out('\\begin{EpydocClassDescription}%\n') + out(self.docstring_to_latex(doc.descr, doc, 4)) + out('\\end{EpydocClassDescription}\n') # Version, author, warnings, requirements, notes, etc. - self.write_standard_fields(out, doc) + out(self.metadata(doc)) # Contents. self.write_list(out, 'Methods', doc, 'EpydocFunctionList', @@ -422,19 +430,24 @@ 'instancevariable', seclevel+1) # Mark the end of the class (for the index) - out(' ' + self.indexterm(doc, 'end')) + out(self.start_of('Footer', doc)) + out(self.indexterm(doc, 'end')) # Write any nested classes. These will have their own # section (at the same level as this section) - for nested_class in doc.select_variables(imported=False, - value_type='class', - public=self._public_filter): - if (nested_class.value.canonical_name != UNKNOWN and - (nested_class.value.canonical_name[:-1] == - doc.canonical_name)): - self.write_class(out, nested_class.value, - DottedName(short_name, - nested_class.canonical_name[-1])) + if not self._list_classes_separately: + nested_classes = doc.select_variables( + imported=False, value_type='class', + public=self._public_filter) + if nested_classes: + out(self.start_of('Nested Classes', doc)) + for nested_class in nested_classes: + if (nested_class.value.canonical_name != UNKNOWN and + (nested_class.value.canonical_name[:-1] == + doc.canonical_name)): + # don't use \include -- can't be nested. + out('\\input{%s-class}\n' % + nested_class.value.canonical_name) #//////////////////////////////////////////////////////////// #{ Module hierarchy trees @@ -456,7 +469,7 @@ def write_module_list(self, out, doc): if len(doc.submodules) == 0: return - self.write_start_of(out, 'Submodules') + out(self.start_of('Submodules', doc)) out(self.section('Submodules', 1)) out('\\begin{EpydocModuleList}\n') @@ -479,10 +492,11 @@ @rtype: C{string} """ - out(' '*depth + '\\item[%s]' % _hyperlink(doc, doc.canonical_name[-1])) + out(' '*depth + '\\item[%s]\n' % + _hyperlink(doc, doc.canonical_name[-1])) if doc.summary not in (None, UNKNOWN): - out(' %s\n' % self.docstring_to_latex(doc.summary, doc)) + out(self.docstring_to_latex(doc.summary, doc, depth+2)) out(self.crossref(doc) + '\n\n') if doc.submodules != UNKNOWN and doc.submodules: out(' '*depth + ' \\begin{EpydocModuleList}\n') @@ -498,7 +512,9 @@ if width is None: width = self._find_tree_width(doc)+2 linespec = [] - s = ('&'*(width-4)+'\\multicolumn{2}{l}{\\textbf{%s}}\n' % + s = (' %% Class tree line for this class (%s)\n ' % + doc.canonical_name + '&'*(width-4) + + '\\multicolumn{2}{l}{\\textbf{%s}}\n' % _dotted('%s'%self._base_name(doc))) s += '\\end{tabular}\n\n' top = 1 @@ -534,36 +550,36 @@ return width def _base_tree_line(self, doc, width, linespec): + # linespec is a list of booleans. base_name = _dotted(self._base_name(doc)) - # linespec is a list of booleans. - s = '%% Line for %s, linespec=%s\n' % (base_name, linespec) - + s = ' %% Class tree line for base "%s"\n' % self._base_name(doc) labelwidth = width-2*len(linespec)-2 # The base class name. - s += ('\\multicolumn{%s}{r}{' % labelwidth) - s += '\\settowidth{\\EpydocBCL}{%s}' % base_name - s += ('\\multirow{2}{\\EpydocBCL}{%s}}\n' % - _hyperlink(doc, self._base_name(doc))) + s += ' \\multicolumn{%s}{r}{\n' % labelwidth + s += ' \\settowidth{\\EpydocBCL}{%s}\n' % base_name + s += ' \\multirow{2}{\\EpydocBCL}{\n' + s += ' %s}}\n' % _hyperlink(doc, self._base_name(doc)) # The vertical bars for other base classes (top half) for vbar in linespec: - if vbar: s += '&&\\multicolumn{1}{|c}{}\n' - else: s += '&&\n' + if vbar: s += ' &&\\multicolumn{1}{|c}{}\n' + else: s += ' &&\n' # The horizontal line. - s += ' \\\\\\cline{%s-%s}\n' % (labelwidth+1, labelwidth+1) + s += ' \\\\\\cline{%s-%s}\n' % (labelwidth+1, labelwidth+1) # The vertical bar for this base class. - s += ' ' + '&'*labelwidth + s += ' ' + '&'*labelwidth s += '\\multicolumn{1}{c|}{}\n' # The vertical bars for other base classes (bottom half) for vbar in linespec: - if vbar: s += '&\\multicolumn{1}{|c}{}&\n' - else: s += '&&\n' - s += ' \\\\\n' + if vbar: s += ' &\\multicolumn{1}{|c}{}&\n' + else: s += ' &&\n' + + s += ' \\\\\n' return s @@ -583,7 +599,7 @@ if not groups: return # Write a header. - self.write_start_of(out, 'Classes') + out(self.start_of('Classes', doc)) out(self.section('Classes', 1)) out('\\begin{EpydocClassList}\n') @@ -605,8 +621,8 @@ 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, doc)) - out(self.crossref(doc) + '\n\n') + out(': %\n' + self.docstring_to_latex(doc.summary, doc)) + out(self.crossref(doc)) #//////////////////////////////////////////////////////////// #{ Details Lists @@ -627,8 +643,8 @@ if not groups: return # Write a header. - self.write_start_of(out, heading) - out(' '+self.section(heading, seclevel)) + out(self.start_of(heading, doc)) + out(self.section(heading, seclevel)) out('\\begin{%s}\n' % list_type) @@ -718,6 +734,15 @@ #//////////////////////////////////////////////////////////// #{ Function Details #//////////////////////////////////////////////////////////// + + def replace_par(self, out): + def new_out(s): + s = re.sub('(?m)\n([ \t]*\n)+', '\\par\n', s) + s = re.sub(r'\\par\b', r'\\EpydocPar', s) + s = re.sub(r'(?m)^([ \t]*)([^ \t].*)\\EpydocPar\n', + r'\1\2\n\1\\EpydocPar\n', s) + out(s) + return new_out def write_function(self, out, var_doc): func_doc = var_doc.value @@ -727,63 +752,73 @@ # select the containing section, and won't give a reference # directly to the function. if not is_inherited: - out(' %s%%\n' % self.indexterm(func_doc)) + out(' %s' % self.indexterm(func_doc)) - # This latex command takes 8 arguments. - out('\\EpydocFunction{%\n') + out(' \\EpydocFunction{%% <<< %s >>>\n' % var_doc.name) + # We're passing arguments using xkeyval, which is unhappy if + # the arguments contain \par. So replace every occurence of + # \par with \EpydocPar (which is defined to just return \par). + out = self.replace_par(out) + # Argument 1: the function signature - out(self.function_signature(var_doc)) - out('}{%\n') + out(' signature={%%\n%s }' % + self.function_signature(var_doc)) # Argument 2: the function description if func_doc.descr not in (None, UNKNOWN): - out(self.docstring_to_latex(func_doc.descr, func_doc, 4)) - out('}{%\n') + out(',\n description={%\n') + out(self.docstring_to_latex(func_doc.descr, func_doc, 6)) + out(' }') # Argument 3: the function parameter descriptions if func_doc.arg_descrs or func_doc.arg_types: + out(',\n parameters={%\n') self.write_function_parameters(out, var_doc) - out('}{%\n') + out(' }') # Argument 4: The return description if func_doc.return_descr not in (None, UNKNOWN): - out(self.docstring_to_latex(func_doc.return_descr, - func_doc, 6)) - out('}{%\n') + out(',\n returndescr={%\n') + out(self.docstring_to_latex(func_doc.return_descr, func_doc, 6)) + out(' }') # Argument 5: The return type if func_doc.return_type not in (None, UNKNOWN): - out(self.docstring_to_latex(func_doc.return_type, - func_doc, 6).strip()) - out('}{%\n') + out(',\n returntype={%\n') + out(self.docstring_to_latex(func_doc.return_type, func_doc, 6)) + out(' }') # Argument 6: The raises section if func_doc.exception_descrs not in (None, UNKNOWN, [], ()): + out(',\n raises={%\n') 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, func_doc, 10)) - out(' '*6+'\\end{EpydocFunctionRaises}\n\n') - out('}{%\n') + out(' '*6+'\\end{EpydocFunctionRaises}\n') + out(' }') # Argument 7: The overrides section if var_doc.overrides not in (None, UNKNOWN): + out(',\n overrides={%\n') 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' + out('{%s}\n' % _hyperlink(var_doc.overrides, '%s' % var_doc.overrides.canonical_name)) - out('}{%\n') + out(' }') # Argument 8: The metadata section - self.write_standard_fields(out, func_doc) - out('}\n') - + metadata = self.metadata(func_doc, 6) + if metadata: + out(',\n metadata={%%\n%s }' % metadata) + out('}%\n') + def write_function_parameters(self, out, var_doc): func_doc = var_doc.value # Find the longest name. @@ -803,7 +838,7 @@ # 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)) + out('%s\\item[%s]\n' % (' '*8, arg_name)) if arg_descr: out(self.docstring_to_latex(arg_descr, func_doc, 10)) # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -816,16 +851,17 @@ lhs = 'type' else: lhs = 'type of %s' % arg_name - rhs = self.docstring_to_latex(arg_typ, func_doc).strip() - out('%s{\\it (%s=%s)}\n\n' % (' '*12, lhs, rhs)) - out(' '*6+'\\end{EpydocFunctionParameters}\n\n') + rhs = self.docstring_to_latex(arg_typ, func_doc, 14) + out('%s\\textit{ (%s=%%\n%s%s)}\n' % (' '*12, lhs, + rhs, ' '*12)) + out(' '*6+'\\end{EpydocFunctionParameters}\n') - def function_signature(self, var_doc): + def function_signature(self, var_doc, indent=6): func_doc = var_doc.value func_name = var_doc.name - s = ('\\begin{EpydocFunctionSignature}{%s}%%\n' % - _hypertarget(var_doc, func_name)) + s = ('%s\\begin{EpydocFunctionSignature}%%\n%s {%s}%%\n' % + (indent*' ', indent*' ', _hypertarget(var_doc, func_name))) # This should never happen, but just in case: if func_doc not in (None, UNKNOWN): @@ -842,9 +878,10 @@ 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' + + argindent = (indent*' '+' ') + s += argindent+('%%\n%s\\and' % argindent).join(args)+'%\n' + s += indent*' '+'\\end{EpydocFunctionSignature}%\n' return s @@ -869,66 +906,80 @@ #//////////////////////////////////////////////////////////// def write_var(self, out, var_doc): + # We're passing arguments using xkeyval, which is unhappy if + # the arguments contain \par. So replace every occurence of + # \par with \EpydocPar (which is defined to just return \par). + out = self.replace_par(out) + has_descr = var_doc.descr not in (None, UNKNOWN) has_type = var_doc.type_descr not in (None, UNKNOWN) 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)) + + out(' \\EpydocVariable{%% <<< %s >>>\n' % var_doc.name) + out(' name={%s}' % _hypertarget(var_doc, var_doc.name)) if has_descr: - out(self.docstring_to_latex(var_doc.descr, var_doc, 10).strip()) - out('}{') + out(',\n description={%%\n%s }' % + self.docstring_to_latex(var_doc.descr, var_doc, 6)) if has_type: - out(self.docstring_to_latex(var_doc.type_descr, - var_doc, 12).strip()) - out('}{') + out(',\n type={%%\n%s }' % + self.docstring_to_latex(var_doc.type_descr, var_doc, 6)) if has_repr: - out(var_doc.value.summary_pyval_repr().to_latex(None)) - out('}\n') + out(',\n value={%s}' % + var_doc.value.summary_pyval_repr().to_latex(None)) + metadata = self.metadata(var_doc, 6) + if metadata: + out(',\n metadata={%%\n%s }' % metadata) + out('}%\n') #//////////////////////////////////////////////////////////// #{ Property Details #//////////////////////////////////////////////////////////// def write_property(self, out, var_doc): + # We're passing arguments using xkeyval, which is unhappy if + # the arguments contain \par. So replace every occurence of + # \par with \EpydocPar (which is defined to just return \par). + out = self.replace_par(out) + prop_doc = var_doc.value has_descr = prop_doc.descr not in (None, UNKNOWN) has_type = prop_doc.type_descr not in (None, UNKNOWN) - out('\\EpydocProperty{%s}{' % _hypertarget(var_doc, var_doc.name)) + + out(' \\EpydocProperty{%% <<< %s >>>\n' % var_doc.name) + out(' name={%s}' % _hypertarget(var_doc, var_doc.name)) if has_descr: - out(self.docstring_to_latex(prop_doc.descr, - prop_doc, 10).strip()) - out('}{') + out(',\n description={%%\n%s }' % + self.docstring_to_latex(prop_doc.descr, prop_doc, 6)) if has_type: - out(self.docstring_to_latex(prop_doc.type_descr, - prop_doc, 12).strip()) - out('}{') + out(',\n type={%%\n%s }' % + self.docstring_to_latex(prop_doc.type_descr, prop_doc, 6)) # [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') + for accessor in ('fget', 'fset', 'fdel'): + accessor_func = getattr(prop_doc, accessor) + if (accessor_func not in (None, UNKNOWN) and + not accessor_func.canonical_name[0].startswith('??')): + if isinstance(accessor_func, RoutineDoc): + suffix = '()' + else: + suffix = '' + out(',\n %s={%s%s}' % + (accessor, _dotted(accessor_func.canonical_name), suffix)) + metadata = self.metadata(prop_doc, 6) + if metadata: + out(',\n metadata={%%\n%s }' % metadata) + out('}%\n') #//////////////////////////////////////////////////////////// #{ Standard Fields #//////////////////////////////////////////////////////////// - # Copied from HTMLWriter: - def write_standard_fields(self, out, doc): + def metadata(self, doc, indent=0): fields = [] field_values = {} + s = '' - #if _sort_fields: fields = STANDARD_FIELD_NAMES [XX] - for (field, arg, descr) in doc.metadata: if field not in field_values: fields.append(field) @@ -938,38 +989,49 @@ else: field_values.setdefault(field,[]).append(descr) + if fields and indent == 0: + s += self.start_of('Metadata', doc) + for field in fields: if field.takes_arg: for arg, descrs in field_values[field].items(): - self.write_standard_field(out, doc, field, descrs, arg) - + s += self.meatadata_field(doc, field, descrs, + indent, arg) else: - self.write_standard_field(out, doc, field, field_values[field]) + s += self.meatadata_field(doc, field, field_values[field], + indent) + return s + - def write_standard_field(self, out, doc, field, descrs, arg=''): + def meatadata_field(self, doc, field, descrs, indent, arg=''): singular = field.singular plural = field.plural if arg: singular += ' (%s)' % arg plural += ' (%s)' % arg - out(self._descrlist([self.docstring_to_latex(d, doc) for d in descrs], - field.singular, field.plural, field.short)) - - def _descrlist(self, items, singular, plural=None, short=0): + return (' '*indent + '%% %s:\n' % field.singular + + self._descrlist([self.docstring_to_latex(d, doc, indent+2) + for d in descrs], + field.singular, field.plural, field.short, + indent)) + + # [xx] ignores indent for now + def _descrlist(self, items, singular, plural=None, short=0, indent=0): + ind = indent*' ' if plural is None: plural = singular if len(items) == 0: return '' if len(items) == 1 and singular is not None: - return ('\\EpydocMetadataSingleValue{%s}{%s}\n\n' % - (singular, items[0])) + return ('%s\\EpydocMetadataSingleValue{%s}{\n%s%s}\n' % + (ind, singular, items[0], ind)) if short: - s = '\\begin{EpydocMetadataShortList}{%s}%%\n ' % plural - s += '%\n \\and '.join([item.strip() for item in items]) - s += '%\n\\end{EpydocMetadataShortList}\n\n' + s = '%s\\begin{EpydocMetadataShortList}{%s}\n' % (ind, plural) + s += ('%s\\and\n' % ind).join(items) + s += '%s\\end{EpydocMetadataShortList}\n' % ind return s else: - s = '\\begin{EpydocMetadataLongList}{%s}%%\n' % plural - s += '\n\n'.join([' \item %s%%' % item for item in items]) - s += '\n\\end{EpydocMetadataLongList}\n\n' + s = '%s\\begin{EpydocMetadataLongList}{%s}\n' % (ind, plural) + s += ''.join(['%s \item\n%s' % (ind,item) for item in items]) + s += '%s\\end{EpydocMetadataLongList}\n' % ind return s @@ -989,15 +1051,20 @@ _docstring_linker = _LatexDocstringLinker() def docstring_to_latex(self, docstring, where, indent=0, breakany=0): + """ + Return a latex string that renders the given docstring. This + string expects to start at the beginning of a line; and ends + with a newline. + """ if docstring is None: return '' - s = docstring.to_latex(self._docstring_linker, indent=indent, + s = docstring.to_latex(self._docstring_linker, indent=indent+2, directory=self._directory, docindex=self.docindex, context=where, hyperref=self._hyperref) - return (' '*indent + '\\begin{EpydocDescription}%\n' + - s.strip() + '%\n' + - ' '*indent + '\\end{EpydocDescription}\n\n') + return (' '*indent + '\\begin{EpydocDescription}\n' + + ' '*indent + ' ' + s.strip() + '%\n' + + ' '*indent + '\\end{EpydocDescription}\n') #//////////////////////////////////////////////////////////// #{ Helpers @@ -1013,10 +1080,10 @@ out('\n%%\n%% Generated by epydoc %s\n' % epydoc.__version__) out('%% [%s]\n%%\n' % time.asctime(time.localtime(time.time()))) - def write_start_of(self, out, section_name): - out('\n' + 75*'%' + '\n') - out('%%' + section_name.center(71) + '%%\n') - out(75*'%' + '\n\n') + def start_of(self, section_name, doc=None): + return ('\n' + 75*'%' + '\n' + + '%%' + section_name.center(71) + '%%\n' + + 75*'%' + '\n\n') def section(self, title, depth=0, ref=None): sec = self.SECTIONS[depth+self._top_section] @@ -1058,8 +1125,9 @@ # [xx] list modules, classes, and functions as top-level index # items. Methods are listed under their classes. Nested classes # are listed under their classes. - def indexterm(self, doc, pos='only'): - """Mark a term or section for inclusion in the index.""" + def indexterm(self, doc, pos='only', indent=0): + """Return a latex string that marks the given term or section + for inclusion in the index. This string ends with a newline.""" if not self._index: return '' if isinstance(doc, RoutineDoc) and not self._index_functions: return '' @@ -1078,8 +1146,10 @@ pieces.reverse() kinds.reverse() for i in range(1, len(pieces)): - pieces[i] = '%s.%s' % (pieces[i-1], pieces[i]) - pieces = ['\\EpydocIndex{%s}{%s}{%s}' % (piece.lower(), piece, kind) + if not kinds[i].endswith('method'): + pieces[i] = '%s.%s' % (pieces[i-1], pieces[i]) + pieces = ['\\EpydocIndex{%s}{%s}{%s}' % + (_dotted(piece.lower()), _dotted(piece), kind) for (piece, kind) in zip (pieces, kinds)] if pos == 'only': modifier = '' @@ -1087,9 +1157,7 @@ elif pos == 'end': modifier = '|)' else: raise AssertionError('Bad index position %s' % pos) - term = '\\index{%s%s}\n' % ('!'.join(pieces), modifier) - - return term + return '%s\\index{%s%s}%%\n' % (' '*indent, '!'.join(pieces), modifier) #: Map the Python encoding representation into mismatching LaTeX ones. latex_encodings = { @@ -1104,16 +1172,26 @@ enc = self._encoding.lower() return self.latex_encodings.get(enc, enc) - def crossref(self, doc): + def crossref(self, doc, indent=0): if (self._show_crossrefs and ((isinstance(doc, ModuleDoc) and doc in self.module_set) or (isinstance(doc, ClassDoc) and doc in self.class_set))): - return '\\CrossRef{%s}' % (_label(doc),) + return '%s\\CrossRef{%s}%%\n' % (' '*indent, _label(doc),) else: return '' def _label(doc): - return ':'.join(doc.canonical_name) + # Convert to a string & replace . and _. + s = '%s' % doc.canonical_name + s = s.replace('.', ':').replace('_','-') + + # Get rid of any other characters. This is necessary only if + # we're processing a script (whose name can be just about + # anything), an unreachable value, or an object whose name has + # been mangled with black magic. + s = re.sub('[^\w:-]', '-', s) + + return s # [xx] this should get used more often than it does, I think: def _hyperlink(target, name): @@ -1124,5 +1202,90 @@ def _dotted(name): if not name: return '' + name = '%s' % name + # There are a couple of characters that even \\EpydocDottedName + # can't cope with; so filter them out. + name = re.sub('[%#]|\^\^+|\n', '?', name) return '\\EpydocDottedName{%s}' % name +LATEX_WARNING_RE = re.compile('|'.join([ + r'(?P<file>\([\.a-zA-Z_\-/\\ \n0-9]+[.\n][a-z]{2,3}\b)', + (r'(?P<pkgwarn>^(Package|Latex) (?P<pkgname>[\w-]+) '+ + r'Warning:[^\n]*\n(\((?P=pkgname)\)[^\n]*\n)*)'), + r'(?P<overfull>^(Overfull|Underfull)[^\n]*\n[^\n]*)', + r'(?P<latexwarn>^LaTeX\s+Warning:\s+[^\n]*)', + r'(?P<otherwarn>^[^\n]*Warning:[^\n]*)', + r'(?P<paren>[()])']), + re.MULTILINE+re.IGNORECASE) + +OVERFULL_RE = re.compile( + r'(?P<typ>Underfull|Overfull)\s+\\(?P<boxtype>[vh]box)\s+' + r'\((?P<size>\d+)[^\n\)]+\)[^\n]+\s+lines\s+' + r'(?P<start>\d+)') + +IGNORE_WARNING_REGEXPS = [ + re.compile(r'LaTeX\s+Font\s+Warning:\s+.*\n\(Font\)\s*using.*instead'), + re.compile(r'LaTeX\s+Font\s+Warning:\s+Some\s+font\s+shapes\s+' + r'were\s+not\s+available,\s+defaults\s+substituted.'), + ] + +def show_latex_warnings(s): + s = re.sub('(.{79,79})\n', r'\1', s) + + #[xx] we should probably pay special attention to overfull \vboxes. + overfull = underfull = 0 + filestack = ['latex'] + for m in LATEX_WARNING_RE.finditer(s): + # Check if it's something we don't care about. + for regexp in IGNORE_WARNING_REGEXPS: + if regexp.match(m.group()): + m = None; break + if m is None: continue + # LaTeX started reading a new file: + if m.group('file'): + filename = ''.join(m.group('file')[1:].split()) + filename = re.sub(r'^\./', '', filename) + filestack.append(filename) + # Latex reported an overfull/underfull warning: + elif m.group('overfull'): + msg = m.group('overfull').strip().split('\n')[0] + if msg.lower().startswith('overfull'): overfull += 1 + else: underfull += 1 + m2 = OVERFULL_RE.match(msg) + if m2: + if m2.group('boxtype') == 'vbox': + log.warning('%s: %s' % (filestack[-1], msg)) + elif (m2.group('typ').lower()=='overfull' and + int(m2.group('size')) > 50): + log.warning('%s: %s' % (filestack[-1], msg)) + else: + log.debug('%s: %s' % (filestack[-1], msg)) + else: + log.debug('%s: %s' % (filestack[-1], msg)) + # Latex reported a warning: + elif m.group('latexwarn'): + msg = m.group('latexwarn').strip() + log.warning('%s: %s' % (filestack[-1], msg)) + # A package reported a warning: + elif m.group('pkgwarn'): + msg = m.group('pkgwarn').strip() + log.warning('%s:\n%s' % (filestack[-1], msg)) + else: + # Display anything else that looks like a warning: + if m.group('otherwarn'): + msg = m.group('otherwarn').strip() + log.warning('%s: %s' % (filestack[-1], msg)) + # Update to account for parens. + n = m.group().count('(') - m.group().count(')') + if n > 0: filestack += [None] * n + if n < 0: del filestack[n:] + if overfull or underfull: + msgs = [] + if overfull == 1: msgs.append('1 overfull box') + elif overfull: msgs.append('%d overfull boxes' % overfull) + if underfull == 1: msgs.append('1 underfull box') + elif underfull: msgs.append('%d underfull boxes' % underfull) + log.warning('LaTeX reported %s' % ' and '.join(msgs)) + +#log.register_logger(log.SimpleLogger(log.DEBUG)) +#show_latex_warnings(open('/tmp/po.test').read()) Modified: trunk/epydoc/src/epydoc/docwriter/latex_sty.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex_sty.py 2008-02-27 20:24:06 UTC (rev 1805) +++ trunk/epydoc/src/epydoc/docwriter/latex_sty.py 2008-03-04 02:31:57 UTC (rev 1806) @@ -75,6 +75,7 @@ \RequirePackage[headings]{fullpage} \RequirePackage[usenames]{color} \RequirePackage{graphicx} +\RequirePackage{url} \@ifclassloaded{memoir}{% \RequirePackage[other,notbib]{tocbibind} @@ -130,6 +131,11 @@ % Create a 'base class' length named EpydocBCL for use in base trees. \newlength{\EpydocBCL} % base class length, for base trees. +% In xkeyval arguments, we're not allowed to use \par. But we *are* +% allowed to use a command that evaluates to \par, so define such a +% command. +\newcommand{\EpydocPar}{\par} + % ====================================================================== % Sections inside docstring @@ -192,17 +198,17 @@ % it to its default value). \newenvironment{EpydocDescription}{% \setlength{\parskip}{\EpydocParskip}% - }{} + \ignorespaces}{\ignorespacesafterend} % This environment is used to mark the description for a class % (which comes from the function's docstring). \newenvironment{EpydocClassDescription}{% - }{} + \ignorespaces}{\ignorespacesafterend} % This environment is used to mark the description for a module % (which comes from the function's docstring). \newenvironment{EpydocModuleDescription}{% - }{} + \ignorespaces}{\ignorespacesafterend} % ====================================================================== % Python Source Code Syntax Highlighting. @@ -323,36 +329,31 @@ % % All arguments except for the first (the signature) may be empty. % +\define@cmdkeys[Epydoc]{function}{signature,description,parameters, + returndescr,returntype,raises, + overrides,metadata} \newenvironment{EpydocFunctionList}{% - \newcommand{\EpydocFunction}[8]{ - \gdef\@EpydocFunctionSignature{##1}% - \gdef\@EpydocFunctionDescription{##2}% - \gdef\@EpydocFunctionParameters{##3}% - \gdef\@EpydocFunctionReturnDescr{##4}% - \gdef\@EpydocFunctionReturnType{##5}% - \gdef\@EpydocFunctionRaises{##6}% - \gdef\@EpydocFunctionOverrides{##7}% - \gdef\@EpydocFunctionMetadata{##8}% - {\Large\raggedright\@EpydocFunctionSignature\par} - \begin{quote}% - \setlength{\parskip}{\EpydocParskip}% - \ifx\@EpydocFunctionDescription\empty\else - \par\@EpydocFunctionDescription\fi% - \ifx\@EpydocFunctionParameters\empty\else - \par\@EpydocFunctionParameters\fi% - \ifx\@EpydocFunctionReturnDescr\empty - \par\@EpydocFunctionReturnDescr\fi% - \ifx\@EpydocFunctionReturnType\empty - \par\@EpydocFunctionReturnType\fi% - \ifx\@EpydocFunctionRaises\empty\else - \par\@EpydocFunctionRaises\fi% - \ifx\@EpydocFunctionOverrides\empty\else - \par\@EpydocFunctionOverrides\fi% - \ifx\@EpydocFunctionMetadata\empty\else - \par\@EpydocFunctionMetadata\fi% - \end{quote} - - }} + \newcommand{\EpydocFunction}[1]{{% + \setkeys[Epydoc]{function}{##1}% + {\Large\raggedright\cmdEpydoc@function@signature\par} + \begin{quote}% + \setlength{\parskip}{\EpydocParskip}% + \@ifundefined{cmdEpydoc@function@description}{}{ + \par\cmdEpydoc@function@description} + \@ifundefined{cmdEpydoc@function@parameters}{}{ + \par\cmdEpydoc@function@parameters} + \@ifundefined{cmdEpydoc@function@returndescr}{}{ + \par \textbf{Returns:} \cmdEpydoc@function@returndescr} + \@ifundefined{cmdEpydoc@function@returntype}{}{ + \par \textbf{Return Type:} \cmdEpydoc@function@returntype} + \@ifundefined{cmdEpydoc@function@raises}{}{ + \par\cmdEpydoc@function@raises} + \@ifundefined{cmdEpydoc@function@overrides}{}{ + \par\cmdEpydoc@function@overrides} + \@ifundefined{cmdEpydoc@function@metadata}{}{ + \ifx\cmdEpydoc@function@metadata\empty\else + \par\cmdEpydoc@function@metadata\fi} + \end{quote}\par}}} {} % The EpydocFunctionSignature environment is used to display a @@ -382,7 +383,7 @@ \textit{##2}% \ifthenelse{\equal{##1}{}}{}{=\texttt{##1}}}% \@hangfrom{\textbf{#1}(}% - }{)\par} + }{)} % The EpydocFunctionParameters environment is used to display % descriptions for the parameters that a function can take. @@ -439,23 +440,23 @@ % % If any of these arguments is not available, then the empty % string will be used. +\define@cmdkeys[Epydoc]{variable}{name,description,type,value,metadata} \newenvironment{EpydocVariableList}{% - \newcommand{\EpydocVariable}[4]{% - \gdef\@EpydocVariableName{##1}% - \gdef\@EpydocVariableDescription{##2}% - \gdef\@EpydocVariableType{##3}% - \gdef\@EpydocVariableValue{##4}% - {\Large\raggedright\@EpydocVariableName\par} - \begin{quote} - \setlength{\parskip}{\EpydocParskip}% - \ifx\@EpydocVariableDescription\empty\else - \par\@EpydocVariableDescription\fi% - \ifx\@EpydocVariableType\empty\else - \par\textbf{Type:} \@EpydocVariableType\fi% - \ifx\@EpydocVariableValue\empty - \par\textbf{Value:} \texttt{\@EpydocVariableValue}\fi% - \end{quote} - }} + \newcommand{\EpydocVariable}[1]{{% + \setkeys[Epydoc]{variable}{##1}% + {\Large\raggedright\cmdEpydoc@variable@name\par} + \begin{quote} + \setlength{\parskip}{\EpydocParskip}% + \@ifundefined{cmdEpydoc@variable@description}{}{% + \par\cmdEpydoc@variable@description}% + \@ifundefined{cmdEpydoc@variable@type}{}{% + \par\textbf{Type:} \cmdEpydoc@variable@type}% + \@ifundefined{cmdEpydoc@variable@value}{}{% + \par\textbf{Value:} \cmdEpydoc@variable@value}% + \@ifundefined{cmdEpydoc@variable@metadata}{}{% + \ifx\cmdEpydoc@variable@metadata\empty\else + \par\cmdEpydoc@variable@metadata\fi}% + \end{quote}\par}}} {} % The EpydocClassVariableList environment is used the same way as @@ -486,29 +487,28 @@ % % If any of these arguments is not available, then the empty % string will be used. +\define@cmdkeys[Epydoc]{property}{name,description,type,fget, + fset,fdel,metadata} \newenvironment{EpydocPropertyList}{% - \newcommand{\EpydocProperty}[6]{% - \gdef\@EpydocPropertyName{##1}% - \gdef\@EpydocPropertyDescription{##2}% - \gdef\@EpydocPropertyType{##3}% - \gdef\@EpydocPropertyGet{##4}% - \gdef\@EpydocPropertySet{##5}% - \gdef\@EpydocPropertyDel{##6}% - {\Large\raggedright\@EpydocPropertyName\par} - \begin{quote} - \setlength{\parskip}{\EpydocParskip}% - \ifx\@EpydocPropertyDescription\empty\else - \par\@EpydocPropertyDescription\fi% - \ifx\@EpydocPropertyType\empty\else - \par\textbf{Type:} \@EpydocPropertyType\fi% - \ifx\@EpydocPropertyGet\empty - \par\textbf{Get:} \texttt{\@EpydocPropertyGet}\fi% - \ifx\@EpydocPropertySet\empty - \par\textbf{Set:} \texttt{\@EpydocPropertySet}\fi% - \ifx\@EpydocPropertyDel\empty - \par\textbf{Delete:} \texttt{\@EpydocPropertyDel}\fi% - \end{quote} - }} + \newcommand{\EpydocProperty}[1]{{% + \setkeys[Epydoc]{property}{##1}% + {\Large\raggedright\cmdEpydoc@property@name\par} + \begin{quote} + \setlength{\parskip}{\EpydocParskip}% + \@ifundefined{cmdEpydoc@property@description}{}{ + \par\cmdEpydoc@property@description} + \@ifundefined{cmdEpydoc@property@type}{}{ + \par\textbf{Type:} \cmdEpydoc@property@type} + \@ifundefined{cmdEpydoc@property@fget}{}{ + \par\textbf{Get:} \cmdEpydoc@property@fget} + \@ifundefined{cmdEpydoc@property@fset}{}{ + \par\textbf{Set:} \cmdEpydoc@property@fset} + \@ifundefined{cmdEpydoc@property@fdel}{}{ + \par\textbf{Delete:} \cmdEpydoc@property@fdel} + \@ifundefined{cmdEpydoc@property@metadata}{}{ + \ifx\cmdEpydoc@property@metadata\empty\else + \par\cmdEpydoc@property@metadata\fi} + \end{quote}\par}}} {} % ====================================================================== @@ -516,28 +516,32 @@ % This command is used to display a metadata field with a single value \newcommand{\EpydocMetadataSingleValue}[2]{% + \par \begin{list}{}{\itemindent-\leftmargin} \item \textbf{#1:} #2 - \end{list} - } + \end{list}\par\ignorespaces} % This environment is used to display a metadata field with multiple % values when the field declares that short=True; i.e., that multiple % values should be combined into a single comma-delimited list. \newenvironment{EpydocMetadataShortList}[1]{% \newcommand{\and}{, }% - \textbf{#1: }} - {} + \par + \begin{list}{}{\itemindent-\leftmargin} + \item \textbf{#1:} \ignorespaces} + {\end{list}\ignorespacesafterend\par} % This list environment is used to display a metadata field with % multiple values when the field declares that short=False; i.e., that % multiple values should be listed separately in a bulleted list. \newenvironment{EpydocMetadataLongList}[1]{% + \par \textbf{#1:} \setlength{\parskip}{0ex} \begin{itemize} - \setlength{\parskip}{\EpydocMetadataLongListParskip}} - {\end{itemize}} + \setlength{\parskip}{\EpydocMetadataLongListParskip} + \ignorespaces} + {\end{itemize}\ignorespacesafterend\par} % ====================================================================== % reStructuredText Admonitions @@ -545,19 +549,16 @@ % This environment is used to display reStructuredText admonitions, % such as ``..warning::'' and ``..note::''. \newenvironment{reSTadmonition}[1][]{% - \begin{center}\begin{sffamily} - \begin{lrbox}{\@tempboxa} - \begin{minipage}{\admonitionwidth} - \textbf{\large #1} - \vspace{2mm} - } - { - \end{minipage} - \end{lrbox} - \fbox{\usebox{\@tempboxa}} - \end{sffamily} - \end{center} - } + \begin{center}\begin{sffamily}% + \begin{lrbox}{\@tempboxa}% + \begin{minipage}{\admonitionwidth}% + \textbf{\large #1}% + \vspace{2mm}}% + {\end{minipage}% + \end{lrbox}% + \fbox{\usebox{\@tempboxa}}% + \end{sffamily}% + \end{center}} % ====================================================================== % Name Formatting @@ -565,27 +566,24 @@ % This section defines the EpydocDottedName command, which is used to % display the names of Python objects. -% Allows non-hyphenated wrapping at the '.' module separators. The -% rest is a simplified version of url.sty's tt style. -\RequirePackage{url} -\def\Url@pydo{% style assignments for tt fonts or T1 encoding -\def\UrlBreaks{\do\]\do\)\do\_}% -\def\UrlBigBreaks{\do@url@hyp\do\.}% -% \def\UrlNoBreaks{\do\(\do\[\do\{\do\<\do\_}% (unnecessary) -\def\UrlNoBreaks{\do\(\do\[\do\{\do\<}% (unnecessary) -\def\UrlSpecials{\do\ {\ }}% -\def\UrlOrds{\do\*\do\-\do\~}% any ordinary characters that aren't usually -} +% The \EpydocDottedName command is used to escape dotted names. In +% particular, it escapes all characters except '#', '%', and newlines, +% and allows non-hyphenated wrapping at '.' separator characters. +% [xx] this generates a warning for names containing _ -- we need +% to somehow strip that out of the second argument. +\newcommand\EpydocDottedName[1]{% + \texorpdfstring{\protect\Epydoc@DottedName{#1}}{#1}} -\def\url@pystyle{% -\@ifundefined{selectfont}{\def\UrlFont{\rm}}{\def\UrlFont{\rmfamily}}\Url@pydo +\DeclareUrlCommand\Epydoc@DottedName{% + \urlstyle{rm}% + \def\UrlBigBreaks{\do\.}% + % We should never see most of these chars in a name, but handle + % them if they happen to show up (eg script names) + \def\UrlOrds{\do\@\do\#\do\%\do\^\do\&\do\(\do\)\do\-\do\_% + \do\|\do\\\do\"\do\/\do\?\do\>\do\<\do\{\do\}% + \do\`\do\~} } -\newcommand\pymodule{\begingroup \urlstyle{py}\Url} -% The \EpydocDottedName command is used to escape dotted names. In -% particular, it escapes underscores (_) and allows non-hyphenated -% wrapping at '.' separator characters. -\newcommand\EpydocDottedName[1]{\texorpdfstring{\protect\pymodule{#1}}{#1}} """+NIST_DISCLAIMER ###################################################################### ###################################################################### @@ -607,15 +605,14 @@ % $Id:$ \NeedsTeXFormat{LaTeX2e} \ProvidesClass{epydoc-boxes}[2008/02/26 v3.0.1 Epydoc Python Documentation] - +% Pass options to the epydoc base package. \RequirePackage{xkeyval} -\DeclareOptionX{index}{\PassOptionsToPackage{index}{epydoc-base}} -\DeclareOptionX{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-base}} -\DeclareOptionX{title}[]{\PassOptionsToPackage{title={#1}}{epydoc-base}} -\DeclareOptionX{creator}[]{\PassOptionsToPackage{creator={#1}}{epydoc-base}} +\DeclareOptionX*{\PassOptionsToPackage{\CurrentOption}{epydoc-base}} \ProcessOptionsX\relax - +% Load the base epydoc package \RequirePackage{epydoc-base} + +% Use longtable for variable & property lists. \RequirePackage{longtable} % Double the standard size boxedminipage outlines. @@ -636,60 +633,50 @@ \renewenvironment{EpydocFunctionList}{% \def\@EpydocSeparator{% \vspace{-2\EpydocParskip} - \rule{\dimexpr \textwidth-2\fboxsep \relax}{0.5\fboxrule} + \rule{\dimexpr \textwidth-2\fboxsep}{0.5\fboxrule} \aftergroup\def\aftergroup\@EpydocSeparator% \aftergroup{\aftergroup}}% - \newcommand{\EpydocFunction}[8]{ - \gdef\@EpydocFunctionSignature{##1}% - \gdef\@EpydocFunctionDescription{##2}% - \gdef\@EpydocFunctionParameters{##3}% - \gdef\@EpydocFunctionReturnDescr{##4}% - \gdef\@EpydocFunctionReturnType{##5}% - \gdef\@EpydocFunctionRaises{##6}% - \gdef\@EpydocFunctionOverrides{##7}% - \gdef\@EpydocFunctionMetadata{##8}% - \begin{boxedminipage}{\dimexpr \textwidth-2\fboxsep \relax} - {\Large\raggedright\@EpydocFunctionSignature\par} - \setlength{\parskip}{\EpydocParskip} - \ifx\@EpydocFunctionDescription\empty\else% - {\@EpydocSeparator}% - \@EpydocFunctionDescription % - \fi% - \ifx\@EpydocFunctionParameters\empty\else% - {\@EpydocSeparator}% - \@EpydocFunctionParameters % - \fi% - \ifx\@EpydocFunctionReturnType\empty% - \ifx\@EpydocFunctionReturnDescr\empty\else% + \newcommand{\EpydocFunction}[1]{{% + \setkeys[Epydoc]{function}{##1}% + \begin{boxedminipage}{\dimexpr \textwidth-2\fboxsep} + {\Large\raggedright\cmdEpydoc@function@signature\par} + \setlength{\parskip}{\EpydocParskip} + \@ifundefined{cmdEpydoc@function@description}{}{% {\@EpydocSeparator}% - \textbf{Return Value}% - \vspace{-\EpydocParskip}% - \begin{quote}\@EpydocFunctionReturnDescr\end{quote}% - \fi% - \else% - {\@EpydocSeparator}% - \textbf{Return Value}% - \vspace{-\EpydocParskip}% - \ifx\@EpydocFunctionReturnDescr\empty% - \begin{quote}\it \@EpydocFunctionReturnType\end{quote}% - \else% - \begin{quote}\@EpydocFunctionReturnDescr% - \textit{(type=\@EpydocFunctionReturnType)}\end{quote}% - \fi% - \fi% - \ifx\@EpydocFunctionRaises\empty\else% - {\@EpydocSeparator}% - \@EpydocFunctionRaises % - \fi% - \ifx\@EpydocFunctionOverrides\empty\else% - {\@EpydocSeparator}% - \@EpydocFunctionOverrides % - \fi% - \ifx\@EpydocFunctionMetadata\empty\else% - {\@EpydocSeparator}% - \@EpydocFunctionMetadata % - \fi% - \end{boxedminipage}\par}} + \par\cmdEpydoc@function@description}% + \@ifundefined{cmdEpydoc@function@parameters}{}{% + {\@EpydocSeparator}% + \par\cmdEpydoc@function@parameters}% + \@ifundefined{cmdEpydoc@function@returntype}{ + \@ifundefined{cmdEpydoc@function@returndescr}{}{ + {\@EpydocSeparator}% + \par\textbf{Return Value}% + \par\vspace{-\EpydocParskip}% + \begin{quote}\cmdEpydoc@function@returndescr\end{quote}}% + }{ + {\@EpydocSeparator}% + \par\textbf{Return Value}% + \par\vspace{-\EpydocParskip}% + \begin{quote}% + \@ifundefined{cmdEpydoc@function@returndescr}{ + \textit{\cmdEpydoc@function@returntype}% + }{% + \cmdEpydoc@function@returndescr% + \textit{(type=\cmdEpydoc@function@returntype)}}% + \end{quote}% + } + \@ifundefined{cmdEpydoc@function@raises}{}{% + {\@EpydocSeparator}% + \par\cmdEpydoc@function@raises}% + \@ifundefined{cmdEpydoc@function@overrides}{}{% + {\@EpydocSeparator}% + \par\cmdEpydoc@function@overrides}% + \@ifundefined{cmdEpydoc@function@metadata}{}{% + \ifx\cmdEpydoc@property@metadata\empty\else + {\@EpydocSeparator}% + \par\cmdEpydoc@function@metadata% + \fi}% + \end{boxedminipage}\par}}} {} % ====================================================================== @@ -718,7 +705,7 @@ p{\EpydocVariableWidth}| p{\dimexpr \textwidth% -4\tabcolsep-7pt - -\EpydocVariableWidth \relax} + -\EpydocVariableWidth} @{\hspace \tabcolsep \vrule width \fboxrule}} % Set up the headers & footer (this makes the table span % multiple pages in a happy way). @@ -738,28 +725,22 @@ % Variable Lists \renewenvironment{EpydocVariableList}{% - \newcommand{\EpydocVariable}[4]{% - \gdef\@EpydocVariableName{##1}% - \gdef\@EpydocVariableDescription{##2}% - \gdef\@EpydocVariableType{##3}% - \gdef\@EpydocVariableValue{##4}% - \raggedright\@EpydocVariableName & % + \newcommand{\EpydocVariable}[1]{{% + \setkeys[Epydoc]{variable}{##1}% + \raggedright\cmdEpydoc@variable@name &% + \setkeys[Epydoc]{variable}{##1}% \setlength{\parskip}{\EpydocParskip}\raggedright% - \@EpydocVariableDescription % - \ifx\@EpydocVariableValue\empty\relax% - \ifx\@EpydocVariableType\empty\else% - \ifx\@EpydocVariableDescription\empty\else\par\fi% - \textit{(type=\texttt{\@EpydocVariableType})}% - \fi% - \else\relax% - \ifx\@EpydocVariableDescription\empty\else\par\fi% - \textbf{Value:} \texttt{\@EpydocVariableValue}% - \ifx\@EpydocVariableType\empty\else% - \textit{(type=\texttt{\@EpydocVariableType})}% - \fi% - \fi% + \@ifundefined{cmdEpydoc@variable@description}{}{% + \cmdEpydoc@variable@description\relax}% + \@ifundefined{cmdEpydoc@variable@value}{}{% + \@ifundefined{cmdEpydoc@variable@description}{}{\par}% + \textbf{Value:} \texttt{\cmdEpydoc@variable@value}}% + \@ifundefined{cmdEpydoc@variable@type}{}{% + \@ifundefined{cmdEpydoc@variable@description}{% + \@ifundefined{cmdEpydoc@variable@value}{}{ }}{ }% + \textit{(type=\texttt{\cmdEpydoc@variable@type})}}% \tabularnewline - \hline}% + \hline}}% \begin{@EpydocGeneralList}% } {\end{@EpydocGeneralList}} @@ -775,39 +756,30 @@ \renewenvironment{EpydocPropertyList}{% \def\@EpydocSeparator{% \aftergroup\def\aftergroup\@EpydocSeparator\aftergroup{% - \aftergroup\\\aftergroup[\aftergroup\EpydocParskip\aftergroup]% + \aftergroup\par% \aftergroup}}% - \newcommand{\EpydocProperty}[6]{% - \gdef\@EpydocPropertyName{##1}% - \gdef\@EpydocPropertyDescription{##2}% - \gdef\@EpydocPropertyType{##3}% - \gdef\@EpydocPropertyGet{##4}% - \gdef\@EpydocPropertySet{##5}% - \gdef\@EpydocPropertyDel{##6}% - \raggedright\@EpydocPropertyName & % + \newcommand{\EpydocProperty}[1]{{% + \setkeys[Epydoc]{property}{##1}% + \raggedright\cmdEpydoc@property@name & % + \setkeys[Epydoc]{property}{##1}% \setlength{\parskip}{\EpydocParskip}\raggedright% - \ifx\@EpydocPropertyDescription\empty\else% + \@ifundefined{cmdEpydoc@property@description}{}{% {\@EpydocSeparator}% - \@EpydocPropertyDescription % - \fi% - \ifx\@EpydocPropertyType\empty\else% + \cmdEpydoc@property@description\relax}% + \@ifundefined{cmdEpydoc@property@type}{}{% {\@EpydocSeparator}% - \textbf{Type:} \@EpydocPropertyType - \fi% - \ifx\@EpydocPropertyGet\empty\else% + \textbf{Type:} \cmdEpydoc@property@type\relax}% + \@ifundefined{cmdEpydoc@property@fget}{}{% {\@EpydocSeparator}% - \textbf{Get:} \@EpydocPropertyGet% - \fi% - \ifx\@EpydocPropertySet\empty\else% + \textbf{Get:} \cmdEpydoc@property@fget\relax}% + \@ifundefined{cmdEpydoc@property@fset}{}{% {\@EpydocSeparator}% - \textbf{Set:} \@EpydocPropertySet% - \fi% - \ifx\@EpydocPropertyDel\empty\else% + \te... [truncated message content] |
From: <dva...@us...> - 2007-02-16 02:33:28
|
Revision: 1512 http://svn.sourceforge.net/epydoc/?rev=1512&view=rev Author: dvarrazzo Date: 2007-02-15 18:32:56 -0800 (Thu, 15 Feb 2007) Log Message: ----------- - HTML for fields cleaned up. It should be easier now to change the page look providing a different CSS. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/html_css.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-16 02:08:51 UTC (rev 1511) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-16 02:32:56 UTC (rev 1512) @@ -1957,7 +1957,6 @@ # Write a footer for the table. out(self.TABLE_FOOTER) - out('\n<br />\n') def write_summary_group(self, out, doc, name, var_docs, grouped_inh_vars): # Split up the var_docs list, according to the way each var @@ -2136,7 +2135,7 @@ if not var_docs: return # Write a header - self.write_table_header(out, "summary", heading) + self.write_table_header(out, "details", heading) out(self.TABLE_FOOTER) for var_doc in var_docs: @@ -2145,9 +2144,7 @@ out('<br />\n') def write_details_entry(self, out, var_doc): - descr = self.descr(var_doc, indent=2) - if descr: descr = '<br />'+descr - else: descr = '' + descr = self.descr(var_doc, indent=2) or '' if var_doc.is_public: div_class = '' else: div_class = ' class="private"' @@ -2255,25 +2252,25 @@ </table> $self.render_callgraph(callgraph)$ $descr$ - <dl><dt></dt><dd> + <dl class="fields"> >>> # === parameters === >>> if arg_descrs: - <dl><dt>Parameters:</dt></dl> - <ul class="nomargin"> + <dt>Parameters:</dt> + <dd><ul class="nomargin-top"> >>> for lhs, rhs in arg_descrs: $self.labelled_list_item(lhs, rhs)$ >>> #endfor - </ul> + </ul></dd> >>> #endif >>> # === return type === >>> if rdescr and rtype: - <dl><dt>Returns: $rtype$</dt> - <dd>$rdescr$</dd></dl> + <dt>Returns: $rtype$</dt> + <dd>$rdescr$</dd> >>> elif rdescr: - <dl><dt>Returns:</dt> - <dd>$rdescr$</dd></dl> + <dt>Returns:</dt> + <dd>$rdescr$</dd> >>> elif rtype: - <dl><dt>Returns: $rtype$</dt></dl> + <dt>Returns: $rtype$</dt> >>> #endif >>> # === decorators === >>> if func_doc.decorators not in (None, UNKNOWN): @@ -2288,17 +2285,17 @@ >>> decos = None >>> #endif >>> if decos: - <dl><dt>Decorators:</dt></dl> - <ul class="nomargin"> + <dt>Decorators:</dt> + <dd><ul class="nomargin-top"> >>> for deco in decos: <li><code>@$deco$</code></li> >>> #endfor - </ul> + </ul></dd> >>> #endif >>> # === exceptions === >>> if func_doc.exception_descrs not in (None, UNKNOWN, (), []): - <dl><dt>Raises:</dt></dl> - <ul class="nomargin"> + <dt>Raises:</dt> + <dd><ul class="nomargin-top"> >>> for name, descr in func_doc.exception_descrs: >>> exc_name = self.docindex.find(name, func_doc) >>> if exc_name is not None: @@ -2309,21 +2306,21 @@ str(name) + "</strong></code>", self.docstring_to_html(descr, func_doc, 8))$ >>> #endfor - </ul> + </ul></dd> >>> #endif >>> # === overrides === >>> if var_doc.overrides not in (None, UNKNOWN): - <dl><dt>Overrides: + <dt>Overrides: $self.href(var_doc.overrides.value, context=var_doc)$ >>> if (func_doc.docstring in (None, UNKNOWN) and >>> var_doc.overrides.value.docstring not in (None, UNKNOWN)): <dd><em class="note">(inherited documentation)</em></dd> >>> #endif - </dt></dl> + </dt> >>> #endif + </dl> >>> # === metadata === >>> self.write_standard_fields(out, func_doc) - </dd></dl> </td></tr></table> </div> ''') @@ -2375,21 +2372,21 @@ <tr><td> <h3 class="epydoc">$var_doc.name$</h3> $descr$ - <dl><dt></dt><dd> + <dl class="fields"> >>> for (name, val, summary) in accessors: - <dl><dt>$name$ Method:</dt> - <dd>$val$ + <dt>$name$ Method:</dt> + <dd class="value">$val$ >>> if summary: - $summary$ >>> #endif - </dd></dl> + </dd> >>> #endfor >>> if prop_doc.type_descr not in (None, UNKNOWN): - <dl><dt>Type:</dt> - <dd>$self.type_descr(var_doc, indent=6)$</dd></dl> + <dt>Type:</dt> + <dd>$self.type_descr(var_doc, indent=6)$</dd> >>> #endif + </dl> >>> self.write_standard_fields(out, prop_doc) - </dd></dl> </td></tr></table> </div> ''') @@ -2407,18 +2404,19 @@ <tr><td> <h3 class="epydoc">$var_doc.name$</h3> $descr$ - <dl><dt></dt><dd> + <dl class="fields"> >>> if var_doc.type_descr not in (None, UNKNOWN): - <dl><dt>Type:</dt> - <dd>$self.type_descr(var_doc, indent=6)$</dd></dl> + <dt>Type:</dt> + <dd>$self.type_descr(var_doc, indent=6)$</dd> >>> #endif + </dl> >>> self.write_standard_fields(out, var_doc) >>> if var_doc.value is not UNKNOWN: - <dl><dt>Value:</dt> + <dl class="fields"> + <dt>Value:</dt> <dd>$self.pprint_value(var_doc.value)$</dd> - </dl> + </dl> >>> #endif - </dd></dl> </td></tr></table> </div> ''') @@ -2729,8 +2727,6 @@ fields = [] field_values = {} - #if _sort_fields: fields = STANDARD_FIELD_NAMES [XX] - for (field, arg, descr) in doc.metadata: if field not in field_values: fields.append(field) @@ -2740,6 +2736,9 @@ else: field_values.setdefault(field,[]).append(descr) + if not fields: return + + out('<div class="fields">') for field in fields: if field.takes_arg: for arg, descrs in field_values[field].items(): @@ -2748,6 +2747,8 @@ else: self.write_standard_field(out, doc, field, field_values[field]) + out('</div>') + write_standard_field = compile_template( """ write_standard_field(self, out, doc, field, descrs, arg='') @@ -2771,7 +2772,7 @@ </dd> </dl> >>> else: - <p><strong>$field.plural+arglabel$:</strong> + <strong>$field.plural+arglabel$:</strong> <ul class="nomargin-top"> >>> for descr in descrs: <li> @@ -3206,7 +3207,6 @@ s = '<span class="docstring">%s</span><!--end docstring-->' % s return s - # [XX] Just use docstring_to_html??? def description(self, parsed_docstring, where=None, indent=0): assert isinstance(where, (APIDoc, type(None))) if parsed_docstring in (None, UNKNOWN): return '' Modified: trunk/epydoc/src/epydoc/docwriter/html_css.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_css.py 2007-02-16 02:08:51 UTC (rev 1511) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2007-02-16 02:32:56 UTC (rev 1512) @@ -129,7 +129,8 @@ */ table.summary { border-collapse: collapse; background: $table_bg; color: $table_fg; - border: $table_border; } + border: $table_border; + margin-bottom: 0.5em; } td.summary { border: $table_border; } code.summary-type { font-size: 85%; } table.summary a:link { color: $table_link; } @@ -137,7 +138,7 @@ /* Details Tables (functions, variables, etc) - * - Each object is described in its own single-celled table. + * - Each object is described in its own div. * - A single-row summary table w/ table-header is used as * a header for each details section (CSS style for table-header * is defined above, under 'Table Headers'). @@ -150,6 +151,13 @@ table.details a:link { color: $table_link; } table.details a:visited { color: $table_visited_link; } +/* Fields */ +dl.fields { margin-left: 2em; margin-top: 1em; + margin-bottom: 1em; } +dl.fields dd ul { margin-left: -2em; } +div.fields { margin-left: 2em; } +div.fields p { margin-bottom: 0.5em; } + /* Index tables (identifier index, term index, etc) * - link-index is used for indices containing lists of links * (namely, the identifier index & term index). This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-03-01 23:40:07
|
Revision: 1565 http://svn.sourceforge.net/epydoc/?rev=1565&view=rev Author: dvarrazzo Date: 2007-03-01 15:40:03 -0800 (Thu, 01 Mar 2007) Log Message: ----------- - Some HTML cleanup. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/dotgraph.py trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/html_colorize.py Modified: trunk/epydoc/src/epydoc/docwriter/dotgraph.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2007-03-01 04:03:01 UTC (rev 1564) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2007-03-01 23:40:03 UTC (rev 1565) @@ -184,7 +184,7 @@ s += ' -- ' if caption: s += '<span class="graph-caption">%s</span>' % caption - s += '\n </td></tr>\n</table><br/>' + s += '\n </td></tr>\n</table><br />' if center: s += '</center>' return s @@ -1004,8 +1004,8 @@ ###################################################################### def class_tree_graph(bases, linker, context=None, **options): """ - Return a `DotGraph` that graphically displays the package - hierarchies for the given packages. + Return a `DotGraph` that graphically displays the class + hierarchy for the given classes. """ graph = DotGraph('Class Hierarchy for %s' % name_list(bases, context), body='ranksep=0.3\n', @@ -1263,7 +1263,7 @@ specialize_valdoc_node(node, val_doc, context, linker.url_for(val_doc)) return nodes -NOOP_URL = 'javascript: void(0);' +NOOP_URL = 'javascript:void(0);' MODULE_NODE_HTML = ''' <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" CELLPADDING="0" PORT="table" ALIGN="LEFT"> Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2007-03-01 04:03:01 UTC (rev 1564) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2007-03-01 23:40:03 UTC (rev 1565) @@ -1013,15 +1013,15 @@ # Alphabetical sections. sections = [s for s in sections if s in index_by_section] if sections: - out('<table border="0" width="100%"><tr valign="top">\n') + out('<table border="0" width="100%">\n') for section in sorted(sections): - out('<td valign="top" width="1%">') - out('<a name="%s"><h2 class="epydoc">%s</h2></a></td>\n' % + out('<tr valign="top"><td valign="top" width="1%">') + out('<h2 class="epydoc"><a name="%s">%s</a></h2></td>\n' % (section, section)) out('<td valign="top">\n') self.write_index_section(out, index_by_section[section], True) out('</td></tr>\n') - out('</table>\n</br />') + out('</table>\n<br />') # Footer material. out('<br />') @@ -1040,7 +1040,7 @@ '%s-index.html' % field) # Page title. - out('<a name="%s"><h1 class="epydoc">%s</h1></a>\n<br />\n' % + out('<h1 class="epydoc"><a name="%s">%s</a></h1>\n<br />\n' % (field, title)) # Index (one section per arg) @@ -1070,7 +1070,6 @@ self.docstring_to_html(descr,doc,4)) out(' </ul>\n') out('</table></div>\n') - out('</dl>\n') # Footer material. out('<br />') @@ -1117,7 +1116,7 @@ else: label = container.canonical_name[-1] out('<span class="index-where">(in %s)' - '</font>' % self.href(container, label)) + '</span>' % self.href(container, label)) else: out(' ') out('</td>\n') Modified: trunk/epydoc/src/epydoc/docwriter/html_colorize.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2007-03-01 04:03:01 UTC (rev 1564) +++ trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2007-03-01 23:40:03 UTC (rev 1565) @@ -52,7 +52,7 @@ var elt = document.getElementById(id+"-expanded-linenums"); if (elt) elt.style.display = "none"; var elt = document.getElementById(id+"-collapsed-linenums"); - if (elt) { elt.innerHTML = "<br/>"; elt.style.display="block"; } + if (elt) { elt.innerHTML = "<br />"; elt.style.display="block"; } var elt = document.getElementById(id+"-toggle"); if (elt) { elt.innerHTML = "+"; } var elt = document.getElementById(id+"-collapsed"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2008-02-26 17:11:41
|
Revision: 1793 http://epydoc.svn.sourceforge.net/epydoc/?rev=1793&view=rev Author: edloper Date: 2008-02-26 09:11:38 -0800 (Tue, 26 Feb 2008) Log Message: ----------- - Use the xkeyval package to add two new keyword options to the epydoc sty file (title and creator), which are used to set the hyperref options pdftitle and pdfcreator. - Use conditional test to decide whether the dvips or pdftex option should be pased to the hyperref package. The generated latex output no longer hard-codes information about the driver (so the same latex output can be used by both latex and pdflatex). - The preamble in the generated api.tex now *just* uses the selected epydoc sty package. (the \uepackage statements for the hyperref and graphicx packages were changed to \RequirePackage statements in epydoc-base.sty.) - Fixed bug where nested classes were not being documented. - Fixed several bugs with index generation - Fixed \ProvidesClass statements in epydoc-*.sty files Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/latex.py trunk/epydoc/src/epydoc/docwriter/latex_sty.py Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2008-02-26 03:13:30 UTC (rev 1792) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2008-02-26 17:11:38 UTC (rev 1793) @@ -31,7 +31,6 @@ PREAMBLE = [ "\\documentclass{article}", "\\usepackage[%s]{%s}", - "\\usepackage{graphicx}", ] SECTIONS = ['\\part{%s}', '\\chapter{%s}', '\\section{%s}', @@ -55,7 +54,6 @@ self._exclude = kwargs.get('exclude', 1) self._list_submodules = kwargs.get('list_submodules', 1) self._sty = kwargs.get('sty') - self._pdfdriver = kwargs.get('pdfdriver', 'latex') self._top_section = 2 self._index_functions = 1 self._hyperref = 1 @@ -270,6 +268,8 @@ def write_preamble(self, out): # If we're generating an index, add it to the preamble. options = [] + options.append('creator={epydoc %s}' % epydoc.__version__) + options.append('title={%s}' % plaintext_to_latex(self._prj_name or '')) if self._index: options.append('index') if self._hyperlink: options.append('hyperlink') out('\n'.join(self.PREAMBLE) % (','.join(options), @@ -283,21 +283,6 @@ if self._hyperref: out('\\definecolor{UrlColor}{rgb}{0,0.08,0.45}\n') - if self._pdfdriver == 'pdflatex': - driver = 'pdftex' - elif self._pdfdriver == 'latex': - driver = 'dvips' - else: - raise ValueError('bad pdfdriver: %s' % self._pdfdriver) - - 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' % - (driver, self._prj_name or '', epydoc.__version__)) - # If restructuredtext was used, then we need to extend # the prefix to include LatexTranslator.head_prefix. if 'restructuredtext' in epydoc.markup.MARKUP_LANGUAGES_USED: @@ -370,7 +355,9 @@ image_file = os.path.join(self._directory, image_url) return graph.to_latex(image_file) or '' - def write_class(self, out, doc): + def write_class(self, out, doc, short_name=None): + if short_name is None: short_name = doc.canonical_name[-1] + if self._list_classes_separately: self.write_header(out, doc) self.write_start_of(out, 'Class Description') @@ -387,7 +374,7 @@ else: seclevel = 1 out(self.section('%s %s' % (self.doc_kind(doc), - _dotted(doc.canonical_name[-1])), + _dotted(short_name)), seclevel, ref=doc)) if ((doc.bases not in (UNKNOWN, None) and len(doc.bases) > 0) or @@ -439,6 +426,18 @@ # Mark the end of the class (for the index) out(' ' + self.indexterm(doc, 'end')) + # Write any nested classes. These will have their own + # section (at the same level as this section) + for nested_class in doc.select_variables(imported=False, + value_type='class', + public=self._public_filter): + if (nested_class.value.canonical_name != UNKNOWN and + (nested_class.value.canonical_name[:-1] == + doc.canonical_name)): + self.write_class(out, nested_class.value, + DottedName(short_name, + nested_class.canonical_name[-1])) + #//////////////////////////////////////////////////////////// #{ Module hierarchy trees #//////////////////////////////////////////////////////////// @@ -1058,6 +1057,9 @@ else: return 'Variable' + # [xx] list modules, classes, and functions as top-level index + # items. Methods are listed under their classes. Nested classes + # are listed under their classes. def indexterm(self, doc, pos='only'): """Mark a term or section for inclusion in the index.""" if not self._index: return '' @@ -1065,39 +1067,30 @@ return '' pieces = [] - - if isinstance(doc, ClassDoc): - classCrossRef = '\\index{\\EpydocIndex[%s]{%s}|see{%%s}}\n' \ - % (self.doc_kind(doc).lower(), - _dotted('%s' % doc.canonical_name)) - else: - classCrossRef = None - - while isinstance(doc, ClassDoc) or isinstance(doc, RoutineDoc): - if doc.canonical_name == UNKNOWN: - return '' # Give up. - pieces.append('\\EpydocIndex[%s]{%s}' % - (self.doc_kind(doc).lower(), - _dotted('%s' % doc.canonical_name))) + kinds = [] + while True: + if doc.canonical_name in (None, UNKNOWN): return '' # Give up. + pieces.append(doc.canonical_name[-1]) + kinds.append(self.doc_kind(doc).lower()) doc = self.docindex.container(doc) - if doc == UNKNOWN: - return '' # Give up. + if isinstance(doc, ModuleDoc): break + if doc is None: break + if doc == UNKNOWN: return '' # give up. pieces.reverse() - if pos == 'only': - term = '\\index{%s}\n' % '!'.join(pieces) - elif pos == 'start': - term = '\\index{%s|(}\n' % '!'.join(pieces) - elif pos == 'end': - term = '\\index{%s|)}\n' % '!'.join(pieces) - else: - raise AssertionError('Bad index position %s' % pos) + kinds.reverse() + for i in range(1, len(pieces)): + pieces[i] = '%s.%s' % (pieces[i-1], pieces[i]) + pieces = ['\\EpydocIndex{%s}{%s}{%s}' % (piece.lower(), piece, kind) + for (piece, kind) in zip (pieces, kinds)] + + if pos == 'only': modifier = '' + elif pos == 'start': modifier = '|(' + elif pos == 'end': modifier = '|)' + else: raise AssertionError('Bad index position %s' % pos) + + term = '\\index{%s%s}\n' % ('!'.join(pieces), modifier) - if pos in ['only', 'start'] and classCrossRef is not None: - term += classCrossRef % ('\\EpydocIndex[%s]{%s}' % - (self.doc_kind(doc).lower(), - _dotted('%s'%doc.canonical_name))) - return term #: Map the Python encoding representation into mismatching LaTeX ones. Modified: trunk/epydoc/src/epydoc/docwriter/latex_sty.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex_sty.py 2008-02-26 03:13:30 UTC (rev 1792) +++ trunk/epydoc/src/epydoc/docwriter/latex_sty.py 2008-02-26 17:11:38 UTC (rev 1793) @@ -41,30 +41,41 @@ % $Id:$ \NeedsTeXFormat{LaTeX2e}% -\ProvidesClass{epydoc}[2007/04/06 v3.0beta1 Epydoc Python Documentation] +\ProvidesClass{epydoc-base}[2008/02/26 v3.0.1 Epydoc Python Documentation] % ====================================================================== -% Basic Package Requirements +% Options -\RequirePackage{alltt, boxedminipage} -\RequirePackage{multirow, amssymb} -\RequirePackage[headings]{fullpage} -\RequirePackage[usenames]{color} +% These two packages are used to process options: \RequirePackage{ifthen} +\RequirePackage{xkeyval} -% ====================================================================== -% Options - +% Define an option 'index' that sets the boolean value \@doIndex \newif\if@doIndex \@doIndexfalse -\DeclareOption{index}{\@doIndextrue} +\DeclareOptionX{index}{\@doIndextrue} +% Define an option 'hyperlink' that sets the boolean value \@docHyperlink \newif\if@doHyperlink \@doHyperlinkfalse -\DeclareOption{hyperlink}{\@doHyperlinktrue} +\DeclareOptionX{hyperlink}{\@doHyperlinktrue} -\ProcessOptions\relax +% Pass the 'title' & 'creator' options to the hyperref package. +\DeclareOptionX{title}[]{\PassOptionsToPackage{pdftitle={#1}}{hyperref}} +\DeclareOptionX{creator}[]{\PassOptionsToPackage{pdfcreator={#1}}{hyperref}} +% Process the options list. +\ProcessOptionsX\relax + +% ====================================================================== +% Package Requirements + +\RequirePackage{alltt, boxedminipage} +\RequirePackage{multirow, amssymb} +\RequirePackage[headings]{fullpage} +\RequirePackage[usenames]{color} +\RequirePackage{graphicx} + \@ifclassloaded{memoir}{% \RequirePackage[other,notbib]{tocbibind} }{% @@ -81,6 +92,17 @@ \makeindex \fi +\ifx\pdfoutput\undefined\newcommand{\driver}{dvips} +\else\ifnum\pdfoutput=1\newcommand{\driver}{pdftex} +\else\newcommand{\driver}{dvips}\fi\fi + +\RequirePackage[\driver, pagebackref, + bookmarks=true, bookmarksopen=false, pdfpagemode=UseOutlines, + colorlinks=true, linkcolor=black, anchorcolor=black, citecolor=black, + filecolor=black, menucolor=black, pagecolor=black, urlcolor=UrlColor] + {hyperref} + + % ====================================================================== % General Formatting @@ -150,14 +172,16 @@ % Index Terms % The \EpydocIndex command is used to mark items that should be included -% in the index. It takes one optional argument, specifying the 'kind' -% of the object, and one required argument, the term that should be -% included in the index. (This command is used inside the \index -% command.) kind can be Package, Script, Module, Class, Class Method, -% Static Method, Method, Function, or Variable. -\newcommand{\EpydocIndex}[2][]{% +% in the index. It takes three arguments. The first argument is the +% item's case-normalized name; this is typically discarded, and is +% simply used to ensure the proper (i.e., case-insensitive) sort order +% in the index. The second argument is the item's name; and the +% third item is the item's "kind". "kind" can be Package, Script, Module, +% Class, Class Method, Static Method, Method, Function, or Variable. +% This command is used inside of the \index{...} command. +\newcommand{\EpydocIndex}[3]{% #2 % - \ifthenelse{\equal{#1}{}}{}{\textit{(\MakeLowercase{#1})}}} + \ifthenelse{\equal{#3}{}}{}{\textit{(#3)}}} % ====================================================================== % Descriptions (docstring contents) @@ -582,11 +606,15 @@ % % $Id:$ \NeedsTeXFormat{LaTeX2e} -\ProvidesClass{epydoc}[2007/04/06 v3.0beta1 Epydoc Python Documentation] -\DeclareOption{index}{\PassOptionsToPackage{index}{epydoc-base}} -\DeclareOption{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-base}} -\ProcessOptions\relax +\ProvidesClass{epydoc-boxes}[2008/02/26 v3.0.1 Epydoc Python Documentation] +\RequirePackage{xkeyval} +\DeclareOptionX{index}{\PassOptionsToPackage{index}{epydoc-base}} +\DeclareOptionX{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-base}} +\DeclareOptionX{title}[]{\PassOptionsToPackage{title={#1}}{epydoc-base}} +\DeclareOptionX{creator}[]{\PassOptionsToPackage{creator={#1}}{epydoc-base}} +\ProcessOptionsX\relax + \RequirePackage{epydoc-base} \RequirePackage{longtable} @@ -810,11 +838,15 @@ % % $Id:$ \NeedsTeXFormat{LaTeX2e} -\ProvidesClass{epydoc}[2007/04/06 v3.0beta1 Epydoc Python Documentation] -\DeclareOption{index}{\PassOptionsToPackage{index}{epydoc-base}} -\DeclareOption{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-base}} -\ProcessOptions\relax +\ProvidesClass{epydoc-shaded}[2008/02/26 v3.0.1 Epydoc Python Documentation] +\RequirePackage{xkeyval} +\DeclareOptionX{index}{\PassOptionsToPackage{index}{epydoc-base}} +\DeclareOptionX{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-base}} +\DeclareOptionX{title}[]{\PassOptionsToPackage{title={#1}}{epydoc-base}} +\DeclareOptionX{creator}[]{\PassOptionsToPackage{creator={#1}}{epydoc-base}} +\ProcessOptionsX\relax + \RequirePackage{epydoc-base} \definecolor{gray95}{gray}{0.95} @@ -1032,11 +1064,18 @@ % how different pieces of the documentation are displayed. % \NeedsTeXFormat{LaTeX2e} -\ProvidesClass{epydoc}[2007/04/06 v3.0beta1 Epydoc Python Documentation] -\DeclareOption{index}{\PassOptionsToPackage{index}{epydoc-base}} -\DeclareOption{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-base}} -\ProcessOptions\relax +% Replace 'XXX' with a new name: +\ProvidesClass{epydoc-XXX}[2008/02/26 v3.0.1 Epydoc Python Documentation] + +% Pass options to the epydoc base package. +\RequirePackage{xkeyval} +\DeclareOptionX{index}{\PassOptionsToPackage{index}{epydoc-base}} +\DeclareOptionX{hyperlink}{\PassOptionsToPackage{hyperlink}{epydoc-base}} +\DeclareOptionX{title}[]{\PassOptionsToPackage{title={#1}}{epydoc-base}} +\DeclareOptionX{creator}[]{\PassOptionsToPackage{creator={#1}}{epydoc-base}} +\ProcessOptionsX\relax + \RequirePackage{epydoc-base} % Add \renewcommand and \renewenvironment commands here. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |