epydoc-commits Mailing List for Python API documentation generation tool (Page 25)
Brought to you by:
edloper
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
(77) |
May
|
Jun
(6) |
Jul
(8) |
Aug
(91) |
Sep
(67) |
Oct
(4) |
Nov
|
Dec
(1) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(17) |
Feb
(135) |
Mar
(25) |
Apr
|
May
(1) |
Jun
(1) |
Jul
(7) |
Aug
|
Sep
(62) |
Oct
(1) |
Nov
(3) |
Dec
|
2008 |
Jan
(40) |
Feb
(102) |
Mar
(5) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2009 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <ed...@us...> - 2006-04-10 13:22:55
|
Revision: 1208 Author: edloper Date: 2006-04-10 06:22:49 -0700 (Mon, 10 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1208&view=rev Log Message: ----------- - Minor change in error reporting Modified Paths: -------------- trunk/epydoc/src/epydoc/docbuilder.py Modified: trunk/epydoc/src/epydoc/docbuilder.py =================================================================== --- trunk/epydoc/src/epydoc/docbuilder.py 2006-04-09 23:28:28 UTC (rev 1207) +++ trunk/epydoc/src/epydoc/docbuilder.py 2006-04-10 13:22:49 UTC (rev 1208) @@ -457,8 +457,7 @@ def _report_errors(name, introspect_doc, parse_doc, introspect_error, parse_error): - if len(name) < 30: hdr = 'In %s: ' % name - else: hdr = 'In %s:\n' % name + hdr = 'In %s:\n' % name if introspect_doc == parse_doc == None: log.start_block('%sNo documentation available!' % hdr) if introspect_error: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 23:28:33
|
Revision: 1207 Author: edloper Date: 2006-04-09 16:28:28 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1207&view=rev Log Message: ----------- - Docstring fixes Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/dotgraph.py Modified: trunk/epydoc/src/epydoc/docwriter/dotgraph.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-09 23:28:07 UTC (rev 1206) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-09 23:28:28 UTC (rev 1207) @@ -338,7 +338,7 @@ class DotGraphUmlClassNode(DotGraphNode): """ - A specialized dot graph node used to display C{ClassDoc}s using + A specialized dot graph node used to display `ClassDoc`\s using UML notation. The node is rendered as a table with three cells: the top cell contains the class name; the middle cell contains a list of attributes; and the bottom cell contains a list of @@ -354,7 +354,7 @@ | ... | +-------------+ - `DotGraphUmlClassNode`s may be *collapsed*, in which case they are + `DotGraphUmlClassNode`\s may be *collapsed*, in which case they are drawn as a simple box containing the class name:: +-------------+ @@ -379,16 +379,16 @@ `class_doc`. :Parameters: - linker: `DocstringLinker<markup.DocstringLinker>` + `linker` : `DocstringLinker<markup.DocstringLinker>` Used to look up URLs for classes. - context: `APIDoc` + `context` : `APIDoc` The context in which this node will be drawn; dotted names will be contextualized to this context. - collapsed: ``bool`` + `collapsed` : ``bool`` If true, then display this node as a simple box. - bgcolor: ``str`` + `bgcolor` : ``str`` The background color for this node. - options: ``dict`` + `options` : ``dict`` A set of options used to control how the node should be displayed. @@ -512,8 +512,8 @@ by `DotGraphUmlClassNode`; they should *not* be added directly to the `DotGraph`. - :param nodes: A dictionary mapping from `ClassDoc`s to - `DotGraphUmlClassNode`s, used to look up the nodes for + :param nodes: A dictionary mapping from `ClassDoc`\s to + `DotGraphUmlClassNode`\s, used to look up the nodes for attribute types. If the ``add_nodes_for_linked_attributes`` option is used, then new nodes will be added to this dictionary for any types that are not already listed. @@ -776,7 +776,7 @@ class DotGraphUmlModuleNode(DotGraphNode): """ - A specialized dot grah node used to display C{ModuleDoc}s using + A specialized dot grah node used to display `ModuleDoc`\s using UML notation. Simple module nodes look like:: .----. @@ -1024,6 +1024,7 @@ """ Return a `DotGraph` that graphically displays the class hierarchy for the given class, using UML notation. Options: + - max_attributes - max_operations - show_private_vars This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 23:28:13
|
Revision: 1206 Author: edloper Date: 2006-04-09 16:28:07 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1206&view=rev Log Message: ----------- - Improved error messages for bad consolidated lists - Fixed bug caused by change in internal variables used by the standard docutils latex writer. Modified Paths: -------------- trunk/epydoc/src/epydoc/markup/restructuredtext.py Modified: trunk/epydoc/src/epydoc/markup/restructuredtext.py =================================================================== --- trunk/epydoc/src/epydoc/markup/restructuredtext.py 2006-04-09 23:23:01 UTC (rev 1205) +++ trunk/epydoc/src/epydoc/markup/restructuredtext.py 2006-04-09 23:28:07 UTC (rev 1206) @@ -353,6 +353,10 @@ # item should have the form: # - `arg`: description... n = 0 + _BAD_ITEM = ("list item %d is not well formed. Each item must " + "consist of a single marked identifier (e.g., `x`), " + "optionally followed by a colon or dash and a " + "description.") for item in items: n += 1 if item.tagname != 'list_item' or len(item) == 0: @@ -363,14 +367,11 @@ 'list (it\'s probably indented '+ 'wrong).') % n) else: - raise ValueError(('list item %d does not begin with '+ - 'an identifier.') % n) + raise ValueError(_BAD_ITEM % n) if len(item[0]) == 0: - raise ValueError(('list item %d does not begin with '+ - 'an identifier.') % n) + raise ValueError(_BAD_ITEM % n) if item[0][0].tagname != 'title_reference': - raise ValueError(('list item %d does not begin with '+ - 'an identifier.') % n) + raise ValueError(_BAD_ITEM % n) # Everything looks good; convert to multiple fields. for item in items: @@ -397,21 +398,23 @@ def handle_consolidated_definition_list(self, items, tagname): # Check the list contents. n = 0 + _BAD_ITEM = ("item %d is not well formed. Each item's term must " + "consist of a single marked identifier (e.g., `x`), " + "optionally followed by a space, colon, space, and " + "a type description.") for item in items: n += 1 if (item.tagname != 'definition_list_item' or len(item) < 2 or item[0].tagname != 'term' or item[-1].tagname != 'definition'): - raise ValueError('bad definition list (bad child).') + raise ValueError('bad definition list (bad child %d).' % n) if len(item) > 3: - raise ValueError('list item %d has multiple classifiers' % n) + raise ValueError(_BAD_ITEM % n) if item[0][0].tagname != 'title_reference': - raise ValueError('list item %d does not begin with an ' - 'identifier' % n) + raise ValueError(_BAD_ITEM % n) for child in item[0][1:]: if child.astext() != '': - raise ValueError('list item %d does not begin with an ' - 'identifier' % n) + raise ValueError(_BAD_ITEM % n) # Extract it. for item in items: @@ -441,8 +444,11 @@ LaTeXTranslator.__init__(self, document) self._linker = docstring_linker - # Start at section level 3. + # Start at section level 3. (Unfortunately, we now have to + # set a private variable to make this work; perhaps the standard + # latex translator should grow an official way to spell this?) self.section_level = 3 + self._section_number = [0]*self.section_level # Handle interpreted text (crossreferences) def visit_title_reference(self, node): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 23:23:05
|
Revision: 1205 Author: edloper Date: 2006-04-09 16:23:01 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1205&view=rev Log Message: ----------- - Fixed bug that was causing tex files to be written for classes even if list_classes_separately=False. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/latex.py Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2006-04-09 21:17:46 UTC (rev 1204) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2006-04-09 23:23:01 UTC (rev 1205) @@ -118,7 +118,8 @@ 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): + elif (isinstance(val_doc, ClassDoc) and + self._list_classes_separately): filename = '%s-class.tex' % val_doc.canonical_name self._write(self.write_class, directory, filename, val_doc) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 21:17:50
|
Revision: 1204 Author: edloper Date: 2006-04-09 14:17:46 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1204&view=rev Log Message: ----------- - Fixed bug in trunation of attribute/operation lists for uml class node Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/dotgraph.py Modified: trunk/epydoc/src/epydoc/docwriter/dotgraph.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-09 21:17:16 UTC (rev 1203) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-09 21:17:46 UTC (rev 1204) @@ -735,17 +735,19 @@ # Construct the attribute list. (If it's too long, truncate) attrib_cells = [self._attribute_cell(a) for a in self.attributes] + max_attributes = self.options.get('max_attributes', 15) if len(attrib_cells) == 0: attrib_cells = ['<TR><TD></TD></TR>'] - elif len(attrib_cells) > self.options.get('max_attributes', 15): + elif len(attrib_cells) > max_attributes: attrib_cells[max_attributes-2:-1] = ['<TR><TD>...</TD></TR>'] attributes = ''.join(attrib_cells) # Construct the operation list. (If it's too long, truncate) oper_cells = [self._operation_cell(a) for a in self.operations] + max_operations = self.options.get('max_operations', 15) if len(oper_cells) == 0: oper_cells = ['<TR><TD></TD></TR>'] - elif len(oper_cells) > self.options.get('max_operations', 15): + elif len(oper_cells) > max_operations: oper_cells[max_operations-2:-1] = ['<TR><TD>...</TD></TR>'] operations = ''.join(oper_cells) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 21:17:20
|
Revision: 1203 Author: edloper Date: 2006-04-09 14:17:16 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1203&view=rev Log Message: ----------- - Fixed minor bug in pp() Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-04-09 20:57:52 UTC (rev 1202) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-04-09 21:17:16 UTC (rev 1203) @@ -1705,10 +1705,10 @@ pyid = id(api_doc.__dict__) if backpointers is None: backpointers = {} if (hasattr(api_doc, 'canonical_name') and - api_doc.canonical_name is not UNKNOWN): + api_doc.canonical_name not in (None, UNKNOWN)): name = '%s for %s' % (api_doc.__class__.__name__, api_doc.canonical_name) - elif hasattr(api_doc, 'name') and api_doc.name is not UNKNOWN: + elif hasattr(api_doc, 'name') and api_doc.name not in (UNKNOWN, None): name = '%s for %s' % (api_doc.__class__.__name__, api_doc.name) else: name = api_doc.__class__.__name__ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 20:57:57
|
Revision: 1202 Author: edloper Date: 2006-04-09 13:57:52 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1202&view=rev Log Message: ----------- - Updated tests to reflect changes in APIDoc: - ValueDoc -> GenericValueDoc - .repr is gone, replaced by .pyval / .parse_repr - Added .lineno Modified Paths: -------------- trunk/epydoc/src/epydoc/test/docparser.doctest Modified: trunk/epydoc/src/epydoc/test/docparser.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docparser.doctest 2006-04-09 20:57:14 UTC (rev 1201) +++ trunk/epydoc/src/epydoc/test/docparser.doctest 2006-04-09 20:57:52 UTC (rev 1202) @@ -81,11 +81,11 @@ | +- is_public = True | +- name = u'x' | +- value - | +- ValueDoc [2] + | +- GenericValueDoc [2] | +- defining_module | | +- ModuleDoc for test [0] (defined above) | +- docs_extracted_by = 'parser' - | +- repr = u'12' + | +- parse_repr = u'12' | +- toktree = [(2, u'12')] +- y => VariableDoc for test.y [3] | +- container @@ -97,11 +97,11 @@ | +- is_public = True | +- name = u'y' | +- value - | +- ValueDoc [4] + | +- GenericValueDoc [4] | +- defining_module | | +- ModuleDoc for test [0] (defined above) | +- docs_extracted_by = 'parser' - | +- repr = u'[1,2,3]+ [4,5]' + | +- parse_repr = u'[1,2,3]+ [4,5]' | +- toktree = [[(51, u'['), (2, u'1'), (51, u','), ... +- z => VariableDoc for test.z [5] +- container @@ -113,11 +113,11 @@ +- is_public = True +- name = u'z' +- value - +- ValueDoc [6] + +- GenericValueDoc [6] +- defining_module | +- ModuleDoc for test [0] (defined above) +- docs_extracted_by = 'parser' - +- repr = u'f(x,y)' + +- parse_repr = u'f(x,y)' +- toktree = [(1, u'f'), [(51, u'('), (1, u'x'), (... In this example, DocParser decides that the assignment to y is @@ -127,21 +127,21 @@ ... x = [1,2] ... y = x ... """, - ... attribs='variables is_alias name value repr') + ... attribs='variables is_alias name value parse_repr') ModuleDoc for test [0] - +- repr = <UNKNOWN> + +- parse_repr = <UNKNOWN> +- variables +- x => VariableDoc for test.x [1] | +- is_alias = False | +- name = u'x' | +- value - | +- ValueDoc [2] - | +- repr = u'[1,2]' + | +- GenericValueDoc [2] + | +- parse_repr = u'[1,2]' +- y => VariableDoc for test.y [3] +- is_alias = True +- name = u'y' +- value - +- ValueDoc [2] (defined above) + +- GenericValueDoc [2] (defined above) DocParser can also parse assignments where the left-hand side is a tuple or list; however, it will not extract values. @@ -191,26 +191,26 @@ >>> runparser(s=""" ... x = y = z = 0 ... """, - ... attribs="variables is_alias name value repr") + ... attribs="variables is_alias name value parse_repr") ModuleDoc for test [0] - +- repr = <UNKNOWN> + +- parse_repr = <UNKNOWN> +- variables +- x => VariableDoc for test.x [1] | +- is_alias = True | +- name = u'x' | +- value - | +- ValueDoc [2] - | +- repr = u'0' + | +- GenericValueDoc [2] + | +- parse_repr = u'0' +- y => VariableDoc for test.y [3] | +- is_alias = True | +- name = u'y' | +- value - | +- ValueDoc [2] (defined above) + | +- GenericValueDoc [2] (defined above) +- z => VariableDoc for test.z [4] +- is_alias = False +- name = u'z' +- value - +- ValueDoc [2] (defined above) + +- GenericValueDoc [2] (defined above) If a variable is assigned to twice, then the later assignment overwrites the earlier one: @@ -219,15 +219,15 @@ ... x = 22 ... x = 33 ... """, - ... attribs="variables name value repr") + ... attribs="variables name value parse_repr") ModuleDoc for test [0] - +- repr = <UNKNOWN> + +- parse_repr = <UNKNOWN> +- variables +- x => VariableDoc for test.x [1] +- name = u'x' +- value - +- ValueDoc [2] - +- repr = u'33' + +- GenericValueDoc [2] + +- parse_repr = u'33' Module Control Blocks ===================== @@ -413,6 +413,7 @@ +- docstring = u'docstring for f' +- docstring_lineno = 3 +- kwarg = None + +- lineno = 2 +- posarg_defaults = [None] +- posargs = [u'x'] +- vararg = None @@ -436,7 +437,8 @@ +- docstring = u'docstring for f' +- docstring_lineno = 3 +- kwarg = u'kw' - +- posarg_defaults = [None, <ValueDoc 22>, <ValueDoc (1,)>] + +- lineno = 2 + +- posarg_defaults = [None, <GenericValueDoc None>, <Gener... +- posargs = [u'x', u'y', u'z'] +- vararg = u'v' @@ -448,6 +450,7 @@ +- canonical_name = DottedName('test', u'f') +- docs_extracted_by = 'parser' +- kwarg = None + +- lineno = 2 +- posarg_defaults = [None] +- posargs = [[u'x', [u'y', u'z']]] +- vararg = None @@ -564,15 +567,15 @@ ... x = y = 12 ... del y ... """, - ... attribs='variables value repr is_alias') + ... attribs='variables value parse_repr is_alias') ModuleDoc for test [0] - +- repr = <UNKNOWN> + +- parse_repr = <UNKNOWN> +- variables +- x => VariableDoc for test.x [1] +- is_alias = True +- value - +- ValueDoc [2] - +- repr = u'12' + +- GenericValueDoc [2] + +- parse_repr = u'12' The right-hand side of a `del` statement may contain a nested combination of lists, tuples, and parenthases. All variables found @@ -627,7 +630,7 @@ +- variables +- b => VariableDoc for test.A.b [3] +- value - +- ValueDoc [4] + +- GenericValueDoc [4] If one of the variables to be deleted is expressed as anything other than a simple identifier or a dotted name, then ignore it. (In @@ -675,12 +678,10 @@ +- variables +- match => VariableDoc for test.match [1] | +- is_imported = True - | +- value - | +- ValueDoc [2] - +- re => VariableDoc for test.re [3] + | +- value = <UNKNOWN> + +- re => VariableDoc for test.re [2] +- is_imported = True - +- value - +- ValueDoc [4] + +- value = <UNKNOWN> Unicode @@ -756,6 +757,6 @@ +- variables +- x => VariableDoc for test.A.x [3] +- value - +- ValueDoc [4] + +- GenericValueDoc [4] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 20:57:22
|
Revision: 1201 Author: edloper Date: 2006-04-09 13:57:14 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1201&view=rev Log Message: ----------- - Updated tests to reflect changes in APIDoc: - ValueDoc -> GenericValueDoc - .repr is gone, replaced by .pyval / .parse_repr - Added .lineno Modified Paths: -------------- trunk/epydoc/src/epydoc/test/docintrospecter.doctest Modified: trunk/epydoc/src/epydoc/test/docintrospecter.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docintrospecter.doctest 2006-04-09 20:52:02 UTC (rev 1200) +++ trunk/epydoc/src/epydoc/test/docintrospecter.doctest 2006-04-09 20:57:14 UTC (rev 1201) @@ -117,18 +117,18 @@ ... if x>100: return x ... else: return f((x+2)*8/7) ... x = f(12) - ... """, attribs="variables value repr") + ... """, attribs="variables value pyval") ModuleDoc for epydoc_test [0] - +- repr = u"<module 'epydoc_test' from ... + +- pyval = <module 'epydoc_test' from ... +- variables +- f => VariableDoc for epydoc_test.f [1] | +- value | +- RoutineDoc for epydoc_test.f [2] - | +- repr = u'<function f at ...>' + | +- pyval = <function f at ...> +- x => VariableDoc for epydoc_test.x [3] +- value - +- ValueDoc [4] - +- repr = u'112' + +- GenericValueDoc [4] + +- pyval = 112 The introspecter is unable to determine when variables are aliases for other variables, so it always sets `is_alias` to `UNKNOWN`: @@ -208,10 +208,10 @@ +- docs_extracted_by = 'introspecter' +- docstring = u'docstring for f' +- kwarg = None + +- lineno = 2 +- posarg_defaults = [None] +- posargs = ['x'] +- pyval = <function f at ...> - +- repr = u'<function f at ...>' +- vararg = None The function's arguments are described by the properties `posargs`, @@ -232,10 +232,10 @@ +- docs_extracted_by = 'introspecter' +- docstring = u'docstring for f' +- kwarg = 'kw' - +- posarg_defaults = [None, <ValueDoc 22>, <ValueDoc 1>] + +- lineno = 2 + +- posarg_defaults = [None, <GenericValueDoc 22>, <Generic... +- posargs = ['x', 'y', 'z'] +- pyval = <function f at ...> - +- repr = u'<function f at ...>' +- vararg = 'v' Tuple arguments are encoded as a single ArgDoc with a complex name: @@ -269,10 +269,10 @@ +- docs_extracted_by = 'introspecter' +- docstring = u'docstring' +- kwarg = None + +- lineno = 3 +- posarg_defaults = [None] +- posargs = ['x'] +- pyval = <bound method A.f of <epydoc_test.A i... - +- repr = u'<bound method A.f of <epydoc_test.A... +- vararg = None Decorators & Wrapper Assignments @@ -286,10 +286,10 @@ +- docs_extracted_by = 'introspecter' +- docstring = u'docstring for f' +- kwarg = None + +- lineno = 2 +- posarg_defaults = [None, None] +- posargs = ['cls', 'x'] +- pyval = <classmethod object at ...> - +- repr = u'<classmethod object at ...>' +- vararg = None Classes @@ -386,13 +386,11 @@ ... """, ... attribs='variables value repr is_alias') ModuleDoc for epydoc_test [0] - +- repr = u"<module 'epydoc_test' from ... +- variables +- x => VariableDoc for epydoc_test.x [1] +- is_alias = <UNKNOWN> +- value - +- ValueDoc [2] - +- repr = u'12' + +- GenericValueDoc [2] The right-hand side of a `del` statement may contain a nested combination of lists, tuples, and parenthases. All variables found @@ -447,7 +445,7 @@ +- variables +- b => VariableDoc for epydoc_test.A.b [3] +- value - +- ValueDoc [4] + +- GenericValueDoc [4] Slice deletes: @@ -543,7 +541,7 @@ +- variables +- x => VariableDoc for epydoc_test.A.x [1] +- value - +- ValueDoc [2] + +- GenericValueDoc [2] Recursive objects ================= @@ -566,7 +564,6 @@ +- docs_extracted_by = 'introspecter' +- docstring = u'A base referring to a child' +- pyval = <class epydoc_test.A at ...> - +- repr = u'<class epydoc_test.A at ...>' +- subclasses | +- ClassDoc for epydoc_test.B [1] | +- bases @@ -575,7 +572,6 @@ | +- docs_extracted_by = 'introspecter' | +- docstring = u'Its child.' | +- pyval = <class epydoc_test.B at ...> - | +- repr = u'<class epydoc_test.B at ...>' | +- subclasses = [] | +- variables = {} +- variables This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 20:52:09
|
Revision: 1200 Author: edloper Date: 2006-04-09 13:52:02 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1200&view=rev Log Message: ----------- - Updated (exception type for invalid DottedName changed) Modified Paths: -------------- trunk/epydoc/src/epydoc/test/apidoc.doctest Modified: trunk/epydoc/src/epydoc/test/apidoc.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/apidoc.doctest 2006-04-09 20:45:24 UTC (rev 1199) +++ trunk/epydoc/src/epydoc/test/apidoc.doctest 2006-04-09 20:52:02 UTC (rev 1200) @@ -154,13 +154,13 @@ >>> DottedName() Traceback (most recent call last): - ValueError: Empty DottedName + InvalidDottedName: Empty DottedName >>> DottedName('1+2') Traceback (most recent call last): - ValueError: Bad identifier '1+2' + InvalidDottedName: Bad identifier '1+2' >>> DottedName({}) Traceback (most recent call last): - ValueError: Bad identifier {} + InvalidDottedName: Bad identifier {} The one exception is that '??' is treated as if it were a valid python identifier: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 20:45:31
|
Revision: 1199 Author: edloper Date: 2006-04-09 13:45:24 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1199&view=rev Log Message: ----------- - Added ascii version of architecture diagram Modified Paths: -------------- trunk/epydoc/src/epydoc/__init__.py Modified: trunk/epydoc/src/epydoc/__init__.py =================================================================== --- trunk/epydoc/src/epydoc/__init__.py 2006-04-09 20:43:09 UTC (rev 1198) +++ trunk/epydoc/src/epydoc/__init__.py 2006-04-09 20:45:24 UTC (rev 1199) @@ -56,6 +56,31 @@ side mark what portions of the processing chain are initiated by build_doc_index() and cli(). Click on any item to see its documentation. + + /* + Python module or value * * + / \ | | + V V | | + introspect_docs() parse_docs() | | + \ / | | + V V | | + merge_docs() | | + | build_doc_index() cli() + V | | + link_imports() | | + | | | + V | | + assign_canonical_names() | | + | | | + V | | + parse_docstrings() | | + | | | + V | | + inherit_docs() * | + / | \ | + V V V | + HTMLWriter LaTeXWriter PlaintextWriter * + */ ranksep = 0.1; node [shape="box", height="0", width="0"] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 20:43:12
|
Revision: 1198 Author: edloper Date: 2006-04-09 13:43:09 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1198&view=rev Log Message: ----------- - Cleand up DotGraphUmlModuleNode (now used by uml_package_tree_graph) Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/dotgraph.py Modified: trunk/epydoc/src/epydoc/docwriter/dotgraph.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-09 18:17:52 UTC (rev 1197) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-09 20:43:09 UTC (rev 1198) @@ -772,7 +772,6 @@ s += '\n' + edge.to_dotfile() return s -# [XX] Not used yet. class DotGraphUmlModuleNode(DotGraphNode): """ A specialized dot grah node used to display C{ModuleDoc}s using @@ -799,12 +798,40 @@ """ def __init__(self, module_doc, linker, context, collapsed=False, - **options): + excluded_submodules=(), **options): self.module_doc = module_doc self.linker = linker self.context = context + self.collapsed = collapsed + self.options = options + self.excluded_submodules = excluded_submodules + DotGraphNode.__init__(self, shape='plaintext', + href=linker.url_for(module_doc) or NOOP_URL, + tooltip=module_doc.canonical_name) - def _nested_package_label(package): + #: Expects: (color, color, url, tooltip, body) + _MODULE_LABEL = ''' + <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" ALIGN="LEFT"> + <TR><TD ALIGN="LEFT" VALIGN="BOTTOM" HEIGHT="8" WIDTH="16" + FIXEDSIZE="true" BGCOLOR="%s" BORDER="1" PORT="tab"></TD></TR> + <TR><TD ALIGN="LEFT" VALIGN="TOP" BGCOLOR="%s" BORDER="1" WIDTH="20" + PORT="body" HREF="%s" TOOLTIP="%s">%s</TD></TR> + </TABLE>''' + + #: Expects: (name, body_rows) + _NESTED_BODY = ''' + <TABLE BORDER="0" CELLBORDER="0" CELLPADDING="0" CELLSPACING="0"> + <TR><TD ALIGN="LEFT">%s</TD></TR> + %s + </TABLE>''' + + #: Expects: (cells,) + _NESTED_BODY_ROW = ''' + <TR><TD> + <TABLE BORDER="0" CELLBORDER="0"><TR>%s</TR></TABLE> + </TD></TR>''' + + def _get_html_label(self, package): """ :Return: (label, depth, width) where: @@ -817,46 +844,45 @@ pkg_name = package.canonical_name pkg_url = self.linker.url_for(package) or NOOP_URL - if not package.is_package or len(package.submodules) == 0: - pkg_color = _nested_uml_package_color(package, self.context, 1) - label = MODULE_NODE_HTML % (pkg_color, pkg_color, pkg_url, - pkg_name, pkg_name[-1]) + if (not package.is_package or len(package.submodules) == 0 or + self.collapsed): + pkg_color = self._color(package, 1) + label = self._MODULE_LABEL % (pkg_color, pkg_color, + pkg_url, pkg_name, pkg_name[-1]) return (label, 1, len(pkg_name[-1])+3) - submodule_labels = [self._nested_package_label(submodule, self.linker, - self.context) - for submodule in package.submodules] - - ROW_HDR = '<TABLE BORDER="0" CELLBORDER="0"><TR>' - # Build the body of the package's icon. - body = '<TABLE BORDER="0" CELLBORDER="0">' - body += '<TR><TD ALIGN="LEFT">%s</TD></TR>' % pkg_name[-1] - body += '<TR><TD>%s' % ROW_HDR - row_width = [0] - for i, (label, depth, width) in enumerate(submodule_labels): - if row_width[-1] > 0 and width+row_width[-1] > MAX_ROW_WIDTH: - body += '</TR></TABLE></TD></TR>' - body += '<TR><TD>%s' % ROW_HDR - row_width.append(0) - #submodule_url = self.linker.url_for(package.submodules[i]) or '#' - #submodule_name = package.submodules[i].canonical_name - body += '<TD ALIGN="LEFT">%s</TD>' % label - row_width [-1] += width - body += '</TR></TABLE></TD></TR></TABLE>' - - # Put together our return value. - depth = max([d for (l,d,w) in submodule_labels])+1 - pkg_color = self._color(package, depth) - label = ('<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"><TR>' - '<TD ALIGN="LEFT" HEIGHT="8" WIDTH="16" FIXEDSIZE="true" ' - 'BORDER="1" VALIGN="BOTTOM" BGCOLOR="%s"></TD></TR><TR>' - '<TD COLSPAN="5" VALIGN="TOP" ALIGN="LEFT" BORDER="1" ' - 'BGCOLOR="%s" HREF="%s" TOOLTIP="%s">%s</TD></TR></TABLE>' % - (pkg_color, pkg_color, pkg_url, pkg_name, body)) - width = max(max(row_width), len(pkg_name[-1])+3) - return label, depth, width - - def _color(package, depth): + # Get the label for each submodule, and divide them into rows. + row_list = [''] + row_width = 0 + max_depth = 0 + max_row_width = len(pkg_name[-1])+3 + for submodule in package.submodules: + if submodule in self.excluded_submodules: continue + # Get the submodule's label. + label, depth, width = self._get_html_label(submodule) + # Check if we should start a new row. + if row_width > 0 and width+row_width > MAX_ROW_WIDTH: + row_list.append('') + row_width = 0 + # Add the submodule's label to the row. + row_width += width + row_list[-1] += '<TD ALIGN="LEFT">%s</TD>' % label + # Update our max's. + max_depth = max(depth, max_depth) + max_row_width = max(row_width, max_row_width) + + # Figure out which color to use. + pkg_color = self._color(package, depth+1) + + # Assemble & return the label. + rows = ''.join([self._NESTED_BODY_ROW % r for r in row_list]) + body = self._NESTED_BODY % (pkg_name, rows) + label = self._MODULE_LABEL % (pkg_color, pkg_color, + pkg_url, pkg_name, body) + return label, max_depth+1, max_row_width + + _COLOR_DIFF = 24 + def _color(self, package, depth): if package == self.context: return SELECTED_BG else: # Parse the base color. @@ -869,12 +895,17 @@ blue = (base & 0x0000ff) # Make it darker with each level of depth. (but not *too* # dark -- package name needs to be readable) - red = max(64, red-(depth-1)*10) - green = max(64, green-(depth-1)*10) - blue = max(64, blue-(depth-1)*10) + red = max(64, red-(depth-1)*self._COLOR_DIFF) + green = max(64, green-(depth-1)*self._COLOR_DIFF) + blue = max(64, blue-(depth-1)*self._COLOR_DIFF) # Convert it back to a color string return '#%06x' % ((red<<16)+(green<<8)+blue) + def to_dotfile(self): + attribs = ['%s="%s"' % (k,v) for (k,v) in self._attribs.items()] + label, depth, width = self._get_html_label(self.module_doc) + attribs.append('label=<%s>' % label) + return 'node%d%s' % (self.id, ' [%s]' % (','.join(attribs))) @@ -889,7 +920,7 @@ """ if options.get('style', 'uml') == 'uml': # default to uml style? if get_dot_version() >= [2]: - return _nested_package_uml_graph(packages, linker, context, + return uml_package_tree_graph(packages, linker, context, **options) elif 'style' in options: log.warning('UML style package trees require dot version 2.0+') @@ -920,7 +951,7 @@ return graph -def _nested_package_uml_graph(packages, linker, context=None, **options): +def uml_package_tree_graph(packages, linker, context=None, **options): """ Return a `DotGraph` that graphically displays the package hierarchies for the given packages as a nested set of UML @@ -939,86 +970,11 @@ # If the context is a variable, then get its value. if isinstance(context, VariableDoc) and context.value is not UNKNOWN: context = context.value - # Build one (complex) node for each root package. + # Return a graph with one node for each root package. for package in root_packages: - html_label, _, _ = _nested_uml_package_label(package, linker, context) - node = DotGraphNode(html_label=html_label, shape='plaintext', - href=linker.url_for(package) or NOOP_URL, - tooltip=package.canonical_name) - graph.nodes.append(node) + graph.nodes.append(DotGraphUmlModuleNode(package, linker, context)) return graph -def _nested_uml_package_label(package, linker, context): - """ - :Return: (label, depth, width) where: - - - `label` is the HTML label - - `depth` is the depth of the package tree - - `width` is the max width of the HTML label, roughly in - units of characters. - - :todo: Add hrefs/tooltips to appropriate <td> or <table> cells. - """ - MAX_ROW_WIDTH = 80 # unit is roughly characters. - pkg_name = package.canonical_name - pkg_url = linker.url_for(package) or NOOP_URL - - if not package.is_package or len(package.submodules) == 0: - pkg_color = _nested_uml_package_color(package, context, 1) - label = MODULE_NODE_HTML % (pkg_color, pkg_color, pkg_url, - pkg_name, pkg_name[-1]) - return (label, 1, len(pkg_name[-1])+3) - - submodule_labels = [_nested_uml_package_label(submodule, linker, context) - for submodule in package.submodules] - - ROW_HDR = '<TABLE BORDER="0" CELLBORDER="0"><TR>' - # Build the body of the package's icon. - body = '<TABLE BORDER="0" CELLBORDER="0">' - body += '<TR><TD ALIGN="LEFT">%s</TD></TR>' % pkg_name[-1] - body += '<TR><TD>%s' % ROW_HDR - row_width = [0] - for i, (label, depth, width) in enumerate(submodule_labels): - if row_width[-1] > 0 and width+row_width[-1] > MAX_ROW_WIDTH: - body += '</TR></TABLE></TD></TR>' - body += '<TR><TD>%s' % ROW_HDR - row_width.append(0) - #submodule_url = linker.url_for(package.submodules[i]) or '#' - #submodule_name = package.submodules[i].canonical_name - body += '<TD ALIGN="LEFT">%s</TD>' % label - row_width [-1] += width - body += '</TR></TABLE></TD></TR></TABLE>' - - # Put together our return value. - depth = max([d for (l,d,w) in submodule_labels])+1 - pkg_color = _nested_uml_package_color(package, context, depth) - label = ('<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"><TR>' - '<TD ALIGN="LEFT" HEIGHT="8" WIDTH="16" FIXEDSIZE="true" ' - 'BORDER="1" VALIGN="BOTTOM" BGCOLOR="%s"></TD></TR><TR>' - '<TD COLSPAN="5" VALIGN="TOP" ALIGN="LEFT" BORDER="1" ' - 'BGCOLOR="%s" HREF="%s" TOOLTIP="%s">%s</TD></TR></TABLE>' % - (pkg_color, pkg_color, pkg_url, pkg_name, body)) - width = max(max(row_width), len(pkg_name[-1])+3) - return label, depth, width - -def _nested_uml_package_color(package, context, depth): - if package == context: return SELECTED_BG - else: - # Parse the base color. - if re.match(MODULE_BG, 'r#[0-9a-fA-F]{6}$'): - base = int(MODULE_BG[1:], 16) - else: - base = int('d8e8ff', 16) - red = (base & 0xff0000) >> 16 - green = (base & 0x00ff00) >> 8 - blue = (base & 0x0000ff) - # Make it darker with each level of depth. - red = max(0, red-(depth-1)*10) - green = max(0, green-(depth-1)*10) - blue = max(0, blue-(depth-1)*10) - # Convert it back to a color string - return '#%06x' % ((red<<16)+(green<<8)+blue) - ###################################################################### def class_tree_graph(bases, linker, context=None, **options): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 18:17:57
|
Revision: 1197 Author: edloper Date: 2006-04-09 11:17:52 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1197&view=rev Log Message: ----------- - Added support for drawing uml class graphs (many thanks to Daniele Varrazzo for the initial code!) - Modified breadcrumbs, so the 'no frames' link works better when viewing source code - Fixed bug in url() for imported variables. - Modified HIDE_PRIVATE_JS so it won't hide private variables if location.href appears to have a private anchor. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-09 18:15:55 UTC (rev 1196) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-04-09 18:17:52 UTC (rev 1197) @@ -587,7 +587,7 @@ # Write the page header (incl. navigation bar & breadcrumbs) self.write_header(out, str(longname)) self.write_navbar(out, doc) - self.write_breadcrumbs(out, doc) + self.write_breadcrumbs(out, doc, self.url(doc)) # Write the name of the module we're describing. if doc.is_package is True: typ = 'Package' @@ -645,7 +645,7 @@ # Header self.write_header(out, name) self.write_navbar(out, doc) - self.write_breadcrumbs(out, doc) + self.write_breadcrumbs(out, doc, self.pysrc_url(doc)) # Source code listing out('<h2 class="py-src">Source Code for %s</h2>\n' % @@ -678,7 +678,7 @@ # Write the page header (incl. navigation bar & breadcrumbs) self.write_header(out, str(longname)) self.write_navbar(out, doc) - self.write_breadcrumbs(out, doc) + self.write_breadcrumbs(out, doc, self.url(doc)) # Write the name of the class we're describing. if doc.is_type(): typ = 'Type' @@ -695,8 +695,13 @@ if ((doc.bases not in (UNKNOWN, None) and len(doc.bases) > 0) or (doc.subclasses not in (UNKNOWN,None) and len(doc.subclasses)>0)): # Display bases graphically, if requested. - if 'classtree' in self._graph_types: + if 'umlclasstree' in self._graph_types: linker = _HTMLDocstringLinker(self, doc) + graph = uml_class_tree_graph(doc, linker, doc) + out('<center>\n%s</center>\n' % self.render_graph(graph)) + + elif 'classtree' in self._graph_types: + linker = _HTMLDocstringLinker(self, doc) graph = class_tree_graph([doc], linker, doc) out('<center>\n%s</center>\n' % self.render_graph(graph)) @@ -773,7 +778,7 @@ # Header material. self.write_header(out, 'Trees') self.write_navbar(out, 'trees') - self.write_breadcrumbs(out, 'trees') + self.write_breadcrumbs(out, 'trees', 'trees.html') # Write the module hierarchy out('<!-- ==================== ' @@ -812,7 +817,7 @@ # Header material. self.write_header(out, 'Index') self.write_navbar(out, 'indices') - self.write_breadcrumbs(out, 'indices') + self.write_breadcrumbs(out, 'indices', 'indices.html') out('<br />\n') terms = self._extract_term_index() @@ -957,7 +962,7 @@ # Insert the help contents into a webpage. self.write_header(out, 'Help') self.write_navbar(out, 'help') - self.write_breadcrumbs(out, 'help') + self.write_breadcrumbs(out, 'help', 'help.html') out(help) self.write_navbar(out, 'help') self.write_footer(out) @@ -1303,11 +1308,15 @@ parent.frames[2].location.href = url2; } '''.strip() - + + #: A javascript that is used to hide private variables, unless + #: either: (a) the cookie says not to; or (b) we appear to be + #: linking to a private variable. HIDE_PRIVATE_JS = ''' function checkCookie() { var cmd=getCookie("EpydocPrivate"); - if (cmd!="show private") {toggle_private();} + if (cmd!="show private" && location.href.indexOf("#_") < 0) + toggle_private(); } '''.strip() @@ -1350,7 +1359,7 @@ def callgraph_link(self, callgraph): if callgraph is None: return '' - return ('<br /><span class="codelink"><a href="#" ' + return ('<br /><span class="codelink"><a href="javascript: void(0);" ' 'onclick="toggleCallGraph(\'%s-div\');return false;">' 'call graph</a></span> ' % callgraph.uid) @@ -1510,7 +1519,7 @@ write_breadcrumbs = compile_template( """ - write_breadcrumbs(self, out, context) + write_breadcrumbs(self, out, context, context_url) Generate HTML for the breadcrumbs line, and write it to C{out}. The breadcrumbs line is an invisible table with a @@ -1547,7 +1556,7 @@ >>> #endif <tr><td align="right"><span class="options" >[<a href="frames.html" target="_top">frames</a - >] | <a href="$self.url(context)$" + >] | <a href="$context_url$" target="_top">no frames</a>]</span></td></tr> </table> </td> @@ -2748,7 +2757,13 @@ if isinstance(val_doc, (ModuleDoc, ClassDoc)): return self.url(val_doc) elif obj.container in (None, UNKNOWN): + if val_doc in (None, UNKNOWN): return None return self.url(val_doc) + elif obj.is_imported == True: + if obj.imported_from is not UNKNOWN: + return self.url(obj.imported_from) + else: + return None else: container_url = self.url(obj.container) if container_url is None: return None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 18:16:00
|
Revision: 1196 Author: edloper Date: 2006-04-09 11:15:55 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1196&view=rev Log Message: ----------- - Added support for drawing uml class graphs (many thanks to Daniele Varrazzo for the initial code!) - Changed default node/edge defaults to use 10pt helvetica Modified Paths: -------------- trunk/epydoc/src/epydoc/cli.py trunk/epydoc/src/epydoc/docwriter/dotgraph.py Modified: trunk/epydoc/src/epydoc/cli.py =================================================================== --- trunk/epydoc/src/epydoc/cli.py 2006-04-09 18:12:40 UTC (rev 1195) +++ trunk/epydoc/src/epydoc/cli.py 2006-04-09 18:15:55 UTC (rev 1196) @@ -69,7 +69,7 @@ import ConfigParser INHERITANCE_STYLES = ('grouped', 'listed', 'included') -GRAPH_TYPES = ('classtree', 'callgraph') +GRAPH_TYPES = ('classtree', 'callgraph', 'umlclasstree') ACTIONS = ('html', 'text', 'latex', 'dvi', 'ps', 'pdf', 'check') DEFAULT_DOCFORMAT = 'epytext' Modified: trunk/epydoc/src/epydoc/docwriter/dotgraph.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-09 18:12:40 UTC (rev 1195) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-09 18:15:55 UTC (rev 1196) @@ -27,6 +27,15 @@ from epydoc.util import * from epydoc.compat import * # Backwards compatibility +# colors for graphs of APIDocs +MODULE_BG = '#d8e8ff' +CLASS_BG = '#d8ffe8' +SELECTED_BG = '#ffd0d0' +BASECLASS_BG = '#e0b0a0' +SUBCLASS_BG = '#e0b0a0' +ROUTINE_BG = '#e8d0b0' # maybe? +INH_LINK_COLOR = '#800000' + ###################################################################### #{ Dot Graphs ###################################################################### @@ -64,6 +73,9 @@ """A set of all uids that that have been generated, used to ensure that each new graph has a unique uid.""" + DEFAULT_NODE_DEFAULTS={'fontsize':10, 'fontname': 'helvetica'} + DEFAULT_EDGE_DEFAULTS={'fontsize':10, 'fontname': 'helvetica'} + def __init__(self, title, body='', node_defaults=None, edge_defaults=None, caption=None): """ @@ -78,12 +90,12 @@ self.nodes = [] """A list of the nodes that are present in the graph. - :type: `list` of `DocGraphNode`""" + :type: `list` of `DotGraphNode`""" self.edges = [] """A list of the edges that are present in the graph. - :type: `list` of `DocGraphEdge`""" + :type: `list` of `DotGraphEdge`""" self.body = body """A string that should be included as-is in the body of the @@ -91,10 +103,10 @@ :type: `str`""" - self.node_defaults = node_defaults or {} + self.node_defaults = node_defaults or self.DEFAULT_NODE_DEFAULTS """Default attribute values for nodes.""" - self.edge_defaults = edge_defaults or {} + self.edge_defaults = edge_defaults or self.DEFAULT_EDGE_DEFAULTS """Default attribute values for edges.""" self.uid = re.sub(r'\W', '_', title).lower() @@ -277,7 +289,8 @@ """ Return the dot commands that should be used to render this node. """ - attribs = ['%s="%s"' % (k,v) for (k,v) in self._attribs.items()] + attribs = ['%s="%s"' % (k,v) for (k,v) in self._attribs.items() + if v is not None] if self._html_label: attribs.insert(0, 'label=<%s>' % (self._html_label,)) if attribs: attribs = ' [%s]' % (','.join(attribs)) @@ -289,6 +302,8 @@ :type start: `DotGraphNode` :type end: `DotGraphNode` """ + assert isinstance(start, DotGraphNode) + assert isinstance(end, DotGraphNode) if label is not None: attribs['label'] = label self.start = start #: :type: `DotGraphNode` self.end = end #: :type: `DotGraphNode` @@ -311,12 +326,559 @@ if (self.end.port is not None and 'tailport' not in attribs): attribs['tailport'] = self.end.port # Convert attribs to a string - attribs = ','.join(['%s="%s"' % (k,v) for (k,v) in attribs.items()]) + attribs = ','.join(['%s="%s"' % (k,v) for (k,v) in attribs.items() + if v is not None]) if attribs: attribs = ' [%s]' % attribs # Return the dotfile edge. return 'node%d -> node%d%s' % (self.start.id, self.end.id, attribs) ###################################################################### +#{ Specialized Nodes for UML Graphs +###################################################################### + +class DotGraphUmlClassNode(DotGraphNode): + """ + A specialized dot graph node used to display C{ClassDoc}s using + UML notation. The node is rendered as a table with three cells: + the top cell contains the class name; the middle cell contains a + list of attributes; and the bottom cell contains a list of + operations:: + + +-------------+ + | ClassName | + +-------------+ + | x: int | + | ... | + +-------------+ + | f(self, x) | + | ... | + +-------------+ + + `DotGraphUmlClassNode`s may be *collapsed*, in which case they are + drawn as a simple box containing the class name:: + + +-------------+ + | ClassName | + +-------------+ + + Attributes with types corresponding to documented classes can + optionally be converted into edges, using `link_attributes()`. + + :todo: Add more options? + - show/hide operation signature + - show/hide operation signature types + - show/hide operation signature return type + - show/hide attribute types + - use qualifiers + """ + + def __init__(self, class_doc, linker, context, collapsed=False, + bgcolor=CLASS_BG, **options): + """ + Create a new `DotGraphUmlClassNode` based on the class + `class_doc`. + + :Parameters: + linker: `DocstringLinker<markup.DocstringLinker>` + Used to look up URLs for classes. + context: `APIDoc` + The context in which this node will be drawn; dotted + names will be contextualized to this context. + collapsed: ``bool`` + If true, then display this node as a simple box. + bgcolor: ``str`` + The background color for this node. + options: ``dict`` + A set of options used to control how the node should + be displayed. + + :Keywords: + - `show_private_vars`: If false, then private variables + are filtered out of the attributes & operations lists. + (Default: *False*) + - `show_magic_vars`: If false, then magic variables + (such as ``__init__`` and ``__add__``) are filtered out of + the attributes & operations lists. (Default: *True*) + - `show_inherited_vars`: If false, then inherited variables + are filtered out of the attributes & operations lists. + (Default: *False*) + - `max_attributes`: The maximum number of attributes that + should be listed in the attribute box. If the class has + more than this number of attributes, some will be + ellided. Ellipsis is marked with ``'...'``. + - `max_operations`: The maximum number of operations that + should be listed in the operation box. + - `add_nodes_for_linked_attributes`: If true, then + `link_attributes()` will create new a collapsed node for + the types of a linked attributes if no node yet exists for + that type. + """ + self.class_doc = class_doc + """The class represented by this node.""" + + self.linker = linker + """Used to look up URLs for classes.""" + + self.context = context + """The context in which the node will be drawn.""" + + self.bgcolor = bgcolor + """The background color of the node.""" + + self.options = options + """Options used to control how the node is displayed.""" + + self.collapsed = collapsed + """If true, then draw this node as a simple box.""" + + self.attributes = [] + """The list of VariableDocs for attributes""" + + self.operations = [] + """The list of VariableDocs for operations""" + + self.qualifiers = [] + """List of (key_label, port) tuples.""" + + self.edges = [] + """List of edges used to represent this node's attributes. + These should not be added to the `DotGraph`; this node will + generate their dotfile code directly.""" + + # Initialize operations & attributes lists. + show_private = options.get('show_private_vars', False) + show_magic = options.get('show_magic_vars', True) + show_inherited = options.get('show_inherited_vars', False) + for name, var in class_doc.variables.iteritems(): + if ((not show_private and var.is_public == False) or + (not show_magic and re.match('__\w+__$', name)) or + (not show_inherited and var.container != class_doc)): + pass + elif isinstance(var.value, RoutineDoc): + self.operations.append(var) + else: + self.attributes.append(var) + + # Initialize our dot node settings. + DotGraphNode.__init__(self, tooltip=class_doc.canonical_name, + width=0, height=0, shape='plaintext', + href=linker.url_for(class_doc) or NOOP_URL) + + #///////////////////////////////////////////////////////////////// + #{ Attribute Linking + #///////////////////////////////////////////////////////////////// + + SIMPLE_TYPE_RE = re.compile( + r'^([\w\.]+)$') + """A regular expression that matches descriptions of simple types.""" + + COLLECTION_TYPE_RE = re.compile( + r'^(list|set|sequence|tuple|collection) of ([\w\.]+)$') + """A regular expression that matches descriptions of collection types.""" + + MAPPING_TYPE_RE = re.compile( + r'^(dict|dictionary|map|mapping) from ([\w\.]+) to ([\w\.]+)$') + """A regular expression that matches descriptions of mapping types.""" + + MAPPING_TO_COLLECTION_TYPE_RE = re.compile( + r'^(dict|dictionary|map|mapping) from ([\w\.]+) to ' + r'(list|set|sequence|tuple|collection) of ([\w\.]+)$') + """A regular expression that matches descriptions of mapping types + whose value type is a collection.""" + + OPTIONAL_TYPE_RE = re.compile( + r'^(None or|optional) ([\w\.]+)$|^([\w\.]+) or None$') + """A regular expression that matches descriptions of optional types.""" + + def link_attributes(self, nodes): + """ + Convert any attributes with type descriptions corresponding to + documented classes to edges. The following type descriptions + are currently handled: + + - Dotted names: Create an attribute edge to the named type, + labelled with the variable name. + - Collections: Create an attribute edge to the named type, + labelled with the variable name, and marked with '*' at the + type end of the edge. + - Mappings: Create an attribute edge to the named type, + labelled with the variable name, connected to the class by + a qualifier box that contains the key type description. + - Optional: Create an attribute edge to the named type, + labelled with the variable name, and marked with '0..1' at + the type end of the edge. + + The edges created by `link_attribute()` are handled internally + by `DotGraphUmlClassNode`; they should *not* be added directly + to the `DotGraph`. + + :param nodes: A dictionary mapping from `ClassDoc`s to + `DotGraphUmlClassNode`s, used to look up the nodes for + attribute types. If the ``add_nodes_for_linked_attributes`` + option is used, then new nodes will be added to this + dictionary for any types that are not already listed. + These added nodes must be added to the `DotGraph`. + """ + # Try to convert each attribute var into a graph edge. If + # _link_attribute returns true, then it succeeded, so remove + # that var from our attribute list; otherwise, leave that var + # in our attribute list. + self.attributes = [var for var in self.attributes + if not self._link_attribute(var, nodes)] + + def _link_attribute(self, var, nodes): + """ + Helper for `link_attributes()`: try to convert the attribute + variable `var` into an edge, and add that edge to + `self.edges`. Return ``True`` iff the variable was + successfully converted to an edge (in which case, it should be + removed from the attributes list). + """ + type_descr = self._type_descr(var) or self._type_descr(var.value) + + # Simple type. + m = self.SIMPLE_TYPE_RE.match(type_descr) + if m and self._add_attribute_edge(var, nodes, m.group(1)): + return True + + # Collection type. + m = self.COLLECTION_TYPE_RE.match(type_descr) + if m and self._add_attribute_edge(var, nodes, m.group(2), + headlabel='*'): + return True + + # Optional type. + m = self.OPTIONAL_TYPE_RE.match(type_descr) + if m and self._add_attribute_edge(var, nodes, m.group(2) or m.group(3), + headlabel='0..1'): + return True + + # Mapping type. + m = self.MAPPING_TYPE_RE.match(type_descr) + if m: + port = 'qualifier_%s' % var.name + if self._add_attribute_edge(var, nodes, m.group(3), + tailport='%s:e' % port): + self.qualifiers.append( (m.group(2), port) ) + return True + + # Mapping to collection type. + m = self.MAPPING_TO_COLLECTION_TYPE_RE.match(type_descr) + if m: + port = 'qualifier_%s' % var.name + if self._add_attribute_edge(var, nodes, m.group(4), headlabel='*', + tailport='%s:e' % port): + self.qualifiers.append( (m.group(2), port) ) + return True + + # We were unable to link this attribute. + return False + + def _add_attribute_edge(self, var, nodes, type_str, **attribs): + """ + Helper for `link_attribute()`: try to add an edge for the + given attribute variable `var`. Return ``True`` if + successful. + """ + # Use the type string to look up a corresponding ValueDoc. + type_doc = self.linker.docindex.find(type_str, var) + if not type_doc: return False + + # Get the type ValueDoc's node. If it doesn't have one (and + # add_nodes_for_linked_attributes=True), then create it. + type_node = nodes.get(type_doc) + if not type_node: + if self.options.get('add_nodes_for_linked_attributes', True): + type_node = DotGraphUmlClassNode(type_doc, self.linker, + self.context, collapsed=True) + nodes[type_doc] = type_node + else: + return False + + # Add an edge from self to the target type node. + # [xx] should I set constraint=false here? + attribs.setdefault('headport', 'body') + attribs.setdefault('tailport', 'body') + url = self.linker.url_for(var) or NOOP_URL + self.edges.append(DotGraphEdge(self, type_node, label=var.name, + arrowhead='open', href=url, + tooltip=var.canonical_name, labeldistance=1.5, + **attribs)) + return True + + #///////////////////////////////////////////////////////////////// + #{ Helper Methods + #///////////////////////////////////////////////////////////////// + def _summary(self, api_doc): + """Return a plaintext summary for `api_doc`""" + if not isinstance(api_doc, APIDoc): return '' + if api_doc.summary in (None, UNKNOWN): return '' + summary = api_doc.summary.to_plaintext(self.linker).strip() + return plaintext_to_html(summary) + + def _type_descr(self, api_doc): + """Return a plaintext type description for `api_doc`""" + if not hasattr(api_doc, 'type_descr'): return '' + if api_doc.type_descr in (None, UNKNOWN): return '' + type_descr = api_doc.type_descr.to_plaintext(self.linker).strip() + return plaintext_to_html(type_descr) + + def _tooltip(self, var_doc): + """Return a tooltip for `var_doc`.""" + return (self._summary(var_doc) or + self._summary(var_doc.value) or + var_doc.canonical_name) + + #///////////////////////////////////////////////////////////////// + #{ Rendering + #///////////////////////////////////////////////////////////////// + + def _attribute_cell(self, var_doc): + # Construct the label + label = var_doc.name + type_descr = (self._type_descr(var_doc) or + self._type_descr(var_doc.value)) + if type_descr: label += ': %s' % type_descr + # Get the URL + url = self.linker.url_for(var_doc) or NOOP_URL + # Construct & return the pseudo-html code + return self._ATTRIBUTE_CELL % (url, self._tooltip(var_doc), label) + + def _operation_cell(self, var_doc): + """ + :todo: do 'word wrapping' on the signature, by starting a new + row in the table, if necessary. How to indent the new + line? Maybe use align=right? I don't think dot has a + . + :todo: Optionally add return type info? + """ + # Construct the label (aka function signature) + func_doc = var_doc.value + args = [self._operation_arg(n, d, func_doc) for (n, d) + in zip(func_doc.posargs, func_doc.posarg_defaults)] + args = [plaintext_to_html(arg) for arg in args] + if func_doc.vararg: args.append('*'+func_doc.vararg) + if func_doc.kwarg: args.append('**'+func_doc.kwarg) + label = '%s(%s)' % (var_doc.name, ', '.join(args)) + # Get the URL + url = self.linker.url_for(var_doc) or NOOP_URL + # Construct & return the pseudo-html code + return self._OPERATION_CELL % (url, self._tooltip(var_doc), label) + + def _operation_arg(self, name, default, func_doc): + """ + :todo: Handle tuple args better + :todo: Optionally add type info? + """ + if default is None: + return '%s' % name + elif default.parse_repr is not UNKNOWN: + return '%s=%s' % (name, default.parse_repr) + else: + pyval_repr = default.pyval_repr() + if pyval_repr is not UNKNOWN: + return '%s=%s' % (name, pyval_repr) + else: + return '%s=??' % name + + def _qualifier_cell(self, key_label, port): + return self._QUALIFIER_CELL % (port, self.bgcolor, key_label) + + #: args: (url, tooltip, label) + _ATTRIBUTE_CELL = ''' + <TR><TD ALIGN="LEFT" HREF="%s" TOOLTIP="%s">%s</TD></TR> + ''' + + #: args: (url, tooltip, label) + _OPERATION_CELL = ''' + <TR><TD ALIGN="LEFT" HREF="%s" TOOLTIP="%s">%s</TD></TR> + ''' + + #: args: (port, bgcolor, label) + _QUALIFIER_CELL = ''' + <TR><TD VALIGN="BOTTOM" PORT="%s" BGCOLOR="%s" BORDER="1">%s</TD></TR> + ''' + + _QUALIFIER_DIV = ''' + <TR><TD VALIGN="BOTTOM" HEIGHT="10" WIDTH="10" FIXEDSIZE="TRUE"></TD></TR> + ''' + + #: Args: (rowspan, bgcolor, classname, attributes, operations, qualifiers) + _LABEL = ''' + <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" CELLPADDING="0"> + <TR><TD ROWSPAN="%s"> + <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" + CELLPADDING="0" PORT="body" BGCOLOR="%s"> + <TR><TD>%s</TD></TR> + <TR><TD><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"> + %s</TABLE></TD></TR> + <TR><TD><TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"> + %s</TABLE></TD></TR> + </TABLE> + </TD></TR> + %s + </TABLE>''' + + _COLLAPSED_LABEL = ''' + <TABLE CELLBORDER="0" BGCOLOR="%s" PORT="body"> + <TR><TD>%s</TD></TR> + </TABLE>''' + + def _get_html_label(self): + # Get the class name & contextualize it. + classname = self.class_doc.canonical_name + classname = classname.contextualize(self.context.canonical_name) + + # If we're collapsed, display the node as a single box. + if self.collapsed: + return self._COLLAPSED_LABEL % (self.bgcolor, classname) + + # Construct the attribute list. (If it's too long, truncate) + attrib_cells = [self._attribute_cell(a) for a in self.attributes] + if len(attrib_cells) == 0: + attrib_cells = ['<TR><TD></TD></TR>'] + elif len(attrib_cells) > self.options.get('max_attributes', 15): + attrib_cells[max_attributes-2:-1] = ['<TR><TD>...</TD></TR>'] + attributes = ''.join(attrib_cells) + + # Construct the operation list. (If it's too long, truncate) + oper_cells = [self._operation_cell(a) for a in self.operations] + if len(oper_cells) == 0: + oper_cells = ['<TR><TD></TD></TR>'] + elif len(oper_cells) > self.options.get('max_operations', 15): + oper_cells[max_operations-2:-1] = ['<TR><TD>...</TD></TR>'] + operations = ''.join(oper_cells) + + # Construct the qualifier list & determine the rowspan. + if self.qualifiers: + rowspan = len(self.qualifiers)*2+2 + div = self._QUALIFIER_DIV + qualifiers = div+div.join([self._qualifier_cell(l,p) for + (l,p) in self.qualifiers])+div + else: + rowspan = 1 + qualifiers = '' + + # Put it all together. + return self._LABEL % (rowspan, self.bgcolor, classname, + attributes, operations, qualifiers) + + def to_dotfile(self): + attribs = ['%s="%s"' % (k,v) for (k,v) in self._attribs.items()] + attribs.append('label=<%s>' % self._get_html_label()) + s = 'node%d%s' % (self.id, ' [%s]' % (','.join(attribs))) + if not self.collapsed: + for edge in self.edges: + s += '\n' + edge.to_dotfile() + return s + +# [XX] Not used yet. +class DotGraphUmlModuleNode(DotGraphNode): + """ + A specialized dot grah node used to display C{ModuleDoc}s using + UML notation. Simple module nodes look like:: + + .----. + +------------+ + | modulename | + +------------+ + + Packages nodes are drawn with their modules & subpackages nested + inside:: + + .----. + +----------------------------------------+ + | packagename | + | | + | .----. .----. .----. | + | +---------+ +---------+ +---------+ | + | | module1 | | module2 | | module3 | | + | +---------+ +---------+ +---------+ | + | | + +----------------------------------------+ + + """ + def __init__(self, module_doc, linker, context, collapsed=False, + **options): + self.module_doc = module_doc + self.linker = linker + self.context = context + + def _nested_package_label(package): + """ + :Return: (label, depth, width) where: + + - `label` is the HTML label + - `depth` is the depth of the package tree (for coloring) + - `width` is the max width of the HTML label, roughly in + units of characters. + """ + MAX_ROW_WIDTH = 80 # unit is roughly characters. + pkg_name = package.canonical_name + pkg_url = self.linker.url_for(package) or NOOP_URL + + if not package.is_package or len(package.submodules) == 0: + pkg_color = _nested_uml_package_color(package, self.context, 1) + label = MODULE_NODE_HTML % (pkg_color, pkg_color, pkg_url, + pkg_name, pkg_name[-1]) + return (label, 1, len(pkg_name[-1])+3) + + submodule_labels = [self._nested_package_label(submodule, self.linker, + self.context) + for submodule in package.submodules] + + ROW_HDR = '<TABLE BORDER="0" CELLBORDER="0"><TR>' + # Build the body of the package's icon. + body = '<TABLE BORDER="0" CELLBORDER="0">' + body += '<TR><TD ALIGN="LEFT">%s</TD></TR>' % pkg_name[-1] + body += '<TR><TD>%s' % ROW_HDR + row_width = [0] + for i, (label, depth, width) in enumerate(submodule_labels): + if row_width[-1] > 0 and width+row_width[-1] > MAX_ROW_WIDTH: + body += '</TR></TABLE></TD></TR>' + body += '<TR><TD>%s' % ROW_HDR + row_width.append(0) + #submodule_url = self.linker.url_for(package.submodules[i]) or '#' + #submodule_name = package.submodules[i].canonical_name + body += '<TD ALIGN="LEFT">%s</TD>' % label + row_width [-1] += width + body += '</TR></TABLE></TD></TR></TABLE>' + + # Put together our return value. + depth = max([d for (l,d,w) in submodule_labels])+1 + pkg_color = self._color(package, depth) + label = ('<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"><TR>' + '<TD ALIGN="LEFT" HEIGHT="8" WIDTH="16" FIXEDSIZE="true" ' + 'BORDER="1" VALIGN="BOTTOM" BGCOLOR="%s"></TD></TR><TR>' + '<TD COLSPAN="5" VALIGN="TOP" ALIGN="LEFT" BORDER="1" ' + 'BGCOLOR="%s" HREF="%s" TOOLTIP="%s">%s</TD></TR></TABLE>' % + (pkg_color, pkg_color, pkg_url, pkg_name, body)) + width = max(max(row_width), len(pkg_name[-1])+3) + return label, depth, width + + def _color(package, depth): + if package == self.context: return SELECTED_BG + else: + # Parse the base color. + if re.match(MODULE_BG, 'r#[0-9a-fA-F]{6}$'): + base = int(MODULE_BG[1:], 16) + else: + base = int('d8e8ff', 16) + red = (base & 0xff0000) >> 16 + green = (base & 0x00ff00) >> 8 + blue = (base & 0x0000ff) + # Make it darker with each level of depth. (but not *too* + # dark -- package name needs to be readable) + red = max(64, red-(depth-1)*10) + green = max(64, green-(depth-1)*10) + blue = max(64, blue-(depth-1)*10) + # Convert it back to a color string + return '#%06x' % ((red<<16)+(green<<8)+blue) + + + + +###################################################################### #{ Graph Generation Functions ###################################################################### @@ -381,7 +943,7 @@ for package in root_packages: html_label, _, _ = _nested_uml_package_label(package, linker, context) node = DotGraphNode(html_label=html_label, shape='plaintext', - url=linker.url_for(package), + href=linker.url_for(package) or NOOP_URL, tooltip=package.canonical_name) graph.nodes.append(node) return graph @@ -500,6 +1062,88 @@ return graph ###################################################################### +def uml_class_tree_graph(class_doc, linker, context=None, **options): + """ + Return a `DotGraph` that graphically displays the class hierarchy + for the given class, using UML notation. Options: + - max_attributes + - max_operations + - show_private_vars + - show_magic_vars + - link_attributes + """ + nodes = {} # ClassDoc -> DotGraphUmlClassNode + + # Create nodes for class_doc and all its bases. + for cls in class_doc.mro(): + if cls.pyval is object: continue # don't include `object`. + if cls == class_doc: color = SELECTED_BG + else: color = BASECLASS_BG + nodes[cls] = DotGraphUmlClassNode(cls, linker, context, + show_inherited_vars=False, + collapsed=False, bgcolor=color) + + # Create nodes for all class_doc's subclasses. + queue = [class_doc] + for cls in queue: + if cls.subclasses not in (None, UNKNOWN): + queue.extend(cls.subclasses) + for cls in cls.subclasses: + if cls not in nodes: + nodes[cls] = DotGraphUmlClassNode(cls, linker, context, + collapsed=True, + bgcolor=SUBCLASS_BG) + + # Only show variables in the class where they're defined for + # *class_doc*. + mro = class_doc.mro() + for name, var in class_doc.variables.items(): + i = mro.index(var.container) + for base in mro[i+1:]: + if base.pyval is object: continue # don't include `object`. + overridden_var = base.variables.get(name) + if overridden_var and overridden_var.container == base: + try: + if isinstance(overridden_var.value, RoutineDoc): + nodes[base].operations.remove(overridden_var) + else: + nodes[base].attributes.remove(overridden_var) + except ValueError: + pass # var is filtered (eg private or magic) + + # Keep track of which nodes are part of the inheritance graph + # (since link_attributes might add new nodes) + inheritance_nodes = set(nodes.values()) + + # Turn attributes into links. + if options.get('link_attributes', True): + for node in nodes.values(): + node.link_attributes(nodes) + # Make sure that none of the new attribute edges break the + # rank ordering assigned by inheritance. + for edge in node.edges: + if edge.end in inheritance_nodes: + edge['constraint'] = 'False' + + # Construct the graph. + graph = DotGraph('UML class diagram for %s' % class_doc, + body='ranksep=.2\n;nodesep=.3\n') + graph.nodes = nodes.values() + + # Add inheritance edges. + for node in inheritance_nodes: + for base in node.class_doc.bases: + if base in nodes: + graph.edges.append(DotGraphEdge(nodes[base], node, + dir='back', arrowtail='empty', + headport='body', tailport='body', + color=INH_LINK_COLOR, weight=100, + style='bold')) + + # And we're done! + return graph + +###################################################################### def import_graph(modules, docindex, linker, context=None, **options): graph = DotGraph('Import Graph', body='ranksep=.3\n;nodesep=.3\n') @@ -633,9 +1277,7 @@ specialize_valdoc_node(node, val_doc, context, linker.url_for(val_doc)) return nodes -NOOP_URL = '#' -NOOP_URL = 'javascript:;' # this option is more evil. - +NOOP_URL = 'javascript: void(0);' MODULE_NODE_HTML = ''' <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" CELLPADDING="0" PORT="table" ALIGN="LEFT"> @@ -644,8 +1286,6 @@ <TR><TD ALIGN="LEFT" VALIGN="TOP" BGCOLOR="%s" BORDER="1" PORT="body" HREF="%s" TOOLTIP="%s">%s</TD></TR> </TABLE>'''.strip() -MODULE_BG = '#d8e8ff' -SELECTED_BG = '#ffd0d0' def specialize_valdoc_node(node, val_doc, context, url): """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 18:12:42
|
Revision: 1195 Author: edloper Date: 2006-04-09 11:12:40 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1195&view=rev Log Message: ----------- In source code colorizer: - Added GUESS_LINK_TARGETS config var - Added 'none of the above' option for box when you click an ambiguous name Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html_colorize.py Modified: trunk/epydoc/src/epydoc/docwriter/html_colorize.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-04-09 18:11:11 UTC (rev 1194) +++ trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-04-09 18:12:40 UTC (rev 1195) @@ -497,8 +497,12 @@ } } -function kill_doclink() { - if (!this.contains(event.toElement)) { +function kill_doclink(id) { + if (id) { + var parent = document.getElementById(id); + parent.removeChild(parent.childNodes.item(0)); + } + else if (!this.contains(event.toElement)) { var parent = document.getElementById(this.parentID); parent.removeChild(parent.childNodes.item(0)); } @@ -553,10 +557,13 @@ //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>"; + box2.innerHTML = + "Which <b>"+name+"</b> do you want to see documentation for?" + + "<ul style=\'margin-bottom: 0;\'>" + + links + + "<li><a href=\'#\' style=\'text-decoration:none\' " + + "onclick=\'kill_doclink(\\""+id+"\\");return false;\'>"+ + "<i>None of the above</i></a></li></ul>"; } } ''' @@ -677,6 +684,11 @@ #: add tooltips for linked names. ADD_TOOLTIPS = True + #: If true, then try to guess which target is appropriate for + #: linked names; if false, then always open a div asking the + #: user which one they want. + GUESS_LINK_TARGETS = True + def __init__(self, module_filename, module_name, docindex=None, api_docs=None, url_func=None): """ @@ -973,7 +985,7 @@ # 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: + if None not in self.context and self.GUESS_LINK_TARGETS: container = DottedName(self.module_name, *self.context) doc = self.docindex.get_vardoc(container+toktext) if doc is not None: @@ -985,7 +997,7 @@ if docs: tooltip='\n'.join(['%s'%d.canonical_name for d in docs]) - if len(docs) == 1: + if len(docs) == 1 and self.GUESS_LINK_TARGETS: url = self.url_func(docs[0]) else: uid, onclick = self.doclink(toktext, docs) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 18:11:13
|
Revision: 1194 Author: edloper Date: 2006-04-09 11:11:11 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1194&view=rev Log Message: ----------- - Underline py-name links in sourcecode output. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html_css.py Modified: trunk/epydoc/src/epydoc/docwriter/html_css.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-09 18:10:28 UTC (rev 1193) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-09 18:11:11 UTC (rev 1194) @@ -131,7 +131,7 @@ padding-left: .4em; } .lineno { font-style: italic; font-size: 90%; padding-left: .5em; } -a.py-name { text-decoration: none; } +/*a.py-name { text-decoration: none; }*/ /* For Graphs */ .graph-without-title { border: none; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-09 18:10:36
|
Revision: 1193 Author: edloper Date: 2006-04-09 11:10:28 -0700 (Sun, 09 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1193&view=rev Log Message: ----------- - When rendering a link as plaintext, render the label, not the target Modified Paths: -------------- trunk/epydoc/src/epydoc/markup/epytext.py Modified: trunk/epydoc/src/epydoc/markup/epytext.py =================================================================== --- trunk/epydoc/src/epydoc/markup/epytext.py 2006-04-07 23:40:05 UTC (rev 1192) +++ trunk/epydoc/src/epydoc/markup/epytext.py 2006-04-09 18:10:28 UTC (rev 1193) @@ -1325,7 +1325,7 @@ else: return '%r<%s>' % (variables[0], variables[1]) elif tree.tagName == 'link': if len(variables) != 2: raise ValueError('Bad Link') - return '%s' % variables[1] + return '%s' % variables[0] elif tree.tagName in ('olist', 'ulist'): # [xx] always use condensed lists. ## Use a condensed list if each list item is 1 line long. 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:40:11
|
Revision: 1192 Author: edloper Date: 2006-04-07 16:40:05 -0700 (Fri, 07 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1192&view=rev Log Message: ----------- - Docstring updates Modified Paths: -------------- trunk/epydoc/src/epydoc/__init__.py Modified: trunk/epydoc/src/epydoc/__init__.py =================================================================== --- trunk/epydoc/src/epydoc/__init__.py 2006-04-07 23:39:46 UTC (rev 1191) +++ trunk/epydoc/src/epydoc/__init__.py 2006-04-07 23:40:05 UTC (rev 1192) @@ -18,37 +18,37 @@ that are related to them (such as the values defined by a module). This can be done via introspection, parsing, or both: - * Use introspection to examine the objects directly. + * *Introspection* imports the objects, and examines them directly + using Python's introspection mechanisms. - * Parse the Python source files that define the objects, - and extract information from those files. + * *Parsing* reads the Python source files that define the objects, + and extracts information from those files. 2. Combine and process that information. - * Merge the information obtained from introspection & parsing - each object into a single structure. (This step is skipped if - information was extracted from only introspection or only - parsing.) + * **Merging**: Merge the information obtained from introspection & + parsing each object into a single structure. - * Replace any 'pointers' that were created for imported - variables with the documentation that they point to (if it's - available). + * **Linking**: Replace any \"pointers\" that were created for + imported variables with the documentation that they point to. - * Assign unique 'canonical names' to each of the specified - objects, and any related objects. + * **Naming**: Assign unique *canonical names* to each of the + specified objects, and any related objects. - * Parse the docstrings of each of the specified objects, and any - related objects. + * **Docstrings**: Parse the docstrings of each of the specified + objects. - * Add variables to classes for any values that they inherit from - their base classes. + * **Inheritance**: Add variables to classes for any values that + they inherit from their base classes. 3. Generate output. Output can be generated in a variety of formats: - * An HTML webpage + * An HTML webpage. - * other formats (under construction) + * A LaTeX document (which can be rendered as a PDF file) + * A plaintext description. + .. digraph:: Overview of epydoc's architecture :caption: The boxes represent steps in epydoc's processing chain. Arrows are annotated with the data classes used to @@ -113,10 +113,25 @@ href="<docbuilder.build_doc_index>"] l1 -> l2 [label=" epydoc.\\l cli()", href="<cli>"] } - { rank=same; l1 l3 introspect } + { rank=same; l1 l3 input } { rank=same; l2 write_html } { rank=same; l4 output } +Package Organization +==================== +The epydoc package contains the following subpackages and modules: + +.. packagetree:: + :style: UML + +The user interfaces are provided by the `gui` and `cli` modules. +The `apidoc` module defines the basic data types used to record +information about Python objects. The programmatic interface to +epydoc is provided by `docbuilder`. Docstring markup parsing is +handled by the `markup` package, and output generation is handled by +the `docwriter` package. See the submodule list for more +information about the submodules and subpackages. + :group User Interface: gui, cli :group Basic Data Types: apidoc :group Documentation Generation: docbuilder, docintrospecter, docparser 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:39:49
|
Revision: 1191 Author: edloper Date: 2006-04-07 16:39:46 -0700 (Fri, 07 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1191&view=rev Log Message: ----------- - Added 'style' option to packagetree directive Modified Paths: -------------- trunk/epydoc/src/epydoc/markup/restructuredtext.py Modified: trunk/epydoc/src/epydoc/markup/restructuredtext.py =================================================================== --- trunk/epydoc/src/epydoc/markup/restructuredtext.py 2006-04-07 23:38:47 UTC (rev 1190) +++ trunk/epydoc/src/epydoc/markup/restructuredtext.py 2006-04-07 23:39:46 UTC (rev 1191) @@ -659,7 +659,9 @@ """ return dotgraph(_construct_packagetree, arguments, options) packagetree_directive.arguments = (0, 1, True) -packagetree_directive.options = {'dir': _dir_option} +packagetree_directive.options = { + 'dir': _dir_option, + 'style': lambda a:directives.choice(a.lower(), ('uml', 'tree'))} packagetree_directive.content = False directives.register_directive('packagetree', packagetree_directive) 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:38:54
|
Revision: 1190 Author: edloper Date: 2006-04-07 16:38:47 -0700 (Fri, 07 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1190&view=rev Log Message: ----------- - Added 'center' option to DotGraph.to_html() - If graphviz dot prints to stderr, generate a warning with that output. - DotGraphNode's can now define a 'port' variable; edges connecting to it will connect to that port, unless otherwise specified. - Added 'uml' style for package_tree: draws the package as a nested set of uml package symbols. - Decrased minimum inter-node spacing in import graph - selected elements now use bold outlines (for some reason, filled,rounded style isn't working with my version of dot) Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/dotgraph.py Modified: trunk/epydoc/src/epydoc/docwriter/dotgraph.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-07 23:35:25 UTC (rev 1189) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-04-07 23:38:47 UTC (rev 1190) @@ -116,7 +116,7 @@ self.uid = '%s_%s' % (self.uid, n) self._uids.add(self.uid) - def to_html(self, image_url): + def to_html(self, image_url, center=True): """ Return the HTML code that should be uesd to display this graph (including a client-side image map). @@ -138,12 +138,13 @@ title_align = 'center' table_width = '' - s = '<center>' + if center: s = '<center>' if title or caption: - s += ('<table border="0" cellpadding="0" cellspacing="0" ' - '%s>\n <tr><td align="center">\n') % table_width + s += ('<p><table border="0" cellpadding="0" cellspacing="0" ' + 'class="graph"%s>\n <tr><td align="center">\n' % + table_width) s += (' %s\n <img src="%s" alt=%r usemap="#%s" ' - 'ismap="ismap" class=%s">\n' % + 'ismap="ismap" class="%s">\n' % (cmapx.strip(), image_url, title, self.uid, css_class)) if title or caption: s += ' </td></tr>\n <tr><td align=%r>\n' % title_align @@ -153,8 +154,8 @@ s += ' -- ' if caption: s += '<span class="graph-caption">%s</span>' % caption - s += '\n </th></tr>\n</table>' - s += '</center>' + s += '\n </th></tr>\n</table></p>' + if center: s += '</center>' return s def link(self, docstring_linker): @@ -217,6 +218,8 @@ # Decode into unicode, if necessary. if language == 'cmapx' and result is not None: result = result.decode('utf-8') + if err: + log.warning("Graphviz dot warning(s):\n%s" % err) except OSError, e: log.warning("Unable to render Graphviz dot graph:\n%s" % e) #log.debug(self.to_dotfile()) @@ -257,6 +260,7 @@ self._attribs = attribs self.id = self.__class__._next_id self.__class__._next_id += 1 + self.port = None def __getitem__(self, attr): return self._attribs[attr] @@ -275,7 +279,7 @@ """ attribs = ['%s="%s"' % (k,v) for (k,v) in self._attribs.items()] if self._html_label: - attribs.insert(0, 'label=<%s>' % self._html_label) + attribs.insert(0, 'label=<%s>' % (self._html_label,)) if attribs: attribs = ' [%s]' % (','.join(attribs)) return 'node%d%s' % (self.id, attribs) @@ -300,9 +304,16 @@ """ Return the dot commands that should be used to render this edge. """ - attribs = ','.join(['%s="%s"' % (k,v) for (k,v) - in self._attribs.items()]) + # Set head & tail ports, if the nodes have preferred ports. + attribs = self._attribs.copy() + if (self.start.port is not None and 'headport' not in attribs): + attribs['headport'] = self.start.port + if (self.end.port is not None and 'tailport' not in attribs): + attribs['tailport'] = self.end.port + # Convert attribs to a string + attribs = ','.join(['%s="%s"' % (k,v) for (k,v) in attribs.items()]) if attribs: attribs = ' [%s]' % attribs + # Return the dotfile edge. return 'node%d -> node%d%s' % (self.start.id, self.end.id, attribs) ###################################################################### @@ -314,12 +325,20 @@ Return a `DotGraph` that graphically displays the package hierarchies for the given packages. """ + if options.get('style', 'uml') == 'uml': # default to uml style? + if get_dot_version() >= [2]: + return _nested_package_uml_graph(packages, linker, context, + **options) + elif 'style' in options: + log.warning('UML style package trees require dot version 2.0+') + graph = DotGraph('Package Tree for %s' % name_list(packages, context), - edge_defaults={'sametail':True}) + body='ranksep=.3\n;nodesep=.1\n', + edge_defaults={'dir':'none'}) # Options - if options.get('dir', 'LR') != 'TB': # default: left-to-right - graph.body += 'rankdir=%s\n' % options.get('dir', 'LR') + if options.get('dir', 'TB') != 'TB': # default: top-to-bottom + graph.body += 'rankdir=%s\n' % options.get('dir', 'TB') # Get a list of all modules in the package. queue = list(packages) @@ -334,11 +353,111 @@ # Add an edge for each package/submodule relationship. for module in modules: for submodule in module.submodules: - graph.edges.append(DotGraphEdge(nodes[module], nodes[submodule])) + graph.edges.append(DotGraphEdge(nodes[module], nodes[submodule], + headport='tab')) return graph +def _nested_package_uml_graph(packages, linker, context=None, **options): + """ + Return a `DotGraph` that graphically displays the package + hierarchies for the given packages as a nested set of UML + symbols. + """ + graph = DotGraph('Package Tree for %s' % name_list(packages, context)) + # Remove any packages whose containers are also in the list. + root_packages = [] + for package1 in packages: + for package2 in packages: + if (package1 is not package2 and + package2.canonical_name.dominates(package1.canonical_name)): + break + else: + root_packages.append(package1) + # If the context is a variable, then get its value. + if isinstance(context, VariableDoc) and context.value is not UNKNOWN: + context = context.value + # Build one (complex) node for each root package. + for package in root_packages: + html_label, _, _ = _nested_uml_package_label(package, linker, context) + node = DotGraphNode(html_label=html_label, shape='plaintext', + url=linker.url_for(package), + tooltip=package.canonical_name) + graph.nodes.append(node) + return graph +def _nested_uml_package_label(package, linker, context): + """ + :Return: (label, depth, width) where: + + - `label` is the HTML label + - `depth` is the depth of the package tree + - `width` is the max width of the HTML label, roughly in + units of characters. + + :todo: Add hrefs/tooltips to appropriate <td> or <table> cells. + """ + MAX_ROW_WIDTH = 80 # unit is roughly characters. + pkg_name = package.canonical_name + pkg_url = linker.url_for(package) or NOOP_URL + + if not package.is_package or len(package.submodules) == 0: + pkg_color = _nested_uml_package_color(package, context, 1) + label = MODULE_NODE_HTML % (pkg_color, pkg_color, pkg_url, + pkg_name, pkg_name[-1]) + return (label, 1, len(pkg_name[-1])+3) + + submodule_labels = [_nested_uml_package_label(submodule, linker, context) + for submodule in package.submodules] + + ROW_HDR = '<TABLE BORDER="0" CELLBORDER="0"><TR>' + # Build the body of the package's icon. + body = '<TABLE BORDER="0" CELLBORDER="0">' + body += '<TR><TD ALIGN="LEFT">%s</TD></TR>' % pkg_name[-1] + body += '<TR><TD>%s' % ROW_HDR + row_width = [0] + for i, (label, depth, width) in enumerate(submodule_labels): + if row_width[-1] > 0 and width+row_width[-1] > MAX_ROW_WIDTH: + body += '</TR></TABLE></TD></TR>' + body += '<TR><TD>%s' % ROW_HDR + row_width.append(0) + #submodule_url = linker.url_for(package.submodules[i]) or '#' + #submodule_name = package.submodules[i].canonical_name + body += '<TD ALIGN="LEFT">%s</TD>' % label + row_width [-1] += width + body += '</TR></TABLE></TD></TR></TABLE>' + + # Put together our return value. + depth = max([d for (l,d,w) in submodule_labels])+1 + pkg_color = _nested_uml_package_color(package, context, depth) + label = ('<TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0"><TR>' + '<TD ALIGN="LEFT" HEIGHT="8" WIDTH="16" FIXEDSIZE="true" ' + 'BORDER="1" VALIGN="BOTTOM" BGCOLOR="%s"></TD></TR><TR>' + '<TD COLSPAN="5" VALIGN="TOP" ALIGN="LEFT" BORDER="1" ' + 'BGCOLOR="%s" HREF="%s" TOOLTIP="%s">%s</TD></TR></TABLE>' % + (pkg_color, pkg_color, pkg_url, pkg_name, body)) + width = max(max(row_width), len(pkg_name[-1])+3) + return label, depth, width + +def _nested_uml_package_color(package, context, depth): + if package == context: return SELECTED_BG + else: + # Parse the base color. + if re.match(MODULE_BG, 'r#[0-9a-fA-F]{6}$'): + base = int(MODULE_BG[1:], 16) + else: + base = int('d8e8ff', 16) + red = (base & 0xff0000) >> 16 + green = (base & 0x00ff00) >> 8 + blue = (base & 0x0000ff) + # Make it darker with each level of depth. + red = max(0, red-(depth-1)*10) + green = max(0, green-(depth-1)*10) + blue = max(0, blue-(depth-1)*10) + # Convert it back to a color string + return '#%06x' % ((red<<16)+(green<<8)+blue) + +###################################################################### def class_tree_graph(bases, linker, context=None, **options): """ Return a `DotGraph` that graphically displays the package @@ -346,7 +465,6 @@ """ graph = DotGraph('Class Hierarchy for %s' % name_list(bases, context), body='ranksep=0.3\n', - node_defaults={'shape':'box', 'width': 0, 'height': 0}, edge_defaults={'sametail':True, 'dir':'none'}) # Options @@ -381,8 +499,9 @@ return graph +###################################################################### def import_graph(modules, docindex, linker, context=None, **options): - graph = DotGraph('Import Graph') + graph = DotGraph('Import Graph', body='ranksep=.3\n;nodesep=.3\n') # Options if options.get('dir', 'RL') != 'TB': # default: right-to-left. @@ -406,6 +525,7 @@ return graph +###################################################################### def call_graph(api_docs, docindex, linker, context=None, **options): """ :param options: @@ -513,12 +633,18 @@ specialize_valdoc_node(node, val_doc, context, linker.url_for(val_doc)) return nodes +NOOP_URL = '#' +NOOP_URL = 'javascript:;' # this option is more evil. + MODULE_NODE_HTML = ''' - <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="0"> - <TR><TD BORDER="0"></TD><TD BORDER="0"></TD> - <TD HEIGHT="8" BGCOLOR="%s"></TD></TR> - <TR><TD COLSPAN="3" BGCOLOR="%s">%s</TD></TR></TABLE>'''.strip() -MODULE_BG = '#d0e0ff' + <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="0" + CELLPADDING="0" PORT="table" ALIGN="LEFT"> + <TR><TD ALIGN="LEFT" VALIGN="BOTTOM" HEIGHT="8" WIDTH="16" FIXEDSIZE="true" + BGCOLOR="%s" BORDER="1" PORT="tab"></TD></TR> + <TR><TD ALIGN="LEFT" VALIGN="TOP" BGCOLOR="%s" BORDER="1" + PORT="body" HREF="%s" TOOLTIP="%s">%s</TD></TR> + </TABLE>'''.strip() +MODULE_BG = '#d8e8ff' SELECTED_BG = '#ffd0d0' def specialize_valdoc_node(node, val_doc, context, url): @@ -526,20 +652,29 @@ Update the style attributes of `node` to reflext its type and context. """ + # We can only use html-style nodes if dot_version>2. dot_version = get_dot_version() - if val_doc != context: - if url: node['href'] = url - + + # If val_doc or context is a variable, get its value. if isinstance(val_doc, VariableDoc) and val_doc.value is not UNKNOWN: val_doc = val_doc.value - - if isinstance(val_doc, ModuleDoc) and dot_version > [2]: + if isinstance(context, VariableDoc) and context.value is not UNKNOWN: + context = context.value + + # Set the URL. (Do this even if it points to the page we're + # currently on; otherwise, the tooltip is ignored.) + node['href'] = url or NOOP_URL + + if isinstance(val_doc, ModuleDoc) and dot_version >= [2]: node['shape'] = 'plaintext' if val_doc == context: color = SELECTED_BG else: color = MODULE_BG node['tooltip'] = node['label'] - node['html_label'] = MODULE_NODE_HTML % (color, color, node['label']) + node['html_label'] = MODULE_NODE_HTML % (color, color, url, + val_doc.canonical_name, + node['label']) node['width'] = node['height'] = 0 + node.port = 'body' elif isinstance(val_doc, RoutineDoc): node['shape'] = 'box' @@ -550,7 +685,7 @@ node['tooltip'] = node['label'] if val_doc == context: node['fillcolor'] = SELECTED_BG - node['style'] = 'filled,rounded' + node['style'] = 'filled,rounded,bold' else: node['shape'] = 'box' @@ -559,7 +694,7 @@ node['tooltip'] = node['label'] if val_doc == context: node['fillcolor'] = SELECTED_BG - node['style'] = 'filled' + node['style'] = 'filled,bold' def name_list(api_docs, context=None): if context is not None: 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:35:32
|
Revision: 1189 Author: edloper Date: 2006-04-07 16:35:25 -0700 (Fri, 07 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1189&view=rev Log Message: ----------- - Removed .callgraph css style Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html_css.py Modified: trunk/epydoc/src/epydoc/docwriter/html_css.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-07 23:34:41 UTC (rev 1188) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-07 23:35:25 UTC (rev 1189) @@ -134,10 +134,9 @@ a.py-name { text-decoration: none; } /* For Graphs */ -.graph-without-title { border: none; } -.graph-with-title { border: 1px solid black; } -.graph-title { font-weight: bold; } -.callgraph { border: 1px solid black; } +.graph-without-title { border: none; } +.graph-with-title { border: 1px solid black; } +.graph-title { font-weight: bold; } /* Lists */ ul { margin-top: 0; } 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-07 23:32:41
|
Revision: 1187 Author: edloper Date: 2006-04-07 16:32:37 -0700 (Fri, 07 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1187&view=rev Log Message: ----------- - Changed docbuilder to recursively add the contents of packages that are specified by name. Modified Paths: -------------- trunk/epydoc/src/epydoc/docbuilder.py Modified: trunk/epydoc/src/epydoc/docbuilder.py =================================================================== --- trunk/epydoc/src/epydoc/docbuilder.py 2006-04-07 01:07:11 UTC (rev 1186) +++ trunk/epydoc/src/epydoc/docbuilder.py 2006-04-07 23:32:37 UTC (rev 1187) @@ -239,13 +239,9 @@ doc_pairs.append(_get_docs_from_module_file( item, introspect, parse, progress_estimator)) elif is_package_dir(item): - if add_submodules: - doc_pairs += _get_docs_from_package_dir( - item, introspect, parse, progress_estimator) - else: - item = os.path.join(item, '__init__') - doc_pairs.append(_get_docs_from_module_file( - item, introspect, parse, progress_estimator)) + pkgfile = os.path.join(item, '__init__') + doc_pairs.append(_get_docs_from_module_file( + pkgfile, introspect, parse, progress_estimator)) elif os.path.isfile(item): doc_pairs.append(_get_docs_from_pyscript( item, introspect, parse, progress_estimator)) @@ -266,7 +262,15 @@ else: doc_pairs.append(_get_docs_from_pyobject( item, introspect, parse, progress_estimator)) - + + # This will only have an effect if doc_pairs[-1] contains a + # package's docs. The 'not is_module_file(item)' prevents + # us from adding subdirectories if they explicitly specify + # a package's __init__.py file. + if add_submodules and not is_module_file(item): + doc_pairs += _get_docs_from_submodules( + item, doc_pairs[-1], introspect, parse, progress_estimator) + log.end_progress() return doc_pairs @@ -407,20 +411,17 @@ # Return the docs we found. return (introspect_doc, parse_doc) -def _get_docs_from_package_dir(package_dir, introspect, parse, - progress_estimator, parent_docs=(None,None)): - pkg_dir = os.path.normpath(os.path.abspath(package_dir)) - pkg_file = os.path.join(pkg_dir, '__init__') - pkg_docs = _get_docs_from_module_file( - pkg_file, introspect, parse, progress_estimator, parent_docs) - +def _get_docs_from_submodules(item, pkg_docs, introspect, parse, + progress_estimator): # Extract the package's __path__. - if pkg_docs == (None, None): - return [] - elif pkg_docs[0] is not None: + if isinstance(pkg_docs[0], ModuleDoc) and pkg_docs[0].is_package: pkg_path = pkg_docs[0].path + package_dir = os.path.split(pkg_docs[0].filename)[0] + elif isinstance(pkg_docs[1], ModuleDoc) and pkg_docs[1].is_package: + pkg_path = pkg_docs[1].path + package_dir = os.path.split(pkg_docs[1].filename)[0] else: - pkg_path = pkg_docs[1].path + return [] module_filenames = {} subpackage_dirs = set() @@ -438,9 +439,8 @@ subpackage_dirs.add(filename) # Update our estimate of the number of modules in this package. - progress_estimator.revise_estimate(package_dir, - module_filenames.items(), - subpackage_dirs) + progress_estimator.revise_estimate(item, module_filenames.items(), + subpackage_dirs) docs = [pkg_docs] for module_filename in module_filenames.values(): @@ -448,8 +448,11 @@ module_filename, introspect, parse, progress_estimator, pkg_docs) docs.append(d) for subpackage_dir in subpackage_dirs: - docs += _get_docs_from_package_dir( - subpackage_dir, introspect, parse, progress_estimator, pkg_docs) + subpackage_file = os.path.join(subpackage_dir, '__init__') + docs.append(_get_docs_from_module_file( + subpackage_file, introspect, parse, progress_estimator, pkg_docs)) + docs += _get_docs_from_submodules( + subpackage_dir, docs[-1], introspect, parse, progress_estimator) return docs def _report_errors(name, introspect_doc, parse_doc, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-07 01:07:16
|
Revision: 1186 Author: edloper Date: 2006-04-06 18:07:11 -0700 (Thu, 06 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1186&view=rev Log Message: ----------- - Changed a color for consistency Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html_css.py Modified: trunk/epydoc/src/epydoc/docwriter/html_css.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-07 01:06:52 UTC (rev 1185) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-04-07 01:07:11 UTC (rev 1186) @@ -166,7 +166,7 @@ table.summary, table.details, table.index { background: #e8f0f8; color: #000000; } tr.summary, tr.details, tr.index - { background: #70b0f0; color: #000000; } + { background: #70b0ff; color: #000000; } th.group { background: #c0e0f8; color: #000000; } /* Details Sections */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-07 01:07:06
|
Revision: 1185 Author: edloper Date: 2006-04-06 18:06:52 -0700 (Thu, 06 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1185&view=rev Log Message: ----------- - Turned on tooltips for linked names Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html_colorize.py Modified: trunk/epydoc/src/epydoc/docwriter/html_colorize.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-04-07 01:06:01 UTC (rev 1184) +++ trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-04-07 01:06:52 UTC (rev 1185) @@ -670,7 +670,9 @@ #: add line numbers. ADD_LINE_NUMBERS = True - ADD_TOOLTIPS = False + #: A configuration constant, used to determine whether or not to + #: add tooltips for linked names. + ADD_TOOLTIPS = True def __init__(self, module_filename, module_name, docindex=None, api_docs=None, url_func=None): @@ -978,12 +980,12 @@ if url is None: docs = sorted(self.name_to_docs.get(toktext, [])) if docs: + tooltip='\n'.join(['%s'%d.canonical_name + for d in 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. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-04-07 01:06:14
|
Revision: 1184 Author: edloper Date: 2006-04-06 18:06:01 -0700 (Thu, 06 Apr 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1184&view=rev Log Message: ----------- - Added option for selecting parsing/introspection/both - Removed obsolete private-css options Modified Paths: -------------- trunk/epydoc/src/epydoc/gui.py Modified: trunk/epydoc/src/epydoc/gui.py =================================================================== --- trunk/epydoc/src/epydoc/gui.py 2006-04-07 01:05:18 UTC (rev 1183) +++ trunk/epydoc/src/epydoc/gui.py 2006-04-07 01:06:01 UTC (rev 1184) @@ -24,6 +24,9 @@ -V, --version Print the version of epydoc. -h, -?, --help, --usage Display this usage message --debug Do not suppress error messages + +@todo: Use ini-style project files, rather than pickles (using the +same format as the CLI). """ __docformat__ = 'epytext en' @@ -218,7 +221,9 @@ epydoc.docstringparser.DEFAULT_DOCFORMAT = docformat try: - docindex = build_doc_index(options['modules']) + parse = options['introspect_or_parse'] in ('parse', 'both') + introspect = options['introspect_or_parse'] in ('introspect', 'both') + docindex = build_doc_index(options['modules'], parse, introspect) html_writer = HTMLWriter(docindex, **options) log.start_progress('Writing HTML docs to %r' % options['target']) html_writer.write(options['target']) @@ -507,7 +512,7 @@ div = Frame(oframe2, background=BG_COLOR, border=1, relief='sunk') div.pack(ipady=1, fill='x', padx=4, pady=2) - Label(oframe2, text="CSS Stylesheets", font='helvetica -16', + Label(oframe2, text="CSS Stylesheet", font='helvetica -16', **COLOR_CONFIG).pack(anchor='w') oframe6 = Frame(oframe2, background=BG_COLOR) oframe6.pack(fill='x') @@ -611,6 +616,26 @@ b.grid(row=row, column=3, sticky='w') row += 1 + # Separater + Frame(oframe7, background=BG_COLOR).grid(row=row, column=1, pady=3) + row += 1 + + # --parse-only, --introspect-only + l = Label(oframe7, text="Get docs from:", **COLOR_CONFIG) + l.grid(row=row, column=0, sticky='e') + iop_var = self._introspect_or_parse_var = StringVar(self._root) + self._introspect_or_parse_var.set('both') + b = Radiobutton(oframe7, var=iop_var, text='Parsing', + value='parse', **CBUTTON_CONFIG) + b.grid(row=row, column=1, sticky='w') + b = Radiobutton(oframe7, var=iop_var, text='Introspecting', + value='introspect', **CBUTTON_CONFIG) + b.grid(row=row, column=2, sticky='w') + b = Radiobutton(oframe7, var=iop_var, text='Both', + value='both', **CBUTTON_CONFIG) + b.grid(row=row, column=3, sticky='w') + row += 1 + #==================== oframe5 ==================== # --help-file FILE row = 0 @@ -644,36 +669,38 @@ # -c CSS, --css CSS # --private-css CSS row = 0 - l = Label(oframe6, text="Public", **COLOR_CONFIG) - l.grid(row=row, column=0, sticky='e') - l = Label(oframe6, text="Private", **COLOR_CONFIG) - l.grid(row=row, column=1, sticky='w') + #l = Label(oframe6, text="Public", **COLOR_CONFIG) + #l.grid(row=row, column=0, sticky='e') + #l = Label(oframe6, text="Private", **COLOR_CONFIG) + #l.grid(row=row, column=1, sticky='w') row += 1 css_var = self._css_var = StringVar(self._root) css_var.set('default') - private_css_var = self._private_css_var = StringVar(self._root) - private_css_var.set('default') + #private_css_var = self._private_css_var = StringVar(self._root) + #private_css_var.set('default') for (name, (sheet, descr)) in items: b = Radiobutton(oframe6, var=css_var, value=name, **CBUTTON_CONFIG) b.grid(row=row, column=0, sticky='e') - b = Radiobutton(oframe6, var=private_css_var, value=name, - text=name, **CBUTTON_CONFIG) - b.grid(row=row, column=1, sticky='w') + #b = Radiobutton(oframe6, var=private_css_var, value=name, + # text=name, **CBUTTON_CONFIG) + #b.grid(row=row, column=1, sticky='w') l = Label(oframe6, text=descr, **COLOR_CONFIG) - l.grid(row=row, column=2, sticky='w') + l.grid(row=row, column=1, sticky='w') row += 1 - b = Radiobutton(oframe6, var=css_var, value='-other-', + b = Radiobutton(oframe6, var=css_var, value='-other-', **CBUTTON_CONFIG) b.grid(row=row, column=0, sticky='e') - b = Radiobutton(oframe6, text='Select File', var=private_css_var, - value='-other-', **CBUTTON_CONFIG) - b.grid(row=row, column=1, sticky='w') + #b = Radiobutton(oframe6, text='Select File', var=private_css_var, + # value='-other-', **CBUTTON_CONFIG) + #b.grid(row=row, column=1, sticky='w') + #l = Label(oframe6, text='Select File', **COLOR_CONFIG) + #l.grid(row=row, column=1, sticky='w') self._css_entry = Entry(oframe6, **ENTRY_CONFIG) - self._css_entry.grid(row=row, column=2, sticky='ew') + self._css_entry.grid(row=row, column=1, sticky='ew') self._css_browse = Button(oframe6, text="Browse", command=self._browse_css, **BUTTON_CONFIG) - self._css_browse.grid(row=row, column=3, sticky='ew', padx=2) + self._css_browse.grid(row=row, column=2, sticky='ew', padx=2) def _init_bindings(self): self._root.bind('<Delete>', self._delete_module) @@ -700,11 +727,11 @@ def _messages_toggle(self, *e): if self._messages_visible: self._msgsframe.forget() - self._message_button['image'] = self._downImage + self._message_button['image'] = self._rightImage self._messages_visible = 0 else: self._msgsframe.pack(fill='both', side='bottom', expand=1) - self._message_button['image'] = self._upImage + self._message_button['image'] = self._leftImage self._messages_visible = 1 def _configure(self, event): @@ -818,6 +845,7 @@ options['prj_url'] = self._url_entry.get() or None options['docformat'] = self._docformat_var.get() options['inheritance'] = self._inheritance_var.get() + options['introspect_or_parse'] = self._introspect_or_parse_var.get() options['target'] = self._out_entry.get() or 'html' options['frames'] = self._frames_var.get() options['private'] = self._private_var.get() @@ -830,10 +858,10 @@ options['css'] = self._css_entry.get() or 'default' else: options['css'] = self._css_var.get() or 'default' - if self._private_css_var.get() == '-other-': - options['private_css'] = self._css_entry.get() or 'default' - else: - options['private_css'] = self._private_css_var.get() or 'default' + #if self._private_css_var.get() == '-other-': + # options['private_css'] = self._css_entry.get() or 'default' + #else: + # options['private_css'] = self._private_css_var.get() or 'default' return options def _go(self, *e): @@ -884,10 +912,13 @@ elif level == 'uline': self._messages.insert('end', data, 'uline header') elif level >= log.ERROR: + data= data.rstrip()+'\n\n' self._messages.insert('end', data, 'guierror') elif level >= log.DOCSTRING_WARNING: + data= data.rstrip()+'\n\n' self._messages.insert('end', data, 'warning') elif log >= log.INFO: + data= data.rstrip()+'\n\n' self._messages.insert('end', data, 'message') # if data == '\n': # if self._last_tag != 'header2': @@ -945,6 +976,7 @@ self._url_entry.delete(0, 'end') self._docformat_var.set('epytext') self._inheritance_var.set('grouped') + self._introspect_or_parse_var.set('both') self._out_entry.delete(0, 'end') self._module_entry.delete(0, 'end') self._css_entry.delete(0, 'end') @@ -953,7 +985,7 @@ self._private_var.set(1) self._imports_var.set(0) self._css_var.set('default') - self._private_css_var.set('default') + #self._private_css_var.set('default') self._help_var.set('default') self._filename = None self._init_dir = None @@ -990,6 +1022,8 @@ self._docformat_var.set(opts.get('docformat', 'epytext')) self._inheritance_var.set(opts.get('inheritance', 'grouped')) + self._introspect_or_parse_var.set( + opts.get('introspect_or_parse', 'both')) self._help_entry.delete(0, 'end') if opts.get('help') is None: @@ -1012,11 +1046,11 @@ self._css_var.set('-other-') self._css_entry.insert(0, opts.get('css', 'default')) - if opts.get('private_css', 'default') in STYLESHEETS.keys(): - self._private_css_var.set(opts.get('private_css', 'default')) - else: - self._private_css_var.set('-other-') - self._css_entry.insert(0, opts.get('private_css', 'default')) + #if opts.get('private_css', 'default') in STYLESHEETS.keys(): + # self._private_css_var.set(opts.get('private_css', 'default')) + #else: + # self._private_css_var.set('-other-') + # self._css_entry.insert(0, opts.get('private_css', 'default')) except Exception, e: log.error('Error opening %s: %s' % (prjfile, e)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |