epydoc-commits Mailing List for Python API documentation generation tool (Page 19)
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-09-06 23:45:31
|
Revision: 1360 http://svn.sourceforge.net/epydoc/?rev=1360&view=rev Author: edloper Date: 2006-09-06 16:45:27 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - Turn on epydoc.DEBUG when running tests Modified Paths: -------------- trunk/epydoc/src/epydoc/test/__init__.py Modified: trunk/epydoc/src/epydoc/test/__init__.py =================================================================== --- trunk/epydoc/src/epydoc/test/__init__.py 2006-09-06 23:44:59 UTC (rev 1359) +++ trunk/epydoc/src/epydoc/test/__init__.py 2006-09-06 23:45:27 UTC (rev 1360) @@ -14,6 +14,9 @@ import unittest, doctest, epydoc, os, os.path def main(): + # Turn on debugging. + epydoc.DEBUG = True + # Options for doctest: options = doctest.ELLIPSIS doctest.set_unittest_reportflags(doctest.REPORT_UDIFF) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-06 23:45:03
|
Revision: 1359 http://svn.sourceforge.net/epydoc/?rev=1359&view=rev Author: edloper Date: 2006-09-06 16:44:59 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - Changed APIDoc.pp() to display full names for variables. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-06 20:06:18 UTC (rev 1358) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-06 23:44:59 UTC (rev 1359) @@ -1809,8 +1809,15 @@ 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 not in (UNKNOWN, None): - name = '%s for %s' % (api_doc.__class__.__name__, api_doc.name) + elif getattr(api_doc, 'name', None) not in (UNKNOWN, None): + if (getattr(api_doc, 'container', None) not in (UNKNOWN, None) and + getattr(api_doc.container, 'canonical_name', None) + not in (UNKNOWN, None)): + name ='%s for %s' % (api_doc.__class__.__name__, + api_doc.container.canonical_name+ + api_doc.name) + else: + 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-09-06 20:06:27
|
Revision: 1358 http://svn.sourceforge.net/epydoc/?rev=1358&view=rev Author: edloper Date: 2006-09-06 13:06:18 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - If the summary is empty, but the return field is not, then generate a summary from 'Return'+return_descr - Fixed bug in details display w/ empty descr - split_fields() now returns None for the body if the body is empty (i.e., the dosctring contained only fields) Modified Paths: -------------- trunk/epydoc/src/epydoc/docstringparser.py trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/html_css.py trunk/epydoc/src/epydoc/markup/__init__.py trunk/epydoc/src/epydoc/markup/epytext.py trunk/epydoc/src/epydoc/markup/javadoc.py trunk/epydoc/src/epydoc/markup/restructuredtext.py Modified: trunk/epydoc/src/epydoc/docstringparser.py =================================================================== --- trunk/epydoc/src/epydoc/docstringparser.py 2006-09-06 19:29:30 UTC (rev 1357) +++ trunk/epydoc/src/epydoc/docstringparser.py 2006-09-06 20:06:18 UTC (rev 1358) @@ -205,13 +205,16 @@ field.arg(), field.body()) except ValueError, e: field_warnings.append(str(e)) - # [XX] If descr is empty but we have a return field, - # generate a descr from it.. - # Extract a summary if api_doc.summary is None and api_doc.descr is not None: api_doc.summary = api_doc.descr.summary() + # If the summary is empty, but the return field is not, then use + # the return field to generate a summary description. + if (isinstance(api_doc, RoutineDoc) and api_doc.summary is None and + api_doc.return_descr is not None): + api_doc.summary = RETURN_PDS + api_doc.return_descr.summary() + # [XX] Make sure we don't have types/param descrs for unknown # vars/params? @@ -321,6 +324,11 @@ # End the message block. log.end_block() +RETURN_PDS = markup.parse('Returns', markup='epytext') +"""A ParsedDocstring containing the text 'Returns'. This is used to +construct summary descriptions for routines that have empty C{descr}, +but non-empty C{return_descr}.""" + ###################################################################### #{ Field Processing Error Messages ###################################################################### Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-06 19:29:30 UTC (rev 1357) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-06 20:06:18 UTC (rev 1358) @@ -1974,6 +1974,8 @@ def write_details_entry(self, out, var_doc): descr = self.descr(var_doc, indent=2) + if descr: descr = '<br />'+descr + else: descr = '' if var_doc.is_public: div_class = '' else: div_class = ' class="private"' Modified: trunk/epydoc/src/epydoc/docwriter/html_css.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-09-06 19:29:30 UTC (rev 1357) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-09-06 20:06:18 UTC (rev 1358) @@ -84,6 +84,8 @@ h1.epydoc { margin: 0; font-size: +140%; font-weight: bold; } h2.epydoc { font-size: +130%; font-weight: bold; } h3.epydoc { font-size: +115%; font-weight: bold; } +td h3.epydoc { font-size: +115%; font-weight: bold; + margin-bottom: 0; } table.navbar { background: #a0c0ff; color: #000000; border: 2px groove #c0d0d0; } table.navbar table { color: #000000; } Modified: trunk/epydoc/src/epydoc/markup/__init__.py =================================================================== --- trunk/epydoc/src/epydoc/markup/__init__.py 2006-09-06 19:29:30 UTC (rev 1357) +++ trunk/epydoc/src/epydoc/markup/__init__.py 2006-09-06 20:06:18 UTC (rev 1358) @@ -245,7 +245,8 @@ @return: A tuple C{(M{body}, M{fields})}, where C{M{body}} is the main body of this docstring, and C{M{fields}} is a list - of its fields. + of its fields. If the resulting body is empty, return + C{None} for the body. @rtype: C{(L{ParsedDocstring}, list of L{Field})} @param errors: A list where any errors generated during splitting will be stored. If no list is specified, then @@ -336,7 +337,8 @@ ################################################## class ConcatenatedDocstring: def __init__(self, *parsed_docstrings): - self._parsed_docstrings = parsed_docstrings + self._parsed_docstrings = [pds for pds in parsed_docstrings + if pds is not None] def split_fields(self, errors=None): bodies = [] Modified: trunk/epydoc/src/epydoc/markup/epytext.py =================================================================== --- trunk/epydoc/src/epydoc/markup/epytext.py 2006-09-06 19:29:30 UTC (rev 1357) +++ trunk/epydoc/src/epydoc/markup/epytext.py 2006-09-06 20:06:18 UTC (rev 1358) @@ -2020,11 +2020,10 @@ # Save the remaining docstring as the description.. if tree.children and tree.children[0].children: - descr = tree + return ParsedEpytextDocstring(tree), fields else: - descr = None + return None, fields - return ParsedEpytextDocstring(descr), fields def index_terms(self): if self._terms is None: Modified: trunk/epydoc/src/epydoc/markup/javadoc.py =================================================================== --- trunk/epydoc/src/epydoc/markup/javadoc.py 2006-09-06 19:29:30 UTC (rev 1357) +++ trunk/epydoc/src/epydoc/markup/javadoc.py 2006-09-06 20:06:18 UTC (rev 1358) @@ -146,7 +146,10 @@ parsed_body = ParsedJavadocDocstring(body) fields.append(Field(tag, arg, parsed_body)) - return (descr, fields) + if pieces[0].strip(): + return (descr, fields) + else: + return (None, fields) #//////////////////////////////////////////////////////////// # HTML Output. Modified: trunk/epydoc/src/epydoc/markup/restructuredtext.py =================================================================== --- trunk/epydoc/src/epydoc/markup/restructuredtext.py 2006-09-06 19:29:30 UTC (rev 1357) +++ trunk/epydoc/src/epydoc/markup/restructuredtext.py 2006-09-06 20:06:18 UTC (rev 1358) @@ -164,7 +164,10 @@ # Inherit docs visitor = _SplitFieldsTranslator(self._document, errors) self._document.walk(visitor) - return self, visitor.fields + if len(self._document.children) > 0: + return self, visitor.fields + else: + return None, visitor.fields def summary(self): # Inherit docs This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-06 19:29:33
|
Revision: 1357 http://svn.sourceforge.net/epydoc/?rev=1357&view=rev Author: edloper Date: 2006-09-06 12:29:30 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - Changed definition of _FIELD_BULLET, so now there is no longer a required space after the ':'. 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-09-06 19:25:54 UTC (rev 1356) +++ trunk/epydoc/src/epydoc/markup/epytext.py 2006-09-06 19:29:30 UTC (rev 1357) @@ -615,7 +615,7 @@ # a docstring. _ULIST_BULLET = '[-]( +|$)' _OLIST_BULLET = '(\d+[.])+( +|$)' -_FIELD_BULLET = '@\w+( [^{}:\n]+)?:( +|$)' +_FIELD_BULLET = '@\w+( [^{}:\n]+)?:' _BULLET_RE = re.compile(_ULIST_BULLET + '|' + _OLIST_BULLET + '|' + _FIELD_BULLET) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-06 19:26:01
|
Revision: 1356 http://svn.sourceforge.net/epydoc/?rev=1356&view=rev Author: edloper Date: 2006-09-06 12:25:54 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - Fixed SF bug [ 1553539 ] Unknown parameter warnings do not occur -- Generate a warning if @param or @type contains an unknown parameter. Modified Paths: -------------- trunk/epydoc/src/epydoc/docstringparser.py Modified: trunk/epydoc/src/epydoc/docstringparser.py =================================================================== --- trunk/epydoc/src/epydoc/docstringparser.py 2006-09-06 19:12:18 UTC (rev 1355) +++ trunk/epydoc/src/epydoc/docstringparser.py 2006-09-06 19:25:54 UTC (rev 1356) @@ -331,6 +331,7 @@ BAD_CONTEXT = 'Invalid context for %r' REDEFINED = 'Redefinition of %s' UNKNOWN_TAG = 'Unknown field tag %r' +BAD_PARAM = '@%s for unknown parameter %s' ###################################################################### #{ Field Processing @@ -517,6 +518,10 @@ if arg in api_doc.arg_types: raise ValueError(REDEFINED % ('type for '+arg)) api_doc.arg_types[arg] = descr + # Check to make sure that the documented parameter(s) are + # actually part of the function signature. + if arg not in api_doc.all_args(): + raise ValueError(BAD_PARAM % (tag, '"%s"' % arg)) else: raise ValueError(BAD_CONTEXT % arg) @@ -578,6 +583,11 @@ _check(api_doc, tag, arg, context=RoutineDoc, expect_arg=True) idents = re.split('[:;, ] *', arg) api_doc.arg_descrs.append( (idents, descr) ) + # Check to make sure that the documented parameter(s) are + # actually part of the function signature. + bad_params = ['"%s"' % i for i in idents if i not in api_doc.all_args()] + if bad_params: + raise ValueError(BAD_PARAM % (tag, ', '.join(bad_params))) def process_kwarg_field(api_doc, docindex, tag, arg, descr): # [xx] these should -not- be checked if they exist.. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-06 19:12:21
|
Revision: 1355 http://svn.sourceforge.net/epydoc/?rev=1355&view=rev Author: edloper Date: 2006-09-06 12:12:18 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - If --debug is specified, then set epydoc.DEBUG to True. - Commented out what looks like some testing code Modified Paths: -------------- trunk/epydoc/src/epydoc/cli.py Modified: trunk/epydoc/src/epydoc/cli.py =================================================================== --- trunk/epydoc/src/epydoc/cli.py 2006-09-06 19:08:13 UTC (rev 1354) +++ trunk/epydoc/src/epydoc/cli.py 2006-09-06 19:12:18 UTC (rev 1355) @@ -408,10 +408,15 @@ ###################################################################### def main(options, names): - if options.action == 'text': - if options.parse and options.introspect: - options.parse = False + # Set the debug flag, if '--debug' was specified. + if options.debug: + epydoc.DEBUG = True + ## [XX] Did this serve a purpose? Commenting out for now: + #if options.action == 'text': + # if options.parse and options.introspect: + # options.parse = False + # Set up the logger if options.action == 'text': logger = None # no logger for text output. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-06 19:08:25
|
Revision: 1354 http://svn.sourceforge.net/epydoc/?rev=1354&view=rev Author: edloper Date: 2006-09-06 12:08:13 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - Fixed broken crossref links in various docstrings - Updated module docstrings in docparser & docintrospector - Removed unused method HTMLWriter._get_index_terms() - Don't report a failed xref if the identifier in question is a parameter of the current function. - If _HTMLDocstringLinker.translate_identifier_xref can't find a target, then try checking in the contexts of the ancestor classes (in case the docstring was inherited). Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py trunk/epydoc/src/epydoc/checker.py trunk/epydoc/src/epydoc/docbuilder.py trunk/epydoc/src/epydoc/docintrospecter.py trunk/epydoc/src/epydoc/docparser.py trunk/epydoc/src/epydoc/docwriter/dotgraph.py trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/latex.py trunk/epydoc/src/epydoc/gui.py trunk/epydoc/src/epydoc/log.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -813,8 +813,8 @@ dictionary mapping from identifiers to C{VariableDoc}s. This dictionary contains all names defined by the namespace, including imported variables, aliased variables, and variables - inherited from base classes (once L{DocInheriter - <epydoc.docinheriter.DocInheriter>} has added them). + inherited from base classes (once L{inherit_docs() + <epydoc.docbuilder.inherit_docs>} has added them). @type: C{dict} from C{string} to L{VariableDoc}""" sorted_variables = UNKNOWN """@ivar: A list of all variables defined by this @@ -1048,8 +1048,8 @@ @require: The L{sorted_variables}, L{variable_groups}, and L{submodule_groups} attributes must be initialized before - this method can be used. See L{init_sorted_variables()} - and L{init_groups()}. + this method can be used. See L{init_sorted_variables()}, + L{init_variable_groups()}, and L{init_submodule_groups()}. @param value_type: A string specifying the value type for which variables should be returned. Valid values are: @@ -1225,7 +1225,7 @@ @require: The L{sorted_variables} and L{variable_groups} attributes must be initialized before this method can be used. See L{init_sorted_variables()} and - L{init_groups()}. + L{init_variable_groups()}. @param value_type: A string specifying the value type for which variables should be returned. Valid values are: @@ -1365,7 +1365,7 @@ """@ivar: A list of names of decorators that were applied to this routine, in the order that they are listed in the source code. (I.e., in the reverse of the order that they were applied in.) - @type: C{list} of L{string}""" + @type: C{list} of C{string}""" #} end of "decorators" group #{ Information Extracted from Docstrings @@ -1543,7 +1543,7 @@ """A mapping from C{profile} function ids to corresponding C{APIDoc} objects. A function id is a tuple of the form C{(filename, lineno, funcname)}. This is used to update - the L{callers} and L{calleeds} variables.""" + the L{callers} and L{callees} variables.""" self._container_cache = {} """A cache for the L{container()} method, to increase speed.""" Modified: trunk/epydoc/src/epydoc/checker.py =================================================================== --- trunk/epydoc/src/epydoc/checker.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/checker.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -53,7 +53,7 @@ - Public/private specifiers indicate whether public or private objects should be checked: L{PRIVATE}. - Check specifiers indicate what checks should be run on the - objects: L{TYPE}; L{DESCR}; L{DESCR_LAZY}; L{AUTHOR}; + objects: L{TYPE}; L{DESCR}; L{AUTHOR}; and L{VERSION}. The L{check} method is used to perform a check on the @@ -66,7 +66,7 @@ values together: >>> checker.check(DocChecker.MODULE | DocChecker.CLASS | - ... DocChecker.FUNC | DocChecker.DESCR_LAZY) + ... DocChecker.FUNC ) @group Types: MODULE, CLASS, FUNC, VAR, IVAR, CVAR, PARAM, RETURN, ALL_T @@ -98,7 +98,7 @@ @cvar ALL_T: Type specifier that indicates that the documentation of all objects should be checked. - @group Checks: TYPE, AUTHOR, VERSION, DESCR_LAZY, DESCR, ALL_C + @group Checks: TYPE, AUTHOR, VERSION, DESCR, ALL_C @type TYPE: C{int} @cvar TYPE: Check specifier that indicates that every variable and parameter should have a C{@type} field. @@ -235,7 +235,7 @@ L{_check_class}, and L{_check_func}. @param doc: The documentation that should be checked. - @type doc: L{ObjDoc} + @type doc: L{APIDoc} @rtype: C{None} """ if ((self._checks & DocChecker.DESCR) and @@ -287,7 +287,7 @@ whose name is C{name}. @param doc: The documentation for the variable to check. - @type doc: L{Doc} + @type doc: L{APIDoc} @param check_type: Whether or not the variable's type should be checked. This is used to allow varargs and keyword parameters to have no type specified. Modified: trunk/epydoc/src/epydoc/docbuilder.py =================================================================== --- trunk/epydoc/src/epydoc/docbuilder.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/docbuilder.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -36,7 +36,7 @@ The main interface to C{epydoc.docbuilder} consists of two functions: - - L{build_docs()} -- Builds documentation for a single item, and + - L{build_doc()} -- Builds documentation for a single item, and returns it as an L{APIDoc} object. - L{build_doc_index()} -- Builds documentation for a collection of items, and returns it as a L{DocIndex} object. @@ -57,7 +57,7 @@ ###################################################################### ## Contents ###################################################################### -## 1. build_docs() -- the main interface. +## 1. build_doc() & build_doc_index() -- the main interface. ## 2. merge_docs() -- helper, used to merge parse & introspect info ## 3. link_imports() -- helper, used to connect imported vars w/ values ## 4. assign_canonical_names() -- helper, used to set canonical names @@ -77,7 +77,7 @@ from epydoc.compat import * # Backwards compatibility ###################################################################### -## 1. build_docs() +## 1. build_doc() ###################################################################### def build_doc(item, introspect=True, parse=True, add_submodules=True): Modified: trunk/epydoc/src/epydoc/docintrospecter.py =================================================================== --- trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/docintrospecter.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -10,12 +10,14 @@ Extract API documentation about python objects by directly introspecting their values. -L{DocIntrospecter} is a processing class that examines Python objects via -introspection, and uses the information it finds to create L{APIDoc} -objects containing the API documentation for those objects. +The function L{introspect_docs()}, which provides the main interface +of this module, examines a Python objects via introspection, and uses +the information it finds to create an L{APIDoc} objects containing the +API documentation for that objects. -C{DocIntrospecter} can be subclassed to extend the set of object types -that it supports. +The L{register_introspecter()} method can be used to extend the +functionality of C{docintrospector}, by providing methods that handle +special value types. """ __docformat__ = 'epytext en' @@ -61,41 +63,6 @@ ## Introspection ###################################################################### -# [xx] old: -""" -An API documentation extractor based on introspecting python values. -C{DocIntrospecter} examines Python objects via introspection, and uses -the information it finds to create L{APIDoc} objects containing -the API documentation for those objects. The main interface to -the C{DocIntrospecter} class is the L{introspect} method, which takes a -Python value, and returns an L{APIDoc} that describes it. - -Currently, C{DocIntrospecter} can extract documentation information -from the following object types: - - - modules - - classes - - functions - - methods - - class methods - - static methods - - builtin routines - - properties - -Subclassing -=========== -C{DocIntrospecter} can be subclassed, to extend the set of object -types that it supports. C{DocIntrospecter} can be extended in -several different ways: - - - A subclass can override one of the existing introspection methods - to modify the behavior for a currently supported object type. - - - A subclass can add support for a new type by adding a new - introspection method; and extending L{introspecter_method()} to - return that method for values of the new type. -""" - def introspect_docs(value=None, name=None, filename=None, context=None, is_script=False): """ Modified: trunk/epydoc/src/epydoc/docparser.py =================================================================== --- trunk/epydoc/src/epydoc/docparser.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/docparser.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -10,13 +10,42 @@ Extract API documentation about python objects by parsing their source code. -L{DocParser} is a processing class that reads the Python source code -for one or more modules, and uses it to create L{APIDoc} objects -containing the API documentation for the variables and values defined -in those modules. +The function L{parse_docs()}, which provides the main interface +of this module, reads and parses the Python source code for a +module, and uses it to create an L{APIDoc} object containing +the API documentation for the variables and values defined in +that modules. -C{DocParser} can be subclassed to extend the set of source code -constructions that it supports. +Currently, C{parse_docs()} extracts documentation from the following +source code constructions: + + - module docstring + - import statements + - class definition blocks + - function definition blocks + - assignment statements + - simple assignment statements + - assignment statements with multiple C{'='}s + - assignment statements with unpacked left-hand sides + - assignment statements that wrap a function in classmethod + or staticmethod. + - assignment to special variables __path__, __all__, and + __docformat__. + - delete statements + +C{parse_docs()} does not yet support the following source code +constructions: + + - assignment statements that create properties + +By default, C{parse_docs()} will expore the contents of top-level +C{try} and C{if} blocks. If desired, C{parse_docs()} can also +be configured to explore the contents of C{while} and C{for} blocks. +(See the configuration constants, below.) + +@todo: Make it possible to extend the functionality of C{parse_docs()}, + by replacing process_line with a dispatch table that can be + customized (similarly to C{docintrospector.register_introspector()}). """ __docformat__ = 'epytext en' @@ -59,52 +88,6 @@ C{ValueDoc} objects. @type: C{dict}""" -# [xx] outdated: -""" -An API documentation extractor based on source code parsing. -C{DocParser} reads and parses the Python source code for one or -more modules, and uses it to create L{APIDoc} objects containing -the API documentation for the variables and values defined in -those modules. The main interface method is L{parse()}, which -returns the documentation for an object with a given dotted name, -or a module with a given filename. - -Currently, C{DocParser} extracts documentation from the following -source code constructions: - - - module docstring - - import statements - - class definition blocks - - function definition blocks - - assignment statements - - simple assignment statements - - assignment statements with multiple C{'='}s - - assignment statements with unpacked left-hand sides - - assignment statements that wrap a function in classmethod - or staticmethod. - - assignment to special variables __path__, __all__, and - __docformat__. - - delete statements - -C{DocParser} does not yet support the following source code -constructions: - - - assignment statements that create properties - -By default, C{DocParser} will expore the contents of top-level -C{try} and C{if} blocks. If desired, C{DocParser} can also -be told to explore the contents of C{while} and C{for} blocks. - -Subclassing -=========== -C{DocParser} can be subclassed, to extend the set of source code -constructions that it supports. C{DocParser} can be extended in -several different ways: - - - [XX] fill this in! - -""" - #//////////////////////////////////////////////////////////// # Configuration Constants #//////////////////////////////////////////////////////////// @@ -211,7 +194,7 @@ C{ModuleDoc} describing its contents. @param name: The fully-qualified python dotted name of any value (including packages, modules, classes, and - functions). C{DocParser} will automatically figure out + functions). C{parse_docs()} will automatically figure out which module(s) it needs to parse in order to find the documentation for the specified object. @param context: The API documentation for the package that Modified: trunk/epydoc/src/epydoc/docwriter/dotgraph.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -45,7 +45,7 @@ class DotGraph: """ - A `dot` directed graph. The contents of the graph are + A ``dot`` directed graph. The contents of the graph are constructed from the following instance variables: - `nodes`: A list of `DotGraphNode`\\s, encoding the nodes @@ -62,7 +62,7 @@ The `link()` method can be used to resolve crossreference links within the graph. In particular, if the 'href' attribute of any - node or edge is assigned a value of the form `<name>`, then it + node or edge is assigned a value of the form ``<name>``, then it will be replaced by the URL of the object with that name. This applies to the `body` as well as the `nodes` and `edges`. @@ -190,8 +190,8 @@ def link(self, docstring_linker): """ - Replace any href attributes whose value is <name> with - the url of the object whose name is <name>. + Replace any href attributes whose value is ``<name>`` with + the url of the object whose name is ``<name>``. """ # Link xrefs in nodes self._link_href(self.node_defaults, docstring_linker) @@ -237,7 +237,7 @@ def render(self, language='gif'): """ Use the ``dot`` command to render this graph, using the output - format `language`. Return the result as a string, or `None` + format `language`. Return the result as a string, or ``None`` if the rendering failed. """ return self._run_dot('-T%s' % language) @@ -394,7 +394,7 @@ `class_doc`. :Parameters: - `linker` : `DocstringLinker<markup.DocstringLinker>` + `linker` : `markup.DocstringLinker` Used to look up URLs for classes. `context` : `APIDoc` The context in which this node will be drawn; dotted @@ -526,7 +526,7 @@ 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 + The edges created by `link_attributes()` are handled internally by `DotGraphUmlClassNode`; they should *not* be added directly to the `DotGraph`. @@ -594,7 +594,7 @@ def _add_attribute_edge(self, var, nodes, type_str, **attribs): """ - Helper for `link_attribute()`: try to add an edge for the + Helper for `link_attributes()`: try to add an edge for the given attribute variable `var`. Return ``True`` if successful. """ @@ -1156,12 +1156,12 @@ def call_graph(api_docs, docindex, linker, context=None, **options): """ :param options: - - `dir`: rankdir for the graph. (default=LR) - - `add_callers`: also include callers for any of the - routines in `api_docs`. (default=False) - - `add_callees`: also include callees for any of the - routines in `api_docs`. (default=False) - :todo: Add an `exclude` option? + - ``dir``: rankdir for the graph. (default=LR) + - ``add_callers``: also include callers for any of the + routines in ``api_docs``. (default=False) + - ``add_callees``: also include callees for any of the + routines in ``api_docs``. (default=False) + :todo: Add an ``exclude`` option? """ if docindex.callers is None: log.warning("No profiling information for call graph!") Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -2488,7 +2488,7 @@ def contextual_label(self, doc, context): """ - Return the label for L{doc} to be shown in C{context}. + Return the label for C{doc} to be shown in C{context}. """ if doc.canonical_name is None: if doc.parse_repr is not None: @@ -2819,23 +2819,6 @@ index.setdefault(arg, []).append( (doc, descr_list) ) return index - def _get_index_terms(self, parsed_docstring, link, terms, links): - """ - A helper function for L{_extract_term_index}. - - For each index term M{t} with key M{k} in C{parsed_docstring}, - modify C{terms} and C{links} as follows: - - Set C{terms[M{k}] = t} (if C{terms[M{k}]} doesn't exist). - - Append C{link} to C{links[M{k}]}. - """ - if parsed_docstring in (None, UNKNOWN): return - for term in parsed_docstring.index_terms(): - key = self._term_index_to_anchor(term) - if not terms.has_key(key): - terms[key] = term - links[key] = [] - links[key].append(link) - def _term_index_to_anchor(self, term): """ Given the name of an inline index item, construct a URI anchor. @@ -3169,6 +3152,16 @@ # Find the APIDoc for it (if it's available). doc = self.docindex.find(identifier, self.container) + # If we didn't find a target, then try checking in the contexts + # of the ancestor classes. + if doc is None and isinstance(self.container, RoutineDoc): + container = self.docindex.get_vardoc( + self.container.canonical_name) + while (doc is None and container not in (None, UNKNOWN) + and container.overrides not in (None, UNKNOWN)): + container = container.overrides + doc = self.docindex.find(identifier, container) + # Translate it into HTML. if doc is None: self._failed_xref(identifier) @@ -3196,6 +3189,12 @@ def _failed_xref(self, identifier): """Add an identifier to the htmlwriter's failed crossreference list.""" + # Don't count it as a failed xref if it's a parameter of the + # current function. + if (isinstance(self.container, RoutineDoc) and + identifier in self.container.all_args()): + return + failed_xrefs = self.htmlwriter._failed_xrefs context = self.container.canonical_name failed_xrefs.setdefault(identifier,{})[context] = 1 Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -428,7 +428,7 @@ def write_module_tree_item(self, out, doc, depth=0): """ - Helper function for L{_module_tree} and L{_module_list}. + Helper function for L{write_module_tree} and L{write_module_list}. @rtype: C{string} """ Modified: trunk/epydoc/src/epydoc/gui.py =================================================================== --- trunk/epydoc/src/epydoc/gui.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/gui.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -208,7 +208,7 @@ @param options: The options to use for generating documentation. This includes keyword options that can be given to - L{html.HTMLFormatter}, as well as the option C{target}, which + L{docwriter.html.HTMLWriter}, as well as the option C{target}, which controls where the output is written to. @type options: C{dictionary} """ Modified: trunk/epydoc/src/epydoc/log.py =================================================================== --- trunk/epydoc/src/epydoc/log.py 2006-09-06 15:51:15 UTC (rev 1353) +++ trunk/epydoc/src/epydoc/log.py 2006-09-06 19:08:13 UTC (rev 1354) @@ -70,13 +70,13 @@ def start_block(self, header): """ - Start a new message block. Any calls to L{info}, L{warn}, or - L{error} that occur between a call to C{start_block} and a - corresponding call to C{end_block} will be grouped together, - and displayed with a common header. C{start_block} can be - called multiple times (to form nested blocks), but every call - to C{start_block} I{must} be balanced by a call to - C{end_block}. + Start a new message block. Any calls to L{info()}, + L{warning()}, or L{error()} that occur between a call to + C{start_block} and a corresponding call to C{end_block} will + be grouped together, and displayed with a common header. + C{start_block} can be called multiple times (to form nested + blocks), but every call to C{start_block} I{must} be balanced + by a call to C{end_block}. """ def end_block(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-06 15:51:19
|
Revision: 1353 http://svn.sourceforge.net/epydoc/?rev=1353&view=rev Author: edloper Date: 2006-09-06 08:51:15 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - Added a couple sanity checks 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-09-06 15:50:54 UTC (rev 1352) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-06 15:51:15 UTC (rev 1353) @@ -2277,6 +2277,11 @@ s = plaintext_to_html(val_doc.pyval_repr()) elif val_doc.parse_repr is not UNKNOWN: s = plaintext_to_html(val_doc.parse_repr) + elif isinstance(val_doc, GenericValueDoc): + # This *should* never happen -- GenericValueDoc's should always + # have a pyval_repr or a parse_repr. + log.debug('pprint_value() got GenericValueDoc w/ UNKNOWN repr') + return '' else: s = self.href(val_doc) return self._linewrap_html(s, self._variable_linelen, @@ -3031,6 +3036,10 @@ label = target.canonical_name elif isinstance(target, DottedName): label = target + elif isinstance(target, GenericValueDoc): + raise ValueError("href() should not be called with " + "GenericValueDoc objects (perhaps you " + "meant to use the containing variable?)") else: raise ValueError("Unable to find a label for %r" % target) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-06 15:50:59
|
Revision: 1352 http://svn.sourceforge.net/epydoc/?rev=1352&view=rev Author: edloper Date: 2006-09-06 08:50:54 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - Fixed bug in rhs_to_valuedoc() that was preventing it from building a ValueDoc for some RHS's. Modified Paths: -------------- trunk/epydoc/src/epydoc/docparser.py Modified: trunk/epydoc/src/epydoc/docparser.py =================================================================== --- trunk/epydoc/src/epydoc/docparser.py 2006-09-06 15:49:48 UTC (rev 1351) +++ trunk/epydoc/src/epydoc/docparser.py 2006-09-06 15:50:54 UTC (rev 1352) @@ -1172,7 +1172,7 @@ try: rhs_name = parse_dotted_name(rhs) rhs_val = lookup_value(rhs_name, parent_docs) - if rhs_val is not None: + if rhs_val is not None and rhs_val is not UNKNOWN: return rhs_val, True except ParseError: pass This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-06 15:49:53
|
Revision: 1351 http://svn.sourceforge.net/epydoc/?rev=1351&view=rev Author: edloper Date: 2006-09-06 08:49:48 -0700 (Wed, 06 Sep 2006) Log Message: ----------- - Replaced VariableDoc._get_canonical_name property with a simple canonical_name attribute. This now gets assigned by docbuilder at the same time as ValueDoc attributes. - When assigning canonical names, don't bother to recurse to GenericValueDoc variables. - Fixed bug in code to merge parsed & introspected GenericValueDocs, which was sometimes causing value repr's to not propagate correctly. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py trunk/epydoc/src/epydoc/docbuilder.py trunk/epydoc/src/epydoc/docstringparser.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-04 04:09:52 UTC (rev 1350) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-06 15:49:48 UTC (rev 1351) @@ -568,6 +568,12 @@ variable. @type: L{ValueDoc}""" + canonical_name = UNKNOWN + """@ivar: A dotted name that serves as a unique identifier for + this C{VariableDoc}. It should be formed by concatenating + the C{VariableDoc}'s C{container} with its C{name}. + @type: L{DottedName}""" + value = UNKNOWN """@ivar: The API documentation for this variable's value. @type: L{ValueDoc}""" @@ -635,24 +641,6 @@ else: return '<%s>' % self.__class__.__name__ - def _get_canonical_name(self): - # Check cache. - canonical_name = getattr(self, '_canonical_name', None) - if canonical_name is not None: return canonical_name - # Otherwise, compute it. - if (self.container is UNKNOWN or - self.container.canonical_name is UNKNOWN): - return UNKNOWN - else: - self._canonical_name = self.container.canonical_name + self.name - return self._canonical_name - canonical_name = property(_get_canonical_name, - doc="""A read-only property that can be used to get the variable's - canonical name. This is formed by taking the varaible's - container's cannonical name, and adding the variable's name - to it. (The value is cached upon the first successful - look-up.)""") - def _get_defining_module(self): if self.container is UNKNOWN: return UNKNOWN Modified: trunk/epydoc/src/epydoc/docbuilder.py =================================================================== --- trunk/epydoc/src/epydoc/docbuilder.py 2006-09-04 04:09:52 UTC (rev 1350) +++ trunk/epydoc/src/epydoc/docbuilder.py 2006-09-06 15:49:48 UTC (rev 1351) @@ -678,9 +678,12 @@ # them. E.g., we don't want to merge 2+2 with 4. So just copy # the inspect_doc's pyval to the parse_doc, and return the parse_doc. if type(introspect_doc) == type(parse_doc) == GenericValueDoc: - parse_doc.pyval = introspect_doc.pyval + if introspect_doc.pyval is not UNKNOWN: + parse_doc.pyval = introspect_doc.pyval + if introspect_doc.parse_repr is not UNKNOWN: + parse_doc.parse_repr = introspect_doc.parse_repr parse_doc.docs_extracted_by = 'both' - return parse_doc + return parse_doc.merge_and_overwrite(introspect_doc) # Perform several sanity checks here -- if we accidentally # merge values that shouldn't get merged, then bad things can @@ -1008,9 +1011,16 @@ # Recurse to any contained values. if isinstance(val_doc, NamespaceDoc): for var_doc in val_doc.variables.values(): - if var_doc.value is UNKNOWN: continue + # Set the variable's canonical name. varname = DottedName(name, var_doc.name) - + var_doc.canonical_name = varname + + # If the value is unknown, or is a generic value doc, then + # the valuedoc doesn't get assigned a name; move on. + if (var_doc.value is UNKNOWN + or isinstance(var_doc.value, GenericValueDoc)): + continue + # This check is for cases like curses.wrapper, where an # imported variable shadows its value's "real" location. if _var_shadows_self(var_doc, varname): Modified: trunk/epydoc/src/epydoc/docstringparser.py =================================================================== --- trunk/epydoc/src/epydoc/docstringparser.py 2006-09-04 04:09:52 UTC (rev 1350) +++ trunk/epydoc/src/epydoc/docstringparser.py 2006-09-06 15:49:48 UTC (rev 1351) @@ -205,6 +205,9 @@ field.arg(), field.body()) except ValueError, e: field_warnings.append(str(e)) + # [XX] If descr is empty but we have a return field, + # generate a descr from it.. + # Extract a summary if api_doc.summary is None and api_doc.descr is not None: api_doc.summary = api_doc.descr.summary() @@ -607,8 +610,9 @@ def set_var_descr(api_doc, ident, descr): if ident not in api_doc.variables: - api_doc.variables[ident] = VariableDoc(container=api_doc, - name=ident) + api_doc.variables[ident] = VariableDoc( + container=api_doc, name=ident, + canonical_name=api_doc.canonical_name+ident) var_doc = api_doc.variables[ident] if var_doc.descr not in (None, UNKNOWN): @@ -619,8 +623,10 @@ def set_var_type(api_doc, ident, descr): if ident not in api_doc.variables: - api_doc.variables[ident] = VariableDoc(container=api_doc, - name=ident) + api_doc.variables[ident] = VariableDoc( + container=api_doc, name=ident, + canonical_name=api_doc.canonical_name+ident) + var_doc = api_doc.variables[ident] if var_doc.type_descr not in (None, UNKNOWN): raise ValueError(REDEFINED % ('type for '+ident)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-04 04:09:56
|
Revision: 1350 http://svn.sourceforge.net/epydoc/?rev=1350&view=rev Author: edloper Date: 2006-09-03 21:09:52 -0700 (Sun, 03 Sep 2006) Log Message: ----------- - Added DottedName._ok_identifiers cache. (As a profile-driven optimization) Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-03 05:31:31 UTC (rev 1349) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-04 04:09:52 UTC (rev 1350) @@ -76,6 +76,10 @@ An exception raised by the DottedName constructor when one of its arguments is not a valid dotted name. """ + + _ok_identifiers = set() + """A cache of identifier strings that have been checked against + _IDENTIFIER_RE and found to be acceptable.""" def __init__(self, *pieces): """ @@ -104,13 +108,16 @@ self._identifiers += piece._identifiers elif isinstance(piece, basestring): for subpiece in piece.split('.'): - if not self._IDENTIFIER_RE.match(subpiece): - raise DottedName.InvalidDottedName( - 'Bad identifier %r' % (piece,)) + if piece not in self._ok_identifiers: + if self._IDENTIFIER_RE.match(subpiece): + self._ok_identifiers.add(piece) + else: + raise DottedName.InvalidDottedName( + 'Bad identifier %r' % (piece,)) self._identifiers.append(subpiece) else: - raise DottedName.InvalidDottedName( - 'Bad identifier %r' % (piece,)) + raise TypeError('Bad identifier %r: expected ' + 'DottedName or str' % (piece,)) self._identifiers = tuple(self._identifiers) def __repr__(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-03 05:31:38
|
Revision: 1349 http://svn.sourceforge.net/epydoc/?rev=1349&view=rev Author: edloper Date: 2006-09-02 22:31:31 -0700 (Sat, 02 Sep 2006) Log Message: ----------- made screenshot thumbnails local Modified Paths: -------------- trunk/epydoc/doc/index.html Added Paths: ----------- trunk/epydoc/doc/home.thumbnail.png trunk/epydoc/doc/index.thumbnail.png trunk/epydoc/doc/pysrc.thumbnail.png trunk/epydoc/doc/uml.thumbnail.png Added: trunk/epydoc/doc/home.thumbnail.png =================================================================== (Binary files differ) Property changes on: trunk/epydoc/doc/home.thumbnail.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Modified: trunk/epydoc/doc/index.html =================================================================== --- trunk/epydoc/doc/index.html 2006-09-03 03:41:12 UTC (rev 1348) +++ trunk/epydoc/doc/index.html 2006-09-03 05:31:31 UTC (rev 1349) @@ -110,13 +110,13 @@ <center> <table class="transparent" cellspacing="10"> <tr> - <td class="transparent" valign="top"><a href="api/"><img src="http://sourceforge.net/dbimage.php?id=85862" alt="Generated HTML documentation for epydoc" border="0" /></a><br /> + <td class="transparent" valign="top"><a href="api/"><img src="home.thumbnail.png" alt="Generated HTML documentation for epydoc" border="0" height="75"/></a><br /> <!-- Generated HTML documentation for epydoc --> </td> - <td class="transparent" valign="top"><a href="api/epydoc.apidoc.VariableDoc-class.html"><img src="http://sourceforge.net/dbimage.php?id=85864" alt="Example of a UML graph generated by epydoc" border="0" /></a><br /> + <td class="transparent" valign="top"><a href="api/epydoc.apidoc.VariableDoc-class.html"><img src="uml.thumbnail.png" alt="Example of a UML graph generated by epydoc" border="0" height="75"/></a><br /> <!-- Example of a UML graph generated by epydoc --> </td> - <td class="transparent" valign="top"><a href="api/epydoc.apidoc-pysrc.html"><img src="http://sourceforge.net/dbimage.php?id=85866" alt="Example of syntax highlighted source, w/ links to API docs" border="0" /></a><br /> + <td class="transparent" valign="top"><a href="api/epydoc.apidoc-pysrc.html"><img src="pysrc.thumbnail.png" alt="Example of syntax highlighted source, w/ links to API docs" border="0" height="75"/></a><br /> <!-- Example of syntax highlighted source, w/ links to API docs --> </td> - <td class="transparent" valign="top"><a href="http://epydoc.sourceforge.net/stdlib/identifier-index.html"><img src="http://sourceforge.net/dbimage.php?id=85868" alt="Identifier index page for generated Python 2.4 docs" border="0" /></a><br /> + <td class="transparent" valign="top"><a href="http://epydoc.sourceforge.net/stdlib/identifier-index.html"><img src="index.thumbnail.png" alt="Identifier index page for generated Python 2.4 docs" border="0" height="75"/></a><br /> <!-- Identifier index page for generated Python 2.4 docs --> </td> </tr> </table> Added: trunk/epydoc/doc/index.thumbnail.png =================================================================== (Binary files differ) Property changes on: trunk/epydoc/doc/index.thumbnail.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/epydoc/doc/pysrc.thumbnail.png =================================================================== (Binary files differ) Property changes on: trunk/epydoc/doc/pysrc.thumbnail.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/epydoc/doc/uml.thumbnail.png =================================================================== (Binary files differ) Property changes on: trunk/epydoc/doc/uml.thumbnail.png ___________________________________________________________________ Name: svn:mime-type + application/octet-stream This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-03 03:41:15
|
Revision: 1348 http://svn.sourceforge.net/epydoc/?rev=1348&view=rev Author: edloper Date: 2006-09-02 20:41:12 -0700 (Sat, 02 Sep 2006) Log Message: ----------- - Added --debug to epydoc invocations Modified Paths: -------------- trunk/epydoc/Makefile Modified: trunk/epydoc/Makefile =================================================================== --- trunk/epydoc/Makefile 2006-09-03 03:40:30 UTC (rev 1347) +++ trunk/epydoc/Makefile 2006-09-03 03:41:12 UTC (rev 1348) @@ -125,7 +125,7 @@ $(EPYDOC) -o $(HTML_API) --name epydoc --css white \ --url http://epydoc.sourceforge.net --pstat profile.out \ --inheritance=listed --navlink "epydoc $(VERSION)"\ - --docformat plaintext -v --graph all $(PY_SRC) + --docformat plaintext -v --graph all --debug $(PY_SRC) touch .api-html.up2date api-pdf: .api-pdf.up2date @@ -133,7 +133,7 @@ rm -rf $(LATEX_API) mkdir -p $(LATEX_API) $(EPYDOC) --pdf -o $(LATEX_API) --docformat plaintext \ - --name "Epydoc $(VERSION)" $(PY_SRC) -v + --name "Epydoc $(VERSION)" $(PY_SRC) -v --debug touch .api-pdf.up2date doctest-html: .doctest-html.up2date @@ -152,21 +152,21 @@ .examples.up2date: $(EXAMPLES_SRC) $(PY_SRCFILES) rm -rf $(HTML_EXAMPLES) mkdir -p $(HTML_EXAMPLES) - $(EPYDOC) -o $(HTML_EXAMPLES) --name epydoc \ + $(EPYDOC) -o $(HTML_EXAMPLES) --name epydoc --debug \ --url http://epydoc.sourceforge.net \ --css white --top epytext_example --docformat=plaintext \ --navlink 'epydoc examples' doc/epytext_example.py sre - $(EPYDOC) -o $(HTML_EXAMPLES)/grouped \ + $(EPYDOC) -o $(HTML_EXAMPLES)/grouped --debug \ --inheritance=grouped \ --name epydoc --url http://epydoc.sourceforge.net \ --css white --debug \ --navlink 'epydoc examples' doc/inh_example.py - $(EPYDOC) -o $(HTML_EXAMPLES)/listed \ + $(EPYDOC) -o $(HTML_EXAMPLES)/listed --debug \ --inheritance=listed \ --name epydoc --url http://epydoc.sourceforge.net \ --css white --debug \ --navlink 'epydoc examples' doc/inh_example.py - $(EPYDOC) -o $(HTML_EXAMPLES)/included \ + $(EPYDOC) -o $(HTML_EXAMPLES)/included --debug \ --inheritance=included \ --name epydoc --url http://epydoc.sourceforge.net \ --css white --debug \ @@ -206,7 +206,7 @@ > doc/epydocgui-man.html profile.out: $(PY_SRCFILES) - $(EPYDOC) -o profile.tmp --name epydoc --css white \ + $(EPYDOC) -o profile.tmp --name epydoc --css white --debug \ --url http://epydoc.sourceforge.net --profile-epydoc \ --inheritance=listed --navlink "epydoc $(VERSION)"\ --docformat plaintext -v --graph all $(PY_SRC) @@ -233,7 +233,7 @@ mkdir -p $(HTML_STDLIB) @echo "Building stdlib html docs..." @$(EPYDOC) -o $(HTML_STDLIB) --css white --name $(SLNAME) \ - --url $(SLURL) --debug --graph classtree \ + --url $(SLURL) --debug --graph classtree --debug \ --show-imports $(SLBUILTINS) $(SLFILES) touch .stdlib-html.up2date @@ -242,7 +242,7 @@ .stdlib-pdf.up2date: $(PY_SRCFILES) rm -rf $(LATEX_STDLIB) mkdir -p $(LATEX_STDLIB) - $(EPYDOC) --pdf -o $(LATEX_STDLIB) \ + $(EPYDOC) --pdf -o $(LATEX_STDLIB) --debug \ --no-private --name $(SLNAME) --docformat plaintext \ --debug --builtins $(SLFILES) ##////////////////////////////////////////////////////////////////////// @@ -263,7 +263,7 @@ .docutils-html.up2date: $(PY_SRCFILES) rm -rf $(HTML)/docutils mkdir -p $(HTML)/docutils - $(EPYDOC) -o $(HTML)/docutils -n 'Docutils' --html \ + $(EPYDOC) -o $(HTML)/docutils -n 'Docutils' --html --debug \ --docformat plaintext --ignore-param-mismatch \ /usr/lib/python2.3/site-packages/docutils touch .docutils-html.up2date @@ -272,7 +272,7 @@ .docutils-pdf.up2date: $(PY_SRCFILES) rm -rf $(LATEX)/docutils mkdir -p $(LATEX)/docutils - $(EPYDOC) -o $(LATEX)/docutils -n 'Docutils' --pdf \ + $(EPYDOC) -o $(LATEX)/docutils -n 'Docutils' --pdf --debug \ --docformat plaintext --ignore-param-mismatch \ /usr/lib/python2.3/site-packages/docutils touch .docutils-pdf.up2date This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-03 03:40:34
|
Revision: 1347 http://svn.sourceforge.net/epydoc/?rev=1347&view=rev Author: edloper Date: 2006-09-02 20:40:30 -0700 (Sat, 02 Sep 2006) Log Message: ----------- - Turned off debug flag (optimizing epydoc for speed) Modified Paths: -------------- trunk/epydoc/src/epydoc/__init__.py Modified: trunk/epydoc/src/epydoc/__init__.py =================================================================== --- trunk/epydoc/src/epydoc/__init__.py 2006-09-03 03:39:58 UTC (rev 1346) +++ trunk/epydoc/src/epydoc/__init__.py 2006-09-03 03:40:30 UTC (rev 1347) @@ -213,7 +213,7 @@ """The license governing the use and distribution of epydoc""" # [xx] this should probably be a private variable: -DEBUG = True +DEBUG = False """True if debugging is turned on.""" # Changes needed for docs: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-03 03:40:02
|
Revision: 1346 http://svn.sourceforge.net/epydoc/?rev=1346&view=rev Author: edloper Date: 2006-09-02 20:39:58 -0700 (Sat, 02 Sep 2006) Log Message: ----------- - Various optimizations to make epydoc run faster: - DottedName slicing is now faster - Cache VariableDoc.canonical_name (perhaps I should just assign them all when doing canonical name assignment, and then get rid of the property version?) - Cache pyval_repr - Made submodule check in DocIndex._get_from faster. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2006-09-02 01:46:11 UTC (rev 1345) +++ trunk/epydoc/src/epydoc/apidoc.py 2006-09-03 03:39:58 UTC (rev 1346) @@ -87,7 +87,15 @@ contains a string, then it is divided into substrings by splitting on periods, and each substring is checked to see if it is a valid identifier. + + As an optimization, C{pieces} may also contain a single tuple + of values. In that case, that tuple will be used as the + C{DottedName}'s identifiers; it will I{not} be checked to + see if it's valid. """ + if len(pieces) == 1 and isinstance(pieces[0], tuple): + self._identifiers = pieces[0] # Optimization + return if len(pieces) == 0: raise DottedName.InvalidDottedName('Empty DottedName') self._identifiers = [] @@ -148,7 +156,7 @@ """ if isinstance(i, types.SliceType): pieces = self._identifiers[i.start:i.stop] - if pieces: return DottedName(*pieces) + if pieces: return DottedName(pieces) else: return [] else: return self._identifiers[i] @@ -613,28 +621,30 @@ self.name.endswith('_')) def __repr__(self): - if (self.container is not UNKNOWN and - self.container.canonical_name is not UNKNOWN): - return '<%s %s.%s>' % (self.__class__.__name__, - self.container.canonical_name, self.name) + if self.canonical_name is not UNKNOWN: + return '<%s %s>' % (self.__class__.__name__, self.canonical_name) if self.name is not UNKNOWN: return '<%s %s>' % (self.__class__.__name__, self.name) else: return '<%s>' % self.__class__.__name__ def _get_canonical_name(self): - if self.container is UNKNOWN: - raise ValueError, `self` + # Check cache. + canonical_name = getattr(self, '_canonical_name', None) + if canonical_name is not None: return canonical_name + # Otherwise, compute it. if (self.container is UNKNOWN or self.container.canonical_name is UNKNOWN): return UNKNOWN else: - return self.container.canonical_name + self.name - canonical_name = property(_get_canonical_name, doc=""" - A read-only property that can be used to get the variable's - canonical name. This is formed by taking the varaible's - container's cannonical name, and adding the variable's name - to it.""") + self._canonical_name = self.container.canonical_name + self.name + return self._canonical_name + canonical_name = property(_get_canonical_name, + doc="""A read-only property that can be used to get the variable's + canonical name. This is formed by taking the varaible's + container's cannonical name, and adding the variable's name + to it. (The value is cached upon the first successful + look-up.)""") def _get_defining_module(self): if self.container is UNKNOWN: @@ -763,6 +773,11 @@ return self.__pickle_state def pyval_repr(self): + if not hasattr(self, '_pyval_repr'): + self._pyval_repr = self._get_pyval_repr() + return self._pyval_repr + + def _get_pyval_repr(self): """ Return a string representation of this value based on its pyval; or UNKNOWN if we don't succeed. This should probably eventually @@ -1036,9 +1051,10 @@ whose values have the specified type. If C{group} is given, then only return variables that belong to the specified group. - @require: The L{sorted_variables} and L{groups} attributes - must be initialized before this method can be used. See - L{init_sorted_variables()} and L{init_groups()}. + @require: The L{sorted_variables}, L{variable_groups}, and + L{submodule_groups} attributes must be initialized before + this method can be used. See L{init_sorted_variables()} + and L{init_groups()}. @param value_type: A string specifying the value type for which variables should be returned. Valid values are: @@ -1211,9 +1227,10 @@ If C{inherited} is True, then only return inherited variables; if C{inherited} is False, then only return local variables. - @require: The L{sorted_variables} and L{groups} attributes - must be initialized before this method can be used. See - L{init_sorted_variables()} and L{init_groups()}. + @require: The L{sorted_variables} and L{variable_groups} + attributes must be initialized before this method can be + used. See L{init_sorted_variables()} and + L{init_groups()}. @param value_type: A string specifying the value type for which variables should be returned. Valid values are: @@ -1612,8 +1629,7 @@ if (isinstance(val_doc, ModuleDoc) and val_doc.submodules is not UNKNOWN): for submodule in val_doc.submodules: - if (submodule.canonical_name == - DottedName(val_doc.canonical_name, identifier)): + if submodule.canonical_name[-1] == identifier: var_doc = None val_doc = submodule if val_doc is UNKNOWN: val_doc = None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-02 01:46:14
|
Revision: 1345 http://svn.sourceforge.net/epydoc/?rev=1345&view=rev Author: edloper Date: 2006-09-01 18:46:11 -0700 (Fri, 01 Sep 2006) Log Message: ----------- - Fixed javascript bug in kill_doclink() - Various optimizations to make the size of the generated HTML files a little smaller. Including: - Changed <span>..</span> to <tt>..</tt> in colorized html source, to make the files slightly smaller. - Modified javascript doclink() function so that the list of choices for a given variable only needs to be included once. This should cut down on the size of generated files where there are a large number of possible targets for each variable 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-09-02 01:40:35 UTC (rev 1344) +++ trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2006-09-02 01:46:11 UTC (rev 1345) @@ -341,13 +341,13 @@ var indent = elt.getAttribute("indent"); var pad = elt.getAttribute("pad"); - var s = "<span class=\'py-lineno\'>"; + var s = "<tt class=\'py-lineno\'>"; for (var i=0; i<pad.length; i++) { s += " " } - s += "</span>"; - s += " <span class=\'py-line\'>"; + s += "</tt>"; + s += " <tt class=\'py-line\'>"; for (var i=0; i<indent.length; i++) { s += " " } s += "<a href=\'#\' onclick=\'expand(\\"" + id; - s += "\\");return false\'>...</a></span><br />"; + s += "\\");return false\'>...</a></tt><br />"; elt.innerHTML = s; } } @@ -358,7 +358,9 @@ collapse(id); else expand(id); + return false; } + function highlight(id) { var elt = document.getElementById(id+"-def"); if (elt) elt.className = "py-highlight-hdr"; @@ -410,17 +412,18 @@ } 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(id); + parent.removeChild(parent.childNodes.item(0)); +} +function auto_kill_doclink(ev) { + if (!ev) var ev = window.event; + if (!this.contains(ev.toElement)) { var parent = document.getElementById(this.parentID); parent.removeChild(parent.childNodes.item(0)); } } -function doclink(id, name, targets) { +function doclink(id, name, targets_id) { var elt = document.getElementById(id); // If we already opened the box, then destroy it. @@ -452,9 +455,12 @@ box2.style.background = "white"; box2.style.padding = ".3em .4em .3em .4em"; box2.style.fontStyle = "normal"; - box2.onmouseout=kill_doclink; + box2.onmouseout=auto_kill_doclink; box2.parentID = id; + // Get the targets + var targets_elt = document.getElementById(targets_id); + var targets = targets_elt.getAttribute("targets"); var links = ""; target_list = targets.split(","); for (var i=0; i<target_list.length; i++) { @@ -477,6 +483,7 @@ "onclick=\'kill_doclink(\\""+id+"\\");return false;\'>"+ "<i>None of the above</i></a></li></ul>"; } + return false; } ''' @@ -702,7 +709,7 @@ def lineno_to_html(self): template = '%%%ds' % self.linenum_size n = template % self.lineno - return '<span class="py-lineno">%s</span>' % n + return '<tt class="py-lineno">%s</tt>' % n def colorize(self): """ @@ -719,6 +726,10 @@ self.def_name = None self.def_type = None + # Cache, used so we only need to list the target elements once + # for each variable. + self.doclink_targets_cache = {} + # Load the module's text. self.text = open(self.module_filename).read() self.text = self.text.expandtabs().rstrip()+'\n' @@ -828,7 +839,7 @@ self.lineno += 1 else: s = '' - s += ' <span class="py-line">' + s += ' <tt class="py-line">' # Loop through each token, and colorize it appropriately. for i, (toktype, toktext) in enumerate(line): @@ -846,7 +857,7 @@ css_class = None url = None tooltip = None - onclick = uid = None # these 3 are used together. + onclick = uid = targets = None # these 3 are used together. # Is this token the class name in a class definition? If # so, then make it a link back into the API docs. @@ -956,7 +967,7 @@ if len(docs) == 1 and self.GUESS_LINK_TARGETS: url = self.url_func(docs[0]) else: - uid, onclick = self.doclink(toktext, docs) + uid, onclick, targets = self.doclink(toktext, docs) # For all other tokens, look up the CSS class to use # based on the token's type. @@ -987,8 +998,10 @@ if css_class: css_class_html = ' class="%s"' % css_class else: css_class_html = '' if onclick: - s += ('<span id="%s"%s><a%s%s href="#" onclick="%s">' % - (uid, css_class_html, tooltip_html, + if targets: targets_html = ' targets="%s"' % targets + else: targets_html = '' + s += ('<tt id="%s"%s%s><a%s%s href="#" onclick="%s">' % + (uid, css_class_html, targets_html, tooltip_html, css_class_html, onclick)) elif url: if isinstance(url, unicode): @@ -996,9 +1009,9 @@ s += ('<a%s%s href="%s">' % (tooltip_html, css_class_html, url)) elif css_class_html or tooltip_html: - s += '<span%s%s>' % (tooltip_html, css_class_html) + s += '<tt%s%s>' % (tooltip_html, css_class_html) if i == len(line)-1: - s += ' </span>' # Closes <span class="py-line"> + s += ' </tt>' # Closes <tt class="py-line"> s += cgi.escape(toktext) else: try: @@ -1007,16 +1020,16 @@ print (toktext, css_class, toktext.encode('ascii')) raise - if onclick: s += "</a></span>" + if onclick: s += "</a></tt>" if url: s += '</a>' - elif css_class_html or tooltip_html: s += '</span>' + elif css_class_html or tooltip_html: s += '</tt>' if self.ADD_DEF_BLOCKS: 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) + # Strip any empty <tt>s. + s = re.sub(r'<tt class="[\w+]"></tt>', '', s) # Write the line. self.out(s) @@ -1048,13 +1061,20 @@ container = DottedName(self.module_name, *context) #else: # container = None - targets = ['%s=%s' % (str(self.doc_descr(d,container)), + targets = ','.join(['%s=%s' % (str(self.doc_descr(d,container)), str(self.url_func(d))) - for d in docs] - onclick = ("doclink('%s', '%s', '%s'); return false;" % - (uid, name, ','.join(targets))) - return uid, onclick + for d in docs]) + if targets in self.doclink_targets_cache: + onclick = ("return doclink('%s', '%s', '%s');" % + (uid, name, self.doclink_targets_cache[targets])) + return uid, onclick, None + else: + self.doclink_targets_cache[targets] = uid + onclick = ("return doclink('%s', '%s', '%s');" % + (uid, name, uid)) + return uid, onclick, targets + def doc_descr(self, doc, context): name = str(doc.canonical_name) descr = '%s %s' % (self.doc_kind(doc), name) @@ -1090,9 +1110,9 @@ def mark_def(self, s, name): replacement = ('<a name="%s"></a><div id="%s-def">\\1' '<a class="py-toggle" href="#" id="%s-toggle" ' - 'onclick="toggle(\'%s\'); return false;">-</a>\\2' % + 'onclick="return toggle(\'%s\');">-</a>\\2' % (name, name, name, name)) - return re.sub('(.*) (<span class="py-line">.*)\Z', replacement, s) + return re.sub('(.*) (<tt class="py-line">.*)\Z', replacement, s) def is_docstring(self, line, i): if line[i][0] != token.STRING: return False @@ -1108,13 +1128,13 @@ end = s.find('\n')+1 while end: result += s[start:end-1] - if css_class: result += '</span>' - result += ' </span>' # py-line + if css_class: result += '</tt>' + result += ' </tt>' # py-line result += '\n' if self.ADD_LINE_NUMBERS: result += self.lineno_to_html() - result += ' <span class="py-line">' - if css_class: result += '<span class="%s">' % css_class + result += ' <tt class="py-line">' + if css_class: result += '<tt class="%s">' % css_class start = end end = s.find('\n', end)+1 self.lineno += 1 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-02 01:40:41
|
Revision: 1344 http://svn.sourceforge.net/epydoc/?rev=1344&view=rev Author: edloper Date: 2006-09-01 18:40:35 -0700 (Fri, 01 Sep 2006) Log Message: ----------- - Replaced xml.dom.minidom with a *very* simple tree representation for parsed epytext. (Using the new Element class). This should significantly speed up some of the epytext processing steps. Modified Paths: -------------- trunk/epydoc/src/epydoc/markup/epytext.py trunk/epydoc/src/epydoc/test/epytext.doctest Modified: trunk/epydoc/src/epydoc/markup/epytext.py =================================================================== --- trunk/epydoc/src/epydoc/markup/epytext.py 2006-09-02 01:23:23 UTC (rev 1343) +++ trunk/epydoc/src/epydoc/markup/epytext.py 2006-09-02 01:40:35 UTC (rev 1344) @@ -9,7 +9,8 @@ """ Parser for epytext strings. Epytext is a lightweight markup whose primary intended application is Python documentation strings. This -parser converts Epytext strings to a XML/DOM representation. Epytext +parser converts Epytext strings to a simple DOM-like representation +(encoded as a tree of L{Element} objects and strings). Epytext strings can contain the following X{structural blocks}: - X{epytext}: The top-level element of the DOM tree. @@ -105,13 +106,48 @@ # 5. testing import re, string, types, sys, os.path -from xml.dom.minidom import Document, Text -import xml.dom.minidom from epydoc.markup import * from epydoc.util import wordwrap, plaintext_to_html, plaintext_to_latex from epydoc.markup.doctest import doctest_to_html, doctest_to_latex ################################################## +## DOM-Like Encoding +################################################## + +class Element: + """ + A very simple DOM-like representation for parsed epytext + documents. Each epytext document is encoded as a tree whose nodes + are L{Element} objects, and whose leaves are C{string}s. Each + node is marked by a I{tag} and zero or more I{attributes}. Each + attribute is a mapping from a string key to a string value. + """ + def __init__(self, tag, *children, **attribs): + self.tag = tag + """A string tag indicating the type of this element. + @type: C{string}""" + + self.children = list(children) + """A list of the children of this element. + @type: C{list} of (C{string} or C{Element})""" + + self.attribs = attribs + """A dictionary mapping attribute names to attribute values + for this element. + @type: C{dict} from C{string} to C{string}""" + + def __str__(self): + """ + Return a string representation of this element, using XML + notation. + @bug: Doesn't escape '<' or '&' or '>'. + """ + attribs = ''.join([' %s=%r' % t for t in self.attribs.items()]) + return ('<%s%s>' % (self.tag, attribs) + + ''.join([str(child) for child in self.children]) + + '</%s>' % self.tag) + +################################################## ## Constants ################################################## @@ -196,7 +232,7 @@ ignored. @type errors: C{list} of L{ParseError} @return: a DOM tree encoding the contents of an epytext string. - @rtype: L{xml.dom.minidom.Document} + @rtype: C{Element} @raise ParseError: If C{errors} is C{None} and an error is encountered while parsing. """ @@ -217,8 +253,8 @@ # Have we encountered a field yet? encountered_field = 0 - # Create an XML document to hold the epytext. - doc = Document() + # Create an document to hold the epytext. + doc = Element('epytext') # Maintain two parallel stacks: one contains DOM elements, and # gives the ancestors of the current block. The other contains @@ -230,13 +266,13 @@ # corresponds to). No 2 consecutive indent_stack values will be # ever be "None." Use initial dummy elements in the stack, so we # don't have to worry about bounds checking. - stack = [None, doc.createElement('epytext')] + stack = [None, doc] indent_stack = [-1, None] for token in tokens: # Uncomment this for debugging: #print ('%s: %s\n%s: %s\n' % - # (''.join(['%-11s' % (t and t.tagName) for t in stack]), + # (''.join(['%-11s' % (t and t.tag) for t in stack]), # token.tag, ''.join(['%-11s' % i for i in indent_stack]), # token.indent)) @@ -253,11 +289,11 @@ # If Token has type LBLOCK, add the new literal block elif token.tag == Token.LBLOCK: - stack[-1].appendChild(token.to_dom(doc)) + stack[-1].children.append(token.to_dom(doc)) # If Token has type DTBLOCK, add the new doctest block elif token.tag == Token.DTBLOCK: - stack[-1].appendChild(token.to_dom(doc)) + stack[-1].children.append(token.to_dom(doc)) # If Token has type BULLET, add the new list/list item/field elif token.tag == Token.BULLET: @@ -266,7 +302,7 @@ assert 0, 'Unknown token type: '+token.tag # Check if the DOM element we just added was a field.. - if stack[-1].tagName == 'field': + if stack[-1].tag == 'field': encountered_field = 1 elif encountered_field == 1: if len(stack) <= 3: @@ -282,7 +318,6 @@ return None # Return the top-level epytext DOM element. - doc.appendChild(stack[1]) return doc def _pop_completed_blocks(token, stack, indent_stack): @@ -305,10 +340,10 @@ # Dedent to a list item, if it is follwed by another list # item with the same indentation. elif (token.tag == 'bullet' and indent==indent_stack[-2] and - stack[-1].tagName in ('li', 'field')): pop=1 + stack[-1].tag in ('li', 'field')): pop=1 # End of a list (no more list items available) - elif (stack[-1].tagName in ('ulist', 'olist') and + elif (stack[-1].tag in ('ulist', 'olist') and (token.tag != 'bullet' or token.contents[-1] == ':')): pop=1 @@ -326,7 +361,7 @@ if para_token.indent == indent_stack[-1]: # Colorize the paragraph and add it. para = _colorize(doc, para_token, errors) - stack[-1].appendChild(para) + stack[-1].children.append(para) else: estr = "Improper paragraph indentation." errors.append(StructuringError(estr, para_token.startline)) @@ -341,7 +376,7 @@ # Check for errors. for tok in stack[2:]: - if tok.tagName != "section": + if tok.tag != "section": estr = "Headings must occur at the top level." errors.append(StructuringError(estr, heading_token.startline)) break @@ -358,10 +393,10 @@ head = _colorize(doc, heading_token, errors, 'heading') # Add the section's and heading's DOM elements. - sec = doc.createElement("section") - stack[-1].appendChild(sec) + sec = Element("section") + stack[-1].children.append(sec) stack.append(sec) - sec.appendChild(head) + sec.children.append(head) indent_stack.append(None) def _add_list(doc, bullet_token, stack, indent_stack, errors): @@ -382,11 +417,11 @@ # Is this a new list? newlist = 0 - if stack[-1].tagName != list_type: + if stack[-1].tag != list_type: newlist = 1 - elif list_type == 'olist' and stack[-1].tagName == 'olist': - old_listitem = stack[-1].childNodes[-1] - old_bullet = old_listitem.getAttribute("bullet").split('.')[:-1] + elif list_type == 'olist' and stack[-1].tag == 'olist': + old_listitem = stack[-1].children[-1] + old_bullet = old_listitem.attribs.get("bullet").split('.')[:-1] new_bullet = bullet_token.contents.split('.')[:-1] if (new_bullet[:-1] != old_bullet[:-1] or int(new_bullet[-1]) != int(old_bullet[-1])+1): @@ -394,7 +429,7 @@ # Create the new list. if newlist: - if stack[-1].tagName is 'fieldlist': + if stack[-1].tag is 'fieldlist': # The new list item is not a field list item (since this # is a new list); but it's indented the same as the field # list. This either means that they forgot to indent the @@ -403,7 +438,7 @@ # just warn about that (to avoid confusion). estr = "Lists must be indented." errors.append(StructuringError(estr, bullet_token.startline)) - if stack[-1].tagName in ('ulist', 'olist', 'fieldlist'): + if stack[-1].tag in ('ulist', 'olist', 'fieldlist'): stack.pop() indent_stack.pop() @@ -419,7 +454,7 @@ if list_type == 'fieldlist': # Fieldlist should be at the top-level. for tok in stack[2:]: - if tok.tagName != "section": + if tok.tag != "section": estr = "Fields must be at the top level." errors.append( StructuringError(estr, bullet_token.startline)) @@ -428,41 +463,40 @@ indent_stack[2:] = [] # Add the new list. - lst = doc.createElement(list_type) - stack[-1].appendChild(lst) + lst = Element(list_type) + stack[-1].children.append(lst) stack.append(lst) indent_stack.append(bullet_token.indent) if list_type == 'olist': start = bullet_token.contents.split('.')[:-1] if start != '1': - lst.setAttribute("start", start[-1]) + lst.attribs["start"] = start[-1] # Fields are treated somewhat specially: A "fieldlist" # node is created to make the parsing simpler, but fields # are adjoined directly into the "epytext" node, not into # the "fieldlist" node. if list_type == 'fieldlist': - li = doc.createElement("field") + li = Element("field") token_words = bullet_token.contents[1:-1].split(None, 1) - tag_elt = doc.createElement("tag") - tag_elt.appendChild(doc.createTextNode(token_words[0])) - li.appendChild(tag_elt) + tag_elt = Element("tag") + tag_elt.children.append(token_words[0]) + li.children.append(tag_elt) if len(token_words) > 1: - arg_elt = doc.createElement("arg") - arg_elt.appendChild(doc.createTextNode(token_words[1])) - li.appendChild(arg_elt) + arg_elt = Element("arg") + arg_elt.children.append(token_words[1]) + li.children.append(arg_elt) else: - li = doc.createElement("li") + li = Element("li") if list_type == 'olist': - li.setAttribute("bullet", bullet_token.contents) + li.attribs["bullet"] = bullet_token.contents # Add the bullet. - stack[-1].appendChild(li) + stack[-1].children.append(li) stack.append(li) indent_stack.append(None) - ################################################## ## Tokenization ################################################## @@ -570,10 +604,10 @@ def to_dom(self, doc): """ @return: a DOM representation of this C{Token}. - @rtype: L{xml.dom.minidom.Element} + @rtype: L{Element} """ - e = doc.createElement(self.tag) - e.appendChild(doc.createTextNode(self.contents)) + e = Element(self.tag) + e.children.append(self.contents) return e # Construct regular expressions for recognizing bullets. These are @@ -941,7 +975,7 @@ # the text currently being analyzed. New elements are pushed when # "{" is encountered, and old elements are popped when "}" is # encountered. - stack = [doc.createElement(tagName)] + stack = [Element(tagName)] # This is just used to make error-reporting friendlier. It's a # stack parallel to "stack" containing the index of each element's @@ -967,20 +1001,20 @@ if match.group() == '{': if (end>0) and 'A' <= str[end-1] <= 'Z': if (end-1) > start: - stack[-1].appendChild(doc.createTextNode(str[start:end-1])) + stack[-1].children.append(str[start:end-1]) if not _COLORIZING_TAGS.has_key(str[end-1]): estr = "Unknown inline markup tag." errors.append(ColorizingError(estr, token, end-1)) - stack.append(doc.createElement('unknown')) + stack.append(Element('unknown')) else: tag = _COLORIZING_TAGS[str[end-1]] - stack.append(doc.createElement(tag)) + stack.append(Element(tag)) else: if end > start: - stack[-1].appendChild(doc.createTextNode(str[start:end])) - stack.append(doc.createElement('litbrace')) + stack[-1].children.append(str[start:end]) + stack.append(Element('litbrace')) openbrace_stack.append(end) - stack[-2].appendChild(stack[-1]) + stack[-2].children.append(stack[-1]) # Close braces end colorizing elements. elif match.group() == '}': @@ -993,62 +1027,51 @@ # Add any remaining text. if end > start: - stack[-1].appendChild(doc.createTextNode(str[start:end])) + stack[-1].children.append(str[start:end]) # Special handling for symbols: - if stack[-1].tagName == 'symbol': - if (len(stack[-1].childNodes) != 1 or - not isinstance(stack[-1].childNodes[0], Text)): + if stack[-1].tag == 'symbol': + if (len(stack[-1].children) != 1 or + not isinstance(stack[-1].children[0], basestring)): estr = "Invalid symbol code." errors.append(ColorizingError(estr, token, end)) else: - symb = stack[-1].childNodes[0].data + symb = stack[-1].children[0] if _SYMBOLS.has_key(symb): # It's a symbol - symbol = doc.createElement('symbol') - stack[-2].removeChild(stack[-1]) - stack[-2].appendChild(symbol) - symbol.appendChild(doc.createTextNode(symb)) + stack[-2].children[-1] = Element('symbol', symb) else: estr = "Invalid symbol code." errors.append(ColorizingError(estr, token, end)) # Special handling for escape elements: - if stack[-1].tagName == 'escape': - if (len(stack[-1].childNodes) != 1 or - not isinstance(stack[-1].childNodes[0], Text)): + if stack[-1].tag == 'escape': + if (len(stack[-1].children) != 1 or + not isinstance(stack[-1].children[0], basestring)): estr = "Invalid escape code." errors.append(ColorizingError(estr, token, end)) else: - escp = stack[-1].childNodes[0].data + escp = stack[-1].children[0] if _ESCAPES.has_key(escp): # It's an escape from _ESCPAES - stack[-2].removeChild(stack[-1]) - escp = _ESCAPES[escp] - stack[-2].appendChild(doc.createTextNode(escp)) + stack[-2].children[-1] = _ESCAPES[escp] elif len(escp) == 1: # It's a single-character escape (eg E{.}) - stack[-2].removeChild(stack[-1]) - stack[-2].appendChild(doc.createTextNode(escp)) + stack[-2].children[-1] = escp else: estr = "Invalid escape code." errors.append(ColorizingError(estr, token, end)) # Special handling for literal braces elements: - if stack[-1].tagName == 'litbrace': - variables = stack[-1].childNodes - stack[-2].removeChild(stack[-1]) - stack[-2].appendChild(doc.createTextNode('{')) - for child in variables: - stack[-2].appendChild(child) - stack[-2].appendChild(doc.createTextNode('}')) + if stack[-1].tag == 'litbrace': + stack[-2].children = ['{'] + stack[-1].children + ['}'] # Special handling for graphs: - if stack[-1].tagName == 'graph': + if stack[-1].tag == 'graph': _colorize_graph(doc, stack[-1], token, end, errors) # Special handling for link-type elements: - if stack[-1].tagName in _LINK_COLORIZING_TAGS: + if stack[-1].tag in _LINK_COLORIZING_TAGS: _colorize_link(doc, stack[-1], token, end, errors) # Pop the completed element. @@ -1059,7 +1082,7 @@ # Add any final text. if start < len(str): - stack[-1].appendChild(doc.createTextNode(str[start:])) + stack[-1].children.append(str[start:]) if len(stack) != 1: estr = "Unbalanced '{'." @@ -1078,13 +1101,13 @@ """ bad_graph_spec = False - children = graph.childNodes[:] - for child in children: graph.removeChild(child) + children = graph.children[:] + graph.children = [] - if len(children) != 1 or not isinstance(children[0], Text): + if len(children) != 1 or not isinstance(children[0], basestring): bad_graph_spec = "Bad graph specification" else: - pieces = children[0].data.split(None, 1) + pieces = children[0].split(None, 1) graphtype = pieces[0].replace(':','').strip().lower() if graphtype in GRAPH_TYPES: if len(pieces) == 2: @@ -1100,51 +1123,49 @@ if bad_graph_spec: errors.append(ColorizingError(bad_graph_spec, token, end)) - graph.appendChild(doc.createTextNode('none')) - graph.appendChild(doc.createTextNode('')) + graph.children.append('none') + graph.children.append('') return - graph.appendChild(doc.createTextNode(graphtype)) + graph.children.append(graphtype) for arg in args: - graph.appendChild(doc.createTextNode(arg)) + graph.children.append(arg) def _colorize_link(doc, link, token, end, errors): - variables = link.childNodes[:] + variables = link.children[:] # If the last child isn't text, we know it's bad. - if len(variables)==0 or not isinstance(variables[-1], Text): - estr = "Bad %s target." % link.tagName + if len(variables)==0 or not isinstance(variables[-1], basestring): + estr = "Bad %s target." % link.tag errors.append(ColorizingError(estr, token, end)) return # Did they provide an explicit target? - match2 = _TARGET_RE.match(variables[-1].data) + match2 = _TARGET_RE.match(variables[-1]) if match2: (text, target) = match2.groups() - variables[-1].data = text + variables[-1] = text # Can we extract an implicit target? elif len(variables) == 1: - target = variables[0].data + target = variables[0] else: - estr = "Bad %s target." % link.tagName + estr = "Bad %s target." % link.tag errors.append(ColorizingError(estr, token, end)) return # Construct the name element. - name_elt = doc.createElement('name') - for child in variables: - name_elt.appendChild(link.removeChild(child)) + name_elt = Element('name', *variables) # Clean up the target. For URIs, assume http or mailto if they # don't specify (no relative urls) target = re.sub(r'\s', '', target) - if link.tagName=='uri': + if link.tag=='uri': if not re.match(r'\w+:', target): if re.match(r'\w+@(\w+)(\.\w+)*', target): target = 'mailto:' + target else: target = 'http://'+target - elif link.tagName=='link': + elif link.tag=='link': # Remove arg lists for functions (e.g., L{_colorize_link()}) target = re.sub(r'\(.*\)$', '', target) if not re.match(r'^[a-zA-Z_]\w*(\.[a-zA-Z_]\w*)*$', target): @@ -1153,12 +1174,10 @@ return # Construct the target element. - target_elt = doc.createElement('target') - target_elt.appendChild(doc.createTextNode(target)) + target_elt = Element('target', target) # Add them to the link element. - link.appendChild(name_elt) - link.appendChild(target_elt) + link.children = [name_elt, target_elt] ################################################## ## Formatters @@ -1176,7 +1195,7 @@ - C{to_epytext(parse(str)) == str} (approximately) @param tree: A DOM document encoding of an epytext string. - @type tree: L{xml.dom.minidom.Document} + @type tree: C{Element} @param indent: The indentation for the string representation of C{tree}. Each line of the returned string will begin with C{indent} space characters. @@ -1187,22 +1206,20 @@ @return: The epytext string corresponding to C{tree}. @rtype: C{string} """ - if isinstance(tree, Document): - return to_epytext(tree.childNodes[0], indent, seclevel) - if isinstance(tree, Text): - str = re.sub(r'\{', '\0', tree.data) + if isinstance(tree, basestring): + str = re.sub(r'\{', '\0', tree) str = re.sub(r'\}', '\1', str) return str - if tree.tagName == 'epytext': indent -= 2 - if tree.tagName == 'section': seclevel += 1 - variables = [to_epytext(c, indent+2, seclevel) for c in tree.childNodes] + if tree.tag == 'epytext': indent -= 2 + if tree.tag == 'section': seclevel += 1 + variables = [to_epytext(c, indent+2, seclevel) for c in tree.children] childstr = ''.join(variables) # Clean up for literal blocks (add the double "::" back) childstr = re.sub(':(\s*)\2', '::\\1', childstr) - if tree.tagName == 'para': + if tree.tag == 'para': str = wordwrap(childstr, indent)+'\n' str = re.sub(r'((^|\n)\s*\d+)\.', r'\1E{.}', str) str = re.sub(r'((^|\n)\s*)-', r'\1E{-}', str) @@ -1211,49 +1228,47 @@ str = re.sub('\0', 'E{lb}', str) str = re.sub('\1', 'E{rb}', str) return str - elif tree.tagName == 'li': - bulletAttr = tree.getAttributeNode('bullet') - if bulletAttr: bullet = bulletAttr.value - else: bullet = '-' + elif tree.tag == 'li': + bullet = tree.attribs.get('bullet') or '-' return indent*' '+ bullet + ' ' + childstr.lstrip() - elif tree.tagName == 'heading': + elif tree.tag == 'heading': str = re.sub('\0', 'E{lb}',childstr) str = re.sub('\1', 'E{rb}', str) uline = len(childstr)*_HEADING_CHARS[seclevel-1] return (indent-2)*' ' + str + '\n' + (indent-2)*' '+uline+'\n' - elif tree.tagName == 'doctestblock': + elif tree.tag == 'doctestblock': str = re.sub('\0', '{', childstr) str = re.sub('\1', '}', str) lines = [' '+indent*' '+line for line in str.split('\n')] return '\n'.join(lines) + '\n\n' - elif tree.tagName == 'literalblock': + elif tree.tag == 'literalblock': str = re.sub('\0', '{', childstr) str = re.sub('\1', '}', str) lines = [(indent+1)*' '+line for line in str.split('\n')] return '\2' + '\n'.join(lines) + '\n\n' - elif tree.tagName == 'field': + elif tree.tag == 'field': numargs = 0 - while tree.childNodes[numargs+1].tagName == 'arg': numargs += 1 + while tree.children[numargs+1].tag == 'arg': numargs += 1 tag = variables[0] args = variables[1:1+numargs] body = variables[1+numargs:] str = (indent)*' '+'@'+variables[0] if args: str += '(' + ', '.join(args) + ')' return str + ':\n' + ''.join(body) - elif tree.tagName == 'target': + elif tree.tag == 'target': return '<%s>' % childstr - elif tree.tagName in ('fieldlist', 'tag', 'arg', 'epytext', + elif tree.tag in ('fieldlist', 'tag', 'arg', 'epytext', 'section', 'olist', 'ulist', 'name'): return childstr - elif tree.tagName == 'symbol': + elif tree.tag == 'symbol': return 'E{%s}' % childstr - elif tree.tagName == 'graph': + elif tree.tag == 'graph': return 'G{%s}' % ' '.join(variables) else: for (tag, name) in _COLORIZING_TAGS.items(): - if name == tree.tagName: + if name == tree.tag: return '%s{%s}' % (tag, childstr) - raise ValueError('Unknown DOM element %r' % tree.tagName) + raise ValueError('Unknown DOM element %r' % tree.tag) def to_plaintext(tree, indent=0, seclevel=0): """ @@ -1263,7 +1278,7 @@ escaped characters in unescaped form, etc. @param tree: A DOM document encoding of an epytext string. - @type tree: L{xml.dom.minidom.Document} + @type tree: C{Element} @param indent: The indentation for the string representation of C{tree}. Each line of the returned string will begin with C{indent} space characters. @@ -1274,67 +1289,63 @@ @return: The epytext string corresponding to C{tree}. @rtype: C{string} """ - if isinstance(tree, Document): - return to_plaintext(tree.childNodes[0], indent, seclevel) - if isinstance(tree, Text): return tree.data + if isinstance(tree, basestring): return tree - if tree.tagName == 'section': seclevel += 1 + if tree.tag == 'section': seclevel += 1 # Figure out the child indent level. - if tree.tagName == 'epytext': cindent = indent - elif tree.tagName == 'li' and tree.getAttributeNode('bullet'): - cindent = indent + 1 + len(tree.getAttributeNode('bullet').value) + if tree.tag == 'epytext': cindent = indent + elif tree.tag == 'li' and tree.attribs.get('bullet'): + cindent = indent + 1 + len(tree.attribs.get('bullet')) else: cindent = indent + 2 - variables = [to_plaintext(c, cindent, seclevel) for c in tree.childNodes] + variables = [to_plaintext(c, cindent, seclevel) for c in tree.children] childstr = ''.join(variables) - if tree.tagName == 'para': + if tree.tag == 'para': return wordwrap(childstr, indent)+'\n' - elif tree.tagName == 'li': + elif tree.tag == 'li': # We should be able to use getAttribute here; but there's no # convenient way to test if an element has an attribute.. - bulletAttr = tree.getAttributeNode('bullet') - if bulletAttr: bullet = bulletAttr.value - else: bullet = '-' + bullet = tree.attribs.get('bullet') or '-' return indent*' ' + bullet + ' ' + childstr.lstrip() - elif tree.tagName == 'heading': + elif tree.tag == 'heading': uline = len(childstr)*_HEADING_CHARS[seclevel-1] return ((indent-2)*' ' + childstr + '\n' + (indent-2)*' ' + uline + '\n') - elif tree.tagName == 'doctestblock': + elif tree.tag == 'doctestblock': lines = [(indent+2)*' '+line for line in childstr.split('\n')] return '\n'.join(lines) + '\n\n' - elif tree.tagName == 'literalblock': + elif tree.tag == 'literalblock': lines = [(indent+1)*' '+line for line in childstr.split('\n')] return '\n'.join(lines) + '\n\n' - elif tree.tagName == 'fieldlist': + elif tree.tag == 'fieldlist': return childstr - elif tree.tagName == 'field': + elif tree.tag == 'field': numargs = 0 - while tree.childNodes[numargs+1].tagName == 'arg': numargs += 1 + while tree.children[numargs+1].tag == 'arg': numargs += 1 tag = variables[0] args = variables[1:1+numargs] body = variables[1+numargs:] str = (indent)*' '+'@'+variables[0] if args: str += '(' + ', '.join(args) + ')' return str + ':\n' + ''.join(body) - elif tree.tagName == 'uri': + elif tree.tag == 'uri': if len(variables) != 2: raise ValueError('Bad URI ') elif variables[0] == variables[1]: return '<%s>' % variables[1] else: return '%r<%s>' % (variables[0], variables[1]) - elif tree.tagName == 'link': + elif tree.tag == 'link': if len(variables) != 2: raise ValueError('Bad Link') return '%s' % variables[0] - elif tree.tagName in ('olist', 'ulist'): + elif tree.tag in ('olist', 'ulist'): # [xx] always use condensed lists. ## Use a condensed list if each list item is 1 line long. #for child in variables: # if child.count('\n') > 2: return childstr return childstr.replace('\n\n', '\n')+'\n' - elif tree.tagName == 'symbol': + elif tree.tag == 'symbol': return '%s' % childstr - elif tree.tagName == 'graph': + elif tree.tag == 'graph': return '<<%s graph: %s>>' % (variables[0], ', '.join(variables[1:])) else: # Assume that anything else can be passed through. @@ -1348,7 +1359,7 @@ where different blocks begin, along the left margin. @param tree: A DOM document encoding of an epytext string. - @type tree: L{xml.dom.minidom.Document} + @type tree: C{Element} @param indent: The indentation for the string representation of C{tree}. Each line of the returned string will begin with C{indent} space characters. @@ -1359,21 +1370,19 @@ @return: The epytext string corresponding to C{tree}. @rtype: C{string} """ - if isinstance(tree, Document): - return to_debug(tree.childNodes[0], indent, seclevel) - if isinstance(tree, Text): - str = re.sub(r'\{', '\0', tree.data) + if isinstance(tree, basestring): + str = re.sub(r'\{', '\0', tree) str = re.sub(r'\}', '\1', str) return str - if tree.tagName == 'section': seclevel += 1 - variables = [to_debug(c, indent+2, seclevel) for c in tree.childNodes] + if tree.tag == 'section': seclevel += 1 + variables = [to_debug(c, indent+2, seclevel) for c in tree.children] childstr = ''.join(variables) # Clean up for literal blocks (add the double "::" back) childstr = re.sub(':( *\n \|\n)\2', '::\\1', childstr) - if tree.tagName == 'para': + if tree.tag == 'para': str = wordwrap(childstr, indent-6, 69)+'\n' str = re.sub(r'((^|\n)\s*\d+)\.', r'\1E{.}', str) str = re.sub(r'((^|\n)\s*)-', r'\1E{-}', str) @@ -1385,54 +1394,52 @@ lines[0] = ' P>|' + lines[0] lines[1:] = [' |'+l for l in lines[1:]] return '\n'.join(lines)+'\n |\n' - elif tree.tagName == 'li': - bulletAttr = tree.getAttributeNode('bullet') - if bulletAttr: bullet = bulletAttr.value - else: bullet = '-' + elif tree.tag == 'li': + bullet = tree.attribs.get('bullet') or '-' return ' LI>|'+ (indent-6)*' '+ bullet + ' ' + childstr[6:].lstrip() - elif tree.tagName in ('olist', 'ulist'): + elif tree.tag in ('olist', 'ulist'): return 'LIST>|'+(indent-4)*' '+childstr[indent+2:] - elif tree.tagName == 'heading': + elif tree.tag == 'heading': str = re.sub('\0', 'E{lb}', childstr) str = re.sub('\1', 'E{rb}', str) uline = len(childstr)*_HEADING_CHARS[seclevel-1] return ('SEC'+`seclevel`+'>|'+(indent-8)*' ' + str + '\n' + ' |'+(indent-8)*' ' + uline + '\n') - elif tree.tagName == 'doctestblock': + elif tree.tag == 'doctestblock': str = re.sub('\0', '{', childstr) str = re.sub('\1', '}', str) lines = [' |'+(indent-4)*' '+line for line in str.split('\n')] lines[0] = 'DTST>'+lines[0][5:] return '\n'.join(lines) + '\n |\n' - elif tree.tagName == 'literalblock': + elif tree.tag == 'literalblock': str = re.sub('\0', '{', childstr) str = re.sub('\1', '}', str) lines = [' |'+(indent-5)*' '+line for line in str.split('\n')] lines[0] = ' LIT>'+lines[0][5:] return '\2' + '\n'.join(lines) + '\n |\n' - elif tree.tagName == 'field': + elif tree.tag == 'field': numargs = 0 - while tree.childNodes[numargs+1].tagName == 'arg': numargs += 1 + while tree.children[numargs+1].tag == 'arg': numargs += 1 tag = variables[0] args = variables[1:1+numargs] body = variables[1+numargs:] str = ' FLD>|'+(indent-6)*' '+'@'+variables[0] if args: str += '(' + ', '.join(args) + ')' return str + ':\n' + ''.join(body) - elif tree.tagName == 'target': + elif tree.tag == 'target': return '<%s>' % childstr - elif tree.tagName in ('fieldlist', 'tag', 'arg', 'epytext', + elif tree.tag in ('fieldlist', 'tag', 'arg', 'epytext', 'section', 'olist', 'ulist', 'name'): return childstr - elif tree.tagName == 'symbol': + elif tree.tag == 'symbol': return 'E{%s}' % childstr - elif tree.tagName == 'graph': + elif tree.tag == 'graph': return 'G{%s}' % ' '.join(variables) else: for (tag, name) in _COLORIZING_TAGS.items(): - if name == tree.tagName: + if name == tree.tag: return '%s{%s}' % (tag, childstr) - raise ValueError('Unknown DOM element %r' % tree.tagName) + raise ValueError('Unknown DOM element %r' % tree.tag) ################################################## ## Top-Level Wrapper function @@ -1455,7 +1462,7 @@ written to. @type stream: C{stream} @return: a DOM document encoding the contents of C{str}. - @rtype: L{xml.dom.minidom.Document} + @rtype: C{Element} @raise SyntaxError: If any fatal errors were encountered. """ errors = [] @@ -1556,15 +1563,9 @@ @return: A DOM document containing C{str} in a single literal block. - @rtype: L{xml.dom.minidom.Document} + @rtype: C{Element} """ - doc = Document() - epytext = doc.createElement('epytext') - lit = doc.createElement('literalblock') - doc.appendChild(epytext) - epytext.appendChild(lit) - lit.appendChild(doc.createTextNode(str)) - return doc + return Element('epytext', Element('literalblock', str)) def parse_as_para(str): """ @@ -1578,15 +1579,9 @@ @type str: C{string} @return: A DOM document containing C{str} in a single paragraph. - @rtype: L{xml.dom.minidom.Document} + @rtype: C{Element} """ - doc = Document() - epytext = doc.createElement('epytext') - para = doc.createElement('para') - doc.appendChild(epytext) - epytext.appendChild(para) - para.appendChild(doc.createTextNode(str)) - return doc + return Element('epytext', Element('para', str)) ################################################################# ## SUPPORT FOR EPYDOC @@ -1710,8 +1705,6 @@ } def __init__(self, dom_tree): - if isinstance(dom_tree, Document): - dom_tree = dom_tree.childNodes[0] self._tree = dom_tree # Caching: self._html = self._latex = self._plaintext = None @@ -1752,84 +1745,81 @@ def _to_html(self, tree, linker, directory, docindex, context, indent=0, seclevel=0): - if isinstance(tree, Text): - return plaintext_to_html(tree.data) + if isinstance(tree, basestring): + return plaintext_to_html(tree) - if tree.tagName == 'epytext': indent -= 2 - if tree.tagName == 'section': seclevel += 1 + if tree.tag == 'epytext': indent -= 2 + if tree.tag == 'section': seclevel += 1 # Process the variables first. variables = [self._to_html(c, linker, directory, docindex, context, indent+2, seclevel) - for c in tree.childNodes] + for c in tree.children] # Get rid of unnecessary <P>...</P> tags; they introduce extra # space on most browsers that we don't want. for i in range(len(variables)-1): - if (not isinstance(tree.childNodes[i], Text) and - tree.childNodes[i].tagName == 'para' and - (isinstance(tree.childNodes[i+1], Text) or - tree.childNodes[i+1].tagName != 'para')): + if (not isinstance(tree.children[i], basestring) and + tree.children[i].tag == 'para' and + (isinstance(tree.children[i+1], basestring) or + tree.children[i+1].tag != 'para')): variables[i] = ' '*(indent+2)+variables[i][5+indent:-5]+'\n' - if (tree.hasChildNodes() and - not isinstance(tree.childNodes[-1], Text) and - tree.childNodes[-1].tagName == 'para'): + if (tree.children and + not isinstance(tree.children[-1], basestring) and + tree.children[-1].tag == 'para'): variables[-1] = ' '*(indent+2)+variables[-1][5+indent:-5]+'\n' # Construct the HTML string for the variables. childstr = ''.join(variables) # Perform the approriate action for the DOM tree type. - if tree.tagName == 'para': + if tree.tag == 'para': return wordwrap('<p>%s</p>' % childstr, indent) - elif tree.tagName == 'code': + elif tree.tag == 'code': return '<code>%s</code>' % childstr - elif tree.tagName == 'uri': + elif tree.tag == 'uri': return ('<a href="%s" target="_top">%s</a>' % (variables[1], variables[0])) - elif tree.tagName == 'link': + elif tree.tag == 'link': return linker.translate_identifier_xref(variables[1], variables[0]) - elif tree.tagName == 'italic': + elif tree.tag == 'italic': return '<i>%s</i>' % childstr - elif tree.tagName == 'math': + elif tree.tag == 'math': return '<i class="math">%s</i>' % childstr - elif tree.tagName == 'indexed': - term = tree.cloneNode(1) - term.tagName = 'epytext' + elif tree.tag == 'indexed': + term = Element('epytext', *tree.children, **tree.attribs) return linker.translate_indexterm(ParsedEpytextDocstring(term)) #term_key = self._index_term_key(tree) #return linker.translate_indexterm(childstr, term_key) - elif tree.tagName == 'bold': + elif tree.tag == 'bold': return '<b>%s</b>' % childstr - elif tree.tagName == 'ulist': + elif tree.tag == 'ulist': return '%s<ul>\n%s%s</ul>\n' % (indent*' ', childstr, indent*' ') - elif tree.tagName == 'olist': - startAttr = tree.getAttributeNode('start') - if startAttr: start = ' start="%s"' % startAttr.value - else: start = '' + elif tree.tag == 'olist': + start = tree.attribs.get('start') or '' return ('%s<ol%s>\n%s%s</ol>\n' % (indent*' ', start, childstr, indent*' ')) - elif tree.tagName == 'li': + elif tree.tag == 'li': return indent*' '+'<li>\n%s%s</li>\n' % (childstr, indent*' ') - elif tree.tagName == 'heading': + elif tree.tag == 'heading': return ('%s<h%s class="heading">%s</h%s>\n' % ((indent-2)*' ', seclevel, childstr, seclevel)) - elif tree.tagName == 'literalblock': + elif tree.tag == 'literalblock': return '<pre class="literalblock">\n%s\n</pre>\n' % childstr - elif tree.tagName == 'doctestblock': - return doctest_to_html(tree.childNodes[0].data.strip()) - elif tree.tagName == 'fieldlist': + elif tree.tag == 'doctestblock': + return doctest_to_html(tree.children[0].strip()) + elif tree.tag == 'fieldlist': raise AssertionError("There should not be any field lists left") - elif tree.tagName in ('epytext', 'section', 'tag', 'arg', + elif tree.tag in ('epytext', 'section', 'tag', 'arg', 'name', 'target', 'html'): return childstr - elif tree.tagName == 'symbol': - symbol = tree.childNodes[0].data + elif tree.tag == 'symbol': + symbol = tree.children[0] if self.SYMBOL_TO_HTML.has_key(symbol): return '&%s;' % self.SYMBOL_TO_HTML[symbol] else: return '[??]' - elif tree.tagName == 'graph': + elif tree.tag == 'graph': # Generate the graph. graph = self._build_graph(variables[0], variables[1:], linker, docindex, context) @@ -1839,7 +1829,7 @@ image_file = os.path.join(directory, image_url) return graph.to_html(image_file, image_url) else: - raise ValueError('Unknown epytext DOM element %r' % tree.tagName) + raise ValueError('Unknown epytext DOM element %r' % tree.tag) #GRAPH_TYPES = ['classtree', 'packagetree', 'importgraph'] def _build_graph(self, graph_type, graph_args, linker, @@ -1883,27 +1873,27 @@ def _to_latex(self, tree, linker, indent=0, seclevel=0, breakany=0): - if isinstance(tree, Text): - return plaintext_to_latex(tree.data, breakany=breakany) + if isinstance(tree, basestring): + return plaintext_to_latex(tree, breakany=breakany) - if tree.tagName == 'section': seclevel += 1 + if tree.tag == 'section': seclevel += 1 # Figure out the child indent level. - if tree.tagName == 'epytext': cindent = indent + if tree.tag == 'epytext': cindent = indent else: cindent = indent + 2 variables = [self._to_latex(c, linker, cindent, seclevel, breakany) - for c in tree.childNodes] + for c in tree.children] childstr = ''.join(variables) - if tree.tagName == 'para': + if tree.tag == 'para': return wordwrap(childstr, indent)+'\n' - elif tree.tagName == 'code': + elif tree.tag == 'code': return '\\texttt{%s}' % childstr - elif tree.tagName == 'uri': + elif tree.tag == 'uri': if len(variables) != 2: raise ValueError('Bad URI ') if self._hyperref: # ~ and # should not be escaped in the URI. - uri = tree.childNodes[1].childNodes[0].data + uri = tree.children[1].children[0] uri = uri.replace('{\\textasciitilde}', '~') uri = uri.replace('\\#', '#') if variables[0] == variables[1]: @@ -1916,46 +1906,45 @@ return '\\textit{%s}' % variables[1] else: return '%s\\footnote{%s}' % (variables[0], variables[1]) - elif tree.tagName == 'link': + elif tree.tag == 'link': if len(variables) != 2: raise ValueError('Bad Link') return linker.translate_identifier_xref(variables[1], variables[0]) - elif tree.tagName == 'italic': + elif tree.tag == 'italic': return '\\textit{%s}' % childstr - elif tree.tagName == 'math': + elif tree.tag == 'math': return '\\textit{%s}' % childstr - elif tree.tagName == 'indexed': - term = tree.cloneNode(1) - term.tagName = 'epytext' + elif tree.tag == 'indexed': + term = Element('epytext', *tree.children, **tree.attribs) return linker.translate_indexterm(ParsedEpytextDocstring(term)) - elif tree.tagName == 'bold': + elif tree.tag == 'bold': return '\\textbf{%s}' % childstr - elif tree.tagName == 'li': + elif tree.tag == 'li': return indent*' ' + '\\item ' + childstr.lstrip() - elif tree.tagName == 'heading': + elif tree.tag == 'heading': return ' '*(indent-2) + '(section) %s\n\n' % childstr - elif tree.tagName == 'doctestblock': - return doctest_to_latex(tree.childNodes[0].data.strip()) - elif tree.tagName == 'literalblock': + elif tree.tag == 'doctestblock': + return doctest_to_latex(tree.children[0].strip()) + elif tree.tag == 'literalblock': return '\\begin{alltt}\n%s\\end{alltt}\n\n' % childstr - elif tree.tagName == 'fieldlist': + elif tree.tag == 'fieldlist': return indent*' '+'{omitted fieldlist}\n' - elif tree.tagName == 'olist': + elif tree.tag == 'olist': return (' '*indent + '\\begin{enumerate}\n\n' + ' '*indent + '\\setlength{\\parskip}{0.5ex}\n' + childstr + ' '*indent + '\\end{enumerate}\n\n') - elif tree.tagName == 'ulist': + elif tree.tag == 'ulist': return (' '*indent + '\\begin{itemize}\n' + ' '*indent + '\\setlength{\\parskip}{0.6ex}\n' + childstr + ' '*indent + '\\end{itemize}\n\n') - elif tree.tagName == 'symbol': - symbol = tree.childNodes[0].data + elif tree.tag == 'symbol': + symbol = tree.children[0] if self.SYMBOL_TO_LATEX.has_key(symbol): return r'%s' % self.SYMBOL_TO_LATEX[symbol] else: return '[??]' - elif tree.tagName == 'graph': + elif tree.tag == 'graph': return '(GRAPH)' #raise ValueError, 'graph not implemented yet for latex' else: @@ -1964,78 +1953,73 @@ def summary(self): if self._tree is None: return self - - # Is the cloning that happens here safe/proper? (Cloning - # between 2 different documents) tree = self._tree - - doc = Document() - epytext = doc.createElement('epytext') - doc.appendChild(epytext) + doc = Element('epytext') # Find the first paragraph. - variables = tree.childNodes - while (len(variables) > 0) and (variables[0].tagName != 'para'): - if variables[0].tagName in ('section', 'ulist', 'olist', 'li'): - variables = variables[0].childNodes + variables = tree.children + while (len(variables) > 0) and (variables[0].tag != 'para'): + if variables[0].tag in ('section', 'ulist', 'olist', 'li'): + variables = variables[0].children else: variables = variables[1:] # Special case: if the docstring contains a single literal block, # then try extracting the summary from it. - if (len(variables) == 0 and len(tree.childNodes) == 1 and - tree.childNodes[0].tagName == 'literalblock'): + if (len(variables) == 0 and len(tree.children) == 1 and + tree.children[0].tag == 'literalblock'): str = re.split(r'\n\s*(\n|$).*', - tree.childNodes[0].childNodes[0].data, 1)[0] - variables = [doc.createElement('para')] - variables[0].appendChild(doc.createTextNode(str)) + tree.children[0].children[0], 1)[0] + variables = [Element('para')] + variables[0].children.append(str) # If we didn't find a paragraph, return an empty epytext. if len(variables) == 0: return ParsedEpytextDocstring(doc) # Extract the first sentence. - parachildren = variables[0].childNodes - para = doc.createElement('para') - epytext.appendChild(para) + parachildren = variables[0].children + para = Element('para') + doc.children.append(para) for parachild in parachildren: - if isinstance(parachild, Text): - m = re.match(r'(\s*[\w\W]*?\.)(\s|$)', parachild.data) + if isinstance(parachild, basestring): + m = re.match(r'(\s*[\w\W]*?\.)(\s|$)', parachild) if m: - para.appendChild(doc.createTextNode(m.group(1))) + para.children.append(m.group(1)) return ParsedEpytextDocstring(doc) - para.appendChild(parachild.cloneNode(1)) + para.children.append(parachild) return ParsedEpytextDocstring(doc) def split_fields(self, errors=None): if self._tree is None: return (self, ()) - tree = self._tree.cloneNode(1) # Hmm.. + tree = Element(self._tree.tag, *self._tree.children, + **self._tree.attribs) fields = [] - if (tree.hasChildNodes() and - tree.childNodes[-1].tagName == 'fieldlist' and - tree.childNodes[-1].hasChildNodes()): - field_nodes = tree.childNodes[-1].childNodes - tree.removeChild(tree.childNodes[-1]) + if (tree.children and + tree.children[-1].tag == 'fieldlist' and + tree.children[-1].children): + field_nodes = tree.children[-1].children + del tree.children[-1] for field in field_nodes: # Get the tag - tag = field.childNodes[0].childNodes[0].data.lower() - field.removeChild(field.childNodes[0]) + tag = field.children[0].children[0].lower() + del field.children[0] # Get the argument. - if field.childNodes and field.childNodes[0].tagName == 'arg': - arg = field.childNodes[0].childNodes[0].data - field.removeChild(field.childNodes[0]) + if field.children and field.children[0].tag == 'arg': + arg = field.children[0].children[0] + del field.children[0] else: arg = None # Process the field. - field.tagName = 'epytext' + field.tag = 'epytext' fields.append(Field(tag, arg, ParsedEpytextDocstring(field))) # Save the remaining docstring as the description.. - if tree.hasChildNodes() and tree.childNodes[0].hasChildNodes(): + if tree.children and tree.children[0].children: descr = tree else: descr = None @@ -2049,14 +2033,13 @@ return self._terms def _index_terms(self, tree, terms): - if tree is None or isinstance(tree, Text): + if tree is None or isinstance(tree, basestring): return - if tree.tagName == 'indexed': - term = tree.cloneNode(1) - term.tagName = 'epytext' + if tree.tag == 'indexed': + term = Element('epytext', *tree.children, **tree.attribs) terms.append(ParsedEpytextDocstring(term)) # Look for index items in child nodes. - for child in tree.childNodes: + for child in tree.children: self._index_terms(child, terms) Modified: trunk/epydoc/src/epydoc/test/epytext.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/epytext.doctest 2006-09-02 01:23:23 UTC (rev 1343) +++ trunk/epydoc/src/epydoc/test/epytext.doctest 2006-09-02 01:40:35 UTC (rev 1344) @@ -9,16 +9,15 @@ >>> import re >>> def testparse(s): ... # this strips off the <epytext>...</epytext> - ... out = ''.join([n.toxml() for n in - ... epytext.parse(s).childNodes[0].childNodes]) + ... out = ''.join([str(n) for n in + ... epytext.parse(s).children]) ... # This is basically word-wrapping: ... out = re.sub(r'((</\w+>)+)', r'\1\n', out).rstrip() ... out = re.sub(r'(?m)^(.{50,70}>)(.)', r'\1\n\2', out).rstrip() ... return out >>> def checkparse(s, expect): ... # this strips off the <epytext>...</epytext> - ... got = ''.join([n.toxml() for n in - ... epytext.parse(s).childNodes[0].childNodes]) + ... got = ''.join([str(n) for n in epytext.parse(s).children]) ... if got != expect: ... raise ValueError('mismatch: %r %r' % (expect, got)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-02 01:23:25
|
Revision: 1343 http://svn.sourceforge.net/epydoc/?rev=1343&view=rev Author: edloper Date: 2006-09-01 18:23:23 -0700 (Fri, 01 Sep 2006) Log Message: ----------- - Optimizations to make parsing rst a little faster: - Reuse docutils 'settings' objects, rather than re-creating them every time we translate a docstring to html or latex - Replace the reporter with one that ignores all debug statements. (Docutils isn't very fast about processing its own debug statements.) 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-09-02 00:54:33 UTC (rev 1342) +++ trunk/epydoc/src/epydoc/markup/restructuredtext.py 2006-09-02 01:23:23 UTC (rev 1343) @@ -132,6 +132,12 @@ 'warning_stream':None}) return ParsedRstDocstring(writer.document) +class OptimizedReporter(docutils.utils.Reporter): + """A reporter that ignores all debug messages. This is used to + shave a couple seconds off of epydoc's run time, since docutils + isn't very fast about processing its own debug messages.""" + def debug(self, *args, **kwargs): pass + class ParsedRstDocstring(ParsedDocstring): """ An encoded version of a ReStructuredText docstring. The contents @@ -150,7 +156,7 @@ # The default document reporter and transformer are not # pickle-able; so replace them with stubs that are. - document.reporter = docutils.utils.Reporter( + document.reporter = OptimizedReporter( document.reporter.source, 'SEVERE', 'SEVERE', '') document.transformer = docutils.transforms.Transformer(document) @@ -460,10 +466,13 @@ return translator.head_prefix class _EpydocLaTeXTranslator(LaTeXTranslator): + settings = None def __init__(self, document, docstring_linker): # Set the document's settings. - settings = OptionParser([LaTeXWriter()]).get_default_values() - document.settings = settings + if self.settings is None: + settings = OptionParser([LaTeXWriter()]).get_default_values() + self.__class__.settings = settings + document.settings = self.settings LaTeXTranslator.__init__(self, document) self._linker = docstring_linker @@ -495,6 +504,7 @@ raise SkipNode() class _EpydocHTMLTranslator(HTMLTranslator): + settings = None def __init__(self, document, docstring_linker, directory, docindex, context): self._linker = docstring_linker @@ -503,8 +513,10 @@ self._context = context # Set the document's settings. - settings = OptionParser([HTMLWriter()]).get_default_values() - document.settings = settings + if self.settings is None: + settings = OptionParser([HTMLWriter()]).get_default_values() + self.__class__.settings = settings + document.settings = self.settings # Call the parent constructor. HTMLTranslator.__init__(self, document) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-02 00:54:37
|
Revision: 1342 http://svn.sourceforge.net/epydoc/?rev=1342&view=rev Author: edloper Date: 2006-09-01 17:54:33 -0700 (Fri, 01 Sep 2006) Log Message: ----------- - Added a cache to HTMLWriter.url() 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-09-02 00:53:39 UTC (rev 1341) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2006-09-02 00:54:33 UTC (rev 1342) @@ -886,8 +886,7 @@ the top-level list is a class with no (documented) bases; and under each class is listed all of its subclasses. Note that in the case of multiple inheritance, a class may appear - multiple times. This is used by L{write_trees} to write - the class hierarchy. + multiple times. @todo: For multiple inheritance, don't repeat subclasses the second time a class is mentioned; instead, link to the @@ -2906,11 +2905,23 @@ ''') # \------------------------------------------------------------/ + _url_cache = {} def url(self, obj): """ Return the URL for the given object, which can be a C{VariableDoc}, a C{ValueDoc}, or a C{DottedName}. """ + cached_url = self._url_cache.get(id(obj)) + if cached_url is not None: + return cached_url + else: + url = self._url_cache[id(obj)] = self._url(obj) + return url + + def _url(self, obj): + """ + Internal helper for L{url}. + """ # Module: <canonical_name>-module.html if isinstance(obj, ModuleDoc): if obj not in self.module_set: return None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-02 00:53:42
|
Revision: 1341 http://svn.sourceforge.net/epydoc/?rev=1341&view=rev Author: edloper Date: 2006-09-01 17:53:39 -0700 (Fri, 01 Sep 2006) Log Message: ----------- - Changed .py-line and .py-lineno to not require "span" tags. (I plan to change <span>..</span> to <tt>..</tt> in colorized html source, to make the files slightly smaller.) 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-09-02 00:52:49 UTC (rev 1340) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2006-09-02 00:53:39 UTC (rev 1341) @@ -253,9 +253,9 @@ color: #000000; } pre.py-src { border: 2px solid #000000; background: #f0f0f0; color: #000000; } -span.py-line { border-left: 2px solid #000000; +.py-line { border-left: 2px solid #000000; margin-left: .2em; padding-left: .4em; } -span.py-lineno { font-style: italic; font-size: 90%; +.py-lineno { font-style: italic; font-size: 90%; padding-left: .5em; } a.py-toggle { text-decoration: none; } div.py-highlight-hdr { border-top: 2px solid #000000; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-02 00:52:52
|
Revision: 1340 http://svn.sourceforge.net/epydoc/?rev=1340&view=rev Author: edloper Date: 2006-09-01 17:52:49 -0700 (Fri, 01 Sep 2006) Log Message: ----------- - Minor docstring fixes - Changed graph title for UML class diagrams to use the class's name, not the entire pprinted repr of the classdoc. 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-09-02 00:51:36 UTC (rev 1339) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2006-09-02 00:52:49 UTC (rev 1340) @@ -90,18 +90,18 @@ self.nodes = [] """A list of the nodes that are present in the graph. - :type: `list` of `DotGraphNode`""" + :type: ``list`` of `DotGraphNode`""" self.edges = [] """A list of the edges that are present in the graph. - :type: `list` of `DotGraphEdge`""" + :type: ``list`` of `DotGraphEdge`""" self.body = body """A string that should be included as-is in the body of the graph. - :type: `str`""" + :type: ``str``""" self.node_defaults = node_defaults or self.DEFAULT_NODE_DEFAULTS """Default attribute values for nodes.""" @@ -401,7 +401,7 @@ names will be contextualized to this context. `collapsed` : ``bool`` If true, then display this node as a simple box. - `bgcolor` : ``str`` + `bgcolor` : ```str``` The background color for this node. `options` : ``dict`` A set of options used to control how the node should @@ -858,9 +858,9 @@ """ :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 + - ``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. @@ -1109,7 +1109,7 @@ edge['constraint'] = 'False' # Construct the graph. - graph = DotGraph('UML class diagram for %s' % class_doc, + graph = DotGraph('UML class diagram for %s' % class_doc.canonical_name, body='ranksep=.2\n;nodesep=.3\n') graph.nodes = nodes.values() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-02 00:51:40
|
Revision: 1339 http://svn.sourceforge.net/epydoc/?rev=1339&view=rev Author: edloper Date: 2006-09-01 17:51:36 -0700 (Fri, 01 Sep 2006) Log Message: ----------- - Fixed typo in comment Modified Paths: -------------- trunk/epydoc/src/epydoc/docbuilder.py Modified: trunk/epydoc/src/epydoc/docbuilder.py =================================================================== --- trunk/epydoc/src/epydoc/docbuilder.py 2006-09-02 00:50:32 UTC (rev 1338) +++ trunk/epydoc/src/epydoc/docbuilder.py 2006-09-02 00:51:36 UTC (rev 1339) @@ -992,7 +992,7 @@ # Update val_doc's canonical name, if appropriate. if (val_doc not in _name_scores and val_doc.canonical_name is not UNKNOWN): - # If this is the fist time we've seen val_doc, and it + # If this is the first time we've seen val_doc, and it # already has a name, then don't change that name. _name_scores[val_doc] = sys.maxint name = val_doc.canonical_name This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-09-02 00:50:37
|
Revision: 1338 http://svn.sourceforge.net/epydoc/?rev=1338&view=rev Author: edloper Date: 2006-09-01 17:50:32 -0700 (Fri, 01 Sep 2006) Log Message: ----------- - Fixed SF bug [ 1550509 ] cli.py: DOT_PATH should be DOT_COMAND - Rewrote the code for --profile-epydoc. It now uses the hotshot profiler instead of proflie.py. Modified Paths: -------------- trunk/epydoc/src/epydoc/cli.py Modified: trunk/epydoc/src/epydoc/cli.py =================================================================== --- trunk/epydoc/src/epydoc/cli.py 2006-08-30 01:52:10 UTC (rev 1337) +++ trunk/epydoc/src/epydoc/cli.py 2006-09-02 00:50:32 UTC (rev 1338) @@ -77,6 +77,7 @@ GRAPH_TYPES = ('classtree', 'callgraph', 'umlclasstree') ACTIONS = ('html', 'text', 'latex', 'dvi', 'ps', 'pdf', 'check') DEFAULT_DOCFORMAT = 'epytext' +PROFILER = 'hotshot' #: Which profiler to use: 'hotshot' or 'profile' ###################################################################### #{ Argument & Config File Parsing @@ -185,12 +186,12 @@ options_group.add_option( # --introspect-only "--introspect-only", action="store_false", dest="parse", help="Get all information from introspecting (don't parse)") - if epydoc.DEBUG: - # this option is for developers, not users. - options_group.add_option( - "--profile-epydoc", action="store_true", dest="profile", - help="Run the profiler. Output will be written to profile.out") + # this option is for developers, not users. options_group.add_option( + "--profile-epydoc", action="store_true", dest="profile", + help=("Run the hotshot profiler on epydoc itself. Output " + "will be written to profile.out.")) + options_group.add_option( "--dotpath", dest="dotpath", metavar='PATH', help="The path to the Graphviz 'dot' executable.") options_group.add_option( @@ -458,7 +459,7 @@ # Set the dot path if options.dotpath: from epydoc.docwriter import dotgraph - dotgraph.DOT_PATH = options.dotpath + dotgraph.DOT_COMMAND = options.dotpath # Set the default graph font & size if options.graph_font: @@ -700,42 +701,48 @@ print >>sys.stderr, 'Use --debug to see trace information.' def _profile(): - try: from profile import Profile - except ImportError: - print >>sys.stderr, "Could not import profile module!" + # Hotshot profiler. + if PROFILER == 'hotshot': + try: import hotshot, hotshot.stats + except ImportError: + print >>sys.stderr, "Could not import profile module!" + return + try: + prof = hotshot.Profile('hotshot.out') + prof = prof.runctx('main(*parse_arguments())', globals(), {}) + except SystemExit: + pass + prof.close() + # Convert profile.hotshot -> profile.out + print 'Consolidating hotshot profiling info...' + hotshot.stats.load('hotshot.out').dump_stats('profile.out') + + # Standard 'profile' profiler. + elif PROFILER == 'profile': + try: from profile import Profile + except ImportError: + print >>sys.stderr, "Could not import profile module!" + return + + # There was a bug in Python 2.4's profiler. Check if it's + # present, and if so, fix it. (Bug was fixed in 2.4maint: + # <http://mail.python.org/pipermail/python-checkins/ + # 2005-September/047099.html>) + if (Profile.dispatch['c_exception'] is + Profile.trace_dispatch_exception.im_func): + trace_dispatch_return = Profile.trace_dispatch_return.im_func + Profile.dispatch['c_exception'] = trace_dispatch_return + try: + prof = Profile() + prof = prof.runctx('main(*parse_arguments())', globals(), {}) + except SystemExit: + pass + prof.dump_stats('profile.out') + + else: + print >>sys.stderr, 'Unknown profiler %s' % PROFILER return - # There was a bug in Python 2.4's profiler. Check if it's - # present, and if so, fix it. (Bug was fixed in 2.4maint: - # <http://mail.python.org/pipermail/python-checkins/ - # 2005-September/047099.html>) - if (Profile.dispatch['c_exception'] is - Profile.trace_dispatch_exception.im_func): - trace_dispatch_return = Profile.trace_dispatch_return.im_func - Profile.dispatch['c_exception'] = trace_dispatch_return - try: - prof = Profile() - prof = prof.runctx('main(*parse_arguments())', globals(), {}) - except SystemExit: - pass - prof.dump_stats('profile.out') - return - - # Use the pstats statistical browser. This is made unnecessarily - # difficult because the whole browser is wrapped in an - # if __name__=='__main__' clause. - try: import pstats - except ImportError: - log.error("Could not import pstats -- skipping browser") - try: - pstats_pyfile = os.path.splitext(pstats.__file__)[0]+'.py' - sys.argv = ['pstats.py', 'profile.out'] - print - execfile(pstats_pyfile, {'__name__':'__main__'}) - except: - print 'Could not run the pstats browser' - print 'Profiling output is in "profile.out"' - ###################################################################### #{ Logging ###################################################################### This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-08-30 01:52:13
|
Revision: 1337 Author: edloper Date: 2006-08-29 18:52:10 -0700 (Tue, 29 Aug 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1337&view=rev Log Message: ----------- - Added tools directory & custom rst2html script. Added Paths: ----------- trunk/epydoc/src/tools/ trunk/epydoc/src/tools/rst2html.py Added: trunk/epydoc/src/tools/rst2html.py =================================================================== --- trunk/epydoc/src/tools/rst2html.py (rev 0) +++ trunk/epydoc/src/tools/rst2html.py 2006-08-30 01:52:10 UTC (rev 1337) @@ -0,0 +1,40 @@ +#!/usr/bin/python + +r""" +A customized driver for converting docutils reStructuredText documents +into HTML. This is used to generated HTML versions of the regression +files, for the webpage. +""" + +# Docutils imports +from docutils.core import publish_cmdline, default_description +from docutils.writers.html4css1 import HTMLTranslator, Writer as HTMLWriter +import docutils.nodes + +# Epydoc imports. Make sure path contains the 'right' epydoc. +import sys +sys.path.insert(0, '../') +from epydoc.markup.doctest import doctest_to_html + +class CustomizedHTMLWriter(HTMLWriter): + settings_defaults = (HTMLWriter.settings_defaults or {}).copy() + settings_defaults.update({ + 'stylesheet': 'doctest.css', + 'stylesheet_path': None, + 'output_encoding': 'ascii', + 'output_encoding_error_handler': 'xmlcharrefreplace', + }) + + def __init__(self): + HTMLWriter.__init__(self) + self.translator_class = CustomizedHTMLTranslator + +class CustomizedHTMLTranslator(HTMLTranslator): + def visit_doctest_block(self, node): + self.body.append(doctest_to_html(str(node[0]))) + raise docutils.nodes.SkipNode + +description = ('Generates HTML documents from reStructuredText ' + 'documents. ' + default_description) +writer = CustomizedHTMLWriter() +docutils.core.publish_cmdline(writer=writer, description=description) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2006-08-29 22:20:31
|
Revision: 1336 Author: edloper Date: 2006-08-29 15:20:29 -0700 (Tue, 29 Aug 2006) ViewCVS: http://svn.sourceforge.net/epydoc/?rev=1336&view=rev Log Message: ----------- - Addded 'feedback' section Modified Paths: -------------- trunk/epydoc/doc/index.html Modified: trunk/epydoc/doc/index.html =================================================================== --- trunk/epydoc/doc/index.html 2006-08-29 22:14:11 UTC (rev 1335) +++ trunk/epydoc/doc/index.html 2006-08-29 22:20:29 UTC (rev 1336) @@ -69,6 +69,20 @@ </div> +<!-- ================= Documentation ================= --> +<div class="box"> +<h2 class="box-title">Feedback</h2> +<ul> + <li> <a + href="http://sourceforge.net/tracker/?func=add&group_id=32455&atid=405618">Report a bug</a> </li> + <li> <a + href="http://sourceforge.net/tracker/?func=add&group_id=32455&atid=405621">Suggest + a feature</a> </li> + +</ul> + +</div> + <!-- NEXT COLUMN --> </td><td width="50%" class="transparent"> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |