epydoc-commits Mailing List for Python API documentation generation tool (Page 14)
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: <dva...@us...> - 2007-02-14 00:34:02
|
Revision: 1487 http://svn.sourceforge.net/epydoc/?rev=1487&view=rev Author: dvarrazzo Date: 2007-02-13 16:34:00 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - profile.out to be ignored by svn. Property Changed: ---------------- trunk/epydoc/ Property changes on: trunk/epydoc ___________________________________________________________________ Name: svn:ignore - .*.up2date api epydoc.notes etc examples html latex lists.txt profile.stdlib stdlib webpage + .*.up2date api epydoc.notes etc examples html latex lists.txt profile.stdlib stdlib webpage profile.out This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-14 00:29:43
|
Revision: 1486 http://svn.sourceforge.net/epydoc/?rev=1486&view=rev Author: edloper Date: 2007-02-13 16:29:40 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - If we introspect a file or module, and don't have a canonical name for it when we're done, then assign it one. Modified Paths: -------------- trunk/epydoc/src/epydoc/docbuilder.py Modified: trunk/epydoc/src/epydoc/docbuilder.py =================================================================== --- trunk/epydoc/src/epydoc/docbuilder.py 2007-02-14 00:27:58 UTC (rev 1485) +++ trunk/epydoc/src/epydoc/docbuilder.py 2007-02-14 00:29:40 UTC (rev 1486) @@ -396,7 +396,8 @@ def _get_docs_from_pyname(name, options, progress_estimator, supress_warnings=False): progress_estimator.complete += 1 - log.progress(progress_estimator.progress(), name) + if options.must_introspect(name) or options.must_parse(name): + log.progress(progress_estimator.progress(), name) introspect_doc = parse_doc = None introspect_error = parse_error = None @@ -432,6 +433,8 @@ if options.introspect: try: introspect_doc = introspect_docs(filename=filename, is_script=True) + if introspect_doc.canonical_name is UNKNOWN: + introspect_doc.canonical_name = munge_script_name(filename) except ImportError, e: introspect_error = str(e) if options.parse: @@ -471,8 +474,9 @@ modulename = DottedName(parent_docs[0].canonical_name, modulename) elif parent_docs[1]: modulename = DottedName(parent_docs[1].canonical_name, modulename) - log.progress(progress_estimator.progress(), - '%s (%s)' % (modulename, filename)) + if options.must_introspect(modulename) or options.must_parse(modulename): + log.progress(progress_estimator.progress(), + '%s (%s)' % (modulename, filename)) progress_estimator.complete += 1 # Normalize the filename. @@ -492,6 +496,8 @@ try: introspect_doc = introspect_docs( filename=filename, context=parent_docs[0]) + if introspect_doc.canonical_name is UNKNOWN: + introspect_doc.canonical_name = modulename except ImportError, e: introspect_error = str(e) if src_file_available and options.must_parse(modulename): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-02-14 00:28:00
|
Revision: 1485 http://svn.sourceforge.net/epydoc/?rev=1485&view=rev Author: dvarrazzo Date: 2007-02-13 16:27:58 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - If the callgraph is available, show it in the summary too. Added a cache to avoid running graphviz twice on the same callgraph. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py trunk/epydoc/src/epydoc/docwriter/html.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-02-14 00:24:22 UTC (rev 1484) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-02-14 00:27:58 UTC (rev 1485) @@ -1502,6 +1502,9 @@ under which the exception specified by C{exc} is raised. @type: C{list}""" #} end of "information extracted from docstrings" group + callgraph_uid = None + """@ivar: L{DotGraph}.uid of the call graph for the function. + @type: C{str}""" def is_detailed(self): if super(RoutineDoc, self).is_detailed(): Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-14 00:24:22 UTC (rev 1484) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-14 00:27:58 UTC (rev 1485) @@ -349,6 +349,10 @@ self._graph_types = kwargs.get('graphs', ()) or () """Graphs that we should include in our output.""" + self._callgraph_cache = {} + """Map the callgraph L{uid<DotGraph.uid>} to their HTML + representation.""" + # For use with select_variables(): if self._show_private: self._public_filter = None @@ -1512,22 +1516,75 @@ image_file = os.path.join(self._directory, image_url) return graph.to_html(image_file, image_url) - def render_callgraph(self, callgraph): - graph_html = self.render_graph(callgraph, css='graph-with-title') - if graph_html == '': return '' - return ('<div style="display:none" id="%s-div"><center>\n' - '<table border="0" cellpadding="0" cellspacing="0">\n' - ' <tr><td>%s</td></tr>\n' - ' <tr><th>Call Graph</th></tr>\n' - '</table><br />\n</center></div>\n' % - (callgraph.uid, graph_html)) + RE_CALLGRAPH_ID = re.compile(r"""["'](.+-div)['"]""") + + def render_callgraph(self, callgraph, token=""): + """Render the HTML chunk of a callgraph. - def callgraph_link(self, callgraph): + If C{callgraph} is a string, use the L{_callgraph_cache} to return + a pre-rendered HTML chunk. This mostly avoids to run C{dot} twice for + the same callgraph. Else, run the graph and store its HTML output in + the cache. + + @param callgraph: The graph to render or its L{uid<DotGraph.uid>}. + @type callgraph: L{DotGraph} or C{str} + @param token: A string that can be used to make the C{<div>} id + unambiguous, if the callgraph is used more than once in a page. + @type token: C{str} + @return: The HTML representation of the graph. + @rtype: C{str} + """ + if callgraph is None: return "" + + if isinstance(callgraph, basestring): + uid = callgraph + rv = self._callgraph_cache.get(callgraph, "") + + else: + uid = callgraph.uid + graph_html = self.render_graph(callgraph, css='graph-with-title') + if graph_html == '': + rv = "" + else: + rv = ('<div style="display:none" id="%%s-div"><center>\n' + '<table border="0" cellpadding="0" cellspacing="0">\n' + ' <tr><td>%s</td></tr>\n' + ' <tr><th>Call Graph</th></tr>\n' + '</table><br />\n</center></div>\n' % graph_html) + + # Store in the cache the complete HTML chunk without the + # div id, which may be made unambiguous by the token + self._callgraph_cache[uid] = rv + + # Mangle with the graph + if rv: rv = rv % (uid + token) + return rv + + def callgraph_link(self, callgraph, token=""): + """Render the HTML chunk of a callgraph link. + + The link can toggles the visibility of the callgraph rendered using + L{render_callgraph} with matching parameters. + + @param callgraph: The graph to render or its L{uid<DotGraph.uid>}. + @type callgraph: L{DotGraph} or C{str} + @param token: A string that can be used to make the C{<div>} id + unambiguous, if the callgraph is used more than once in a page. + @type token: C{str} + @return: The HTML representation of the graph link. + @rtype: C{str} + """ # Use class=codelink, to match style w/ the source code link. if callgraph is None: return '' + + if isinstance(callgraph, basestring): + uid = callgraph + else: + uid = callgraph.uid + return ('<br /><span class="codelink"><a href="javascript:void(0);" ' 'onclick="toggleCallGraph(\'%s-div\');return false;">' - 'call graph</a></span> ' % callgraph.uid) + 'call graph</a></span> ' % (uid + token)) #//////////////////////////////////////////////////////////// #{ 2.11. Images @@ -1917,8 +1974,9 @@ @param container: The API documentation for the class or module whose summary table we're writing. """ - link = None # link to the source code - + pysrc_link = None + callgraph = None + # If it's a private variable, then mark its <tr>. if var_doc.is_public: tr_class = '' else: tr_class = ' class="private"' @@ -1928,7 +1986,18 @@ if isinstance(var_doc.value, RoutineDoc): typ = self.return_type(var_doc, indent=6) description = self.function_signature(var_doc, True, True) - link = self.pysrc_link(var_doc.value) + pysrc_link = self.pysrc_link(var_doc.value) + + # Perpare the call-graph, if requested + if 'callgraph' in self._graph_types: + linker = _HTMLDocstringLinker(self, var_doc.value) + callgraph = call_graph([var_doc.value], self.docindex, + linker, var_doc, add_callers=True, + add_callees=True) + if callgraph and callgraph.nodes: + var_doc.value.callgraph_uid = callgraph.uid + else: + callgraph = None else: typ = self.type_descr(var_doc, indent=6) description = self.summary_name(var_doc, link_name=True) @@ -1951,27 +2020,31 @@ self.href(var_doc.container) + ")</em>") # Write the summary line. - self._write_summary_line(out, typ, description, tr_class, link) + self._write_summary_line(out, typ, description, tr_class, pysrc_link, + callgraph) _write_summary_line = compile_template( - """ - _write_summary_line(self, out, typ, description, tr_class, link) - """, + "_write_summary_line(self, out, typ, description, tr_class, " + "pysrc_link, callgraph)", # /------------------------- Template -------------------------\ ''' <tr$tr_class$> <td width="15%" align="right" valign="top" class="summary"> <span class="summary-type">$typ or " "$</span> </td><td class="summary"> - >>> if link is not None: + >>> if pysrc_link is not None or callgraph is not None: <table width="100%" cellpadding="0" cellspacing="0" border="0"> <tr> <td>$description$</td> - <td align="right" valign="top">$link$</td> + <td align="right" valign="top"> + $pysrc_link$ + $self.callgraph_link(callgraph, token='-summary')$ + </td> </tr> </table> + $self.render_callgraph(callgraph, token='-summary')$ >>> #endif - >>> if link is None: + >>> if pysrc_link is None and callgraph is None: $description$ >>> #endif </td> @@ -2025,17 +2098,9 @@ for n in arg_names]) rhs = self.docstring_to_html(arg_descr, var_doc.value, 10) arg_descrs.append( (lhs, rhs) ) - # Perpare the call-graph, if requested - if 'callgraph' in self._graph_types: - linker = _HTMLDocstringLinker(self, var_doc.value) - callgraph = call_graph([var_doc.value], self.docindex, - linker, var_doc, add_callers=True, - add_callees=True) - if callgraph is not None and len(callgraph.nodes) == 0: - callgraph = None - else: - callgraph = None - self.write_function_details_entry(out, var_doc, descr, callgraph, + + self.write_function_details_entry(out, var_doc, descr, + var_doc.value.callgraph_uid, rtype, rdescr, arg_descrs, div_class) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-02-14 00:24:24
|
Revision: 1484 http://svn.sourceforge.net/epydoc/?rev=1484&view=rev Author: dvarrazzo Date: 2007-02-13 16:24:22 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Tag fixed. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/dotgraph.py Modified: trunk/epydoc/src/epydoc/docwriter/dotgraph.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2007-02-13 22:39:34 UTC (rev 1483) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2007-02-14 00:24:22 UTC (rev 1484) @@ -1244,7 +1244,7 @@ def add_valdoc_nodes(graph, val_docs, linker, context): """ - @todo: Use different node styles for different subclasses of APIDoc + :todo: Use different node styles for different subclasses of APIDoc """ nodes = {} val_docs = sorted(val_docs, key=lambda d:d.canonical_name) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 22:39:39
|
Revision: 1483 http://svn.sourceforge.net/epydoc/?rev=1483&view=rev Author: edloper Date: 2007-02-13 14:39:34 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Added check in DocIndex._get_module_classes to make sure we don't try to access the canonical name of a value if it doesn't have one yet (since this gets called before we assign canonical names to all APIDocs). Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-02-13 22:23:50 UTC (rev 1482) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-02-13 22:39:34 UTC (rev 1483) @@ -1893,6 +1893,8 @@ val = var.value if val in (None, UNKNOWN) or val.defining_module is not doc: continue + if val.canonical_name in (None, UNKNOWN): + continue name = val.canonical_name[-1] vals = classes.get(name) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 22:23:52
|
Revision: 1482 http://svn.sourceforge.net/epydoc/?rev=1482&view=rev Author: edloper Date: 2007-02-13 14:23:50 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Fixed bug introduced by previous checkin that made epydoc fail if no --exclude options were given Modified Paths: -------------- trunk/epydoc/src/epydoc/docbuilder.py Modified: trunk/epydoc/src/epydoc/docbuilder.py =================================================================== --- trunk/epydoc/src/epydoc/docbuilder.py 2007-02-13 22:12:14 UTC (rev 1481) +++ trunk/epydoc/src/epydoc/docbuilder.py 2007-02-13 22:23:50 UTC (rev 1482) @@ -96,9 +96,9 @@ # Test for pattern syntax and compile them into pattern objects. try: self._introspect_regexp = (exclude_introspect - and re.compile(exclude_introspect)) + and re.compile(exclude_introspect) or None) self._parse_regexp = (exclude_parse - and re.compile(exclude_parse)) + and re.compile(exclude_parse) or None) except Exception, exc: log.error('Error in regular expression pattern: %s' % exc) raise This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 22:12:15
|
Revision: 1481 http://svn.sourceforge.net/epydoc/?rev=1481&view=rev Author: edloper Date: 2007-02-13 14:12:14 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Added 'frozenset' to epydoc.compat Modified Paths: -------------- trunk/epydoc/src/epydoc/compat.py Modified: trunk/epydoc/src/epydoc/compat.py =================================================================== --- trunk/epydoc/src/epydoc/compat.py 2007-02-13 22:04:45 UTC (rev 1480) +++ trunk/epydoc/src/epydoc/compat.py 2007-02-13 22:12:14 UTC (rev 1481) @@ -28,7 +28,7 @@ set except NameError: try: - from sets import Set as set + from sets import Set as set, ImmutableSet as frozenset except ImportError: pass # use fallback, in the next section. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 22:04:58
|
Revision: 1480 http://svn.sourceforge.net/epydoc/?rev=1480&view=rev Author: edloper Date: 2007-02-13 14:04:45 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Removed debug printfs Modified Paths: -------------- trunk/epydoc/src/epydoc/cli.py Modified: trunk/epydoc/src/epydoc/cli.py =================================================================== --- trunk/epydoc/src/epydoc/cli.py 2007-02-13 22:01:15 UTC (rev 1479) +++ trunk/epydoc/src/epydoc/cli.py 2007-02-13 22:04:45 UTC (rev 1480) @@ -563,8 +563,6 @@ exclude_parse = '|'.join(options.exclude_parse+options.exclude) exclude_introspect = '|'.join(options.exclude_introspect+ options.exclude) - log.warning('exclude parse', `exclude_parse`) - log.warning('exclude introspect', `exclude_introspect`) docindex = build_doc_index(names, options.introspect, options.parse, add_submodules=(options.action!='text'), exclude_introspect=exclude_introspect, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 22:01:18
|
Revision: 1479 http://svn.sourceforge.net/epydoc/?rev=1479&view=rev Author: edloper Date: 2007-02-13 14:01:15 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Fixed bug where latex writer would crash if vardoc.value was UNKNOWN. Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/latex.py Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2007-02-13 21:59:10 UTC (rev 1478) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2007-02-13 22:01:15 UTC (rev 1479) @@ -812,29 +812,21 @@ out(' & ') has_descr = var_doc.descr not in (None, UNKNOWN) has_type = var_doc.type_descr not in (None, UNKNOWN) - out('\\raggedright ') + has_value = var_doc.value is not UNKNOWN + if has_type or has_value: + out('\\raggedright ') if has_descr: out(self.docstring_to_latex(var_doc.descr, 10).strip()) - out('\n\n') - out('\\textbf{Value:} \n') - out(self._pprint_var_value(var_doc)) + if has_type or has_value: out('\n\n') + if has_value: + out('\\textbf{Value:} \n{\\tt %s}' % + var_doc.value.summary_pyval_repr().to_latex(None)) if has_type: ptype = self.docstring_to_latex(var_doc.type_descr, 12).strip() out('%s\\textit{(type=%s)}' % (' '*12, ptype)) out('&\\\\\n') out('\\cline{1-2}\n') - def _pprint_var_value(self, var_doc): - pyval_repr = var_doc.value.pyval_repr().to_latex(None) - if '\n' in pyval_repr: - return ('\\begin{alltt}\n%s\\end{alltt}' % - pyval_repr) - #plaintext_to_latex(pyval_repr, nbsp=False, breakany=True)) - else: - return '{\\tt %s}' % pyval_repr - #plaintext_to_latex(pyval_repr, nbsp=True, - #breakany=True) - def write_property_list_line(self, out, var_doc): prop_doc = var_doc.value out('\\raggedright ') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 21:59:12
|
Revision: 1478 http://svn.sourceforge.net/epydoc/?rev=1478&view=rev Author: edloper Date: 2007-02-13 13:59:10 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Added "--exclude" option, which does "--exclude-parse" and "--exclude-introspect" at the same time. It may be mixed freely with the other two exclude options. - Allow "--exclude"-type options to be repeated. E.g., "--exclude foo --exclude bar" is equivalent to "--exclude foo|bar" - Fixed bug 1658378 by changing args to ps2pdf to use "#" instead of "=". Modified Paths: -------------- trunk/epydoc/src/epydoc/cli.py Modified: trunk/epydoc/src/epydoc/cli.py =================================================================== --- trunk/epydoc/src/epydoc/cli.py 2007-02-13 20:27:31 UTC (rev 1477) +++ trunk/epydoc/src/epydoc/cli.py 2007-02-13 21:59:10 UTC (rev 1478) @@ -150,11 +150,18 @@ "--introspect-only", action="store_false", dest="parse", help="Get all information from introspecting (don't parse)") generation_group.add_option( # --exclude-introspect + "--exclude", dest="exclude", metavar="PATTERN", + action="append", + help="Exclude modules whose dotted name matches " + "the regular expression PATTERN") + generation_group.add_option( # --exclude-introspect "--exclude-introspect", dest="exclude_introspect", metavar="PATTERN", + action="append", help="Exclude introspection of modules whose dotted name matches " "the regular expression PATTERN") generation_group.add_option( # --exclude-parse "--exclude-parse", dest="exclude_parse", metavar="PATTERN", + action="append", help="Exclude parsing of modules whose dotted name matches " "the regular expression PATTERN") generation_group.add_option( # --inheritance @@ -288,7 +295,9 @@ graphs=[], list_classes_separately=False, graph_font=None, graph_font_size=None, include_source_code=True, pstat_files=[], - simple_term=False, fail_on=None) + simple_term=False, fail_on=None, + exclude=[], exclude_parse=[], + exclude_introspect=[]) # Parse the arguments. options, names = optparser.parse_args() @@ -551,10 +560,15 @@ else: # Build docs for the named values. from epydoc.docbuilder import build_doc_index + exclude_parse = '|'.join(options.exclude_parse+options.exclude) + exclude_introspect = '|'.join(options.exclude_introspect+ + options.exclude) + log.warning('exclude parse', `exclude_parse`) + log.warning('exclude introspect', `exclude_introspect`) docindex = build_doc_index(names, options.introspect, options.parse, add_submodules=(options.action!='text'), - exclude_introspect=options.exclude_introspect, - exclude_parse=options.exclude_parse) + exclude_introspect=exclude_introspect, + exclude_parse=exclude_parse) if docindex is None: if log.ERROR in logger.reported_message_levels: @@ -722,9 +736,9 @@ running = 'ps2pdf' log.progress(5./steps, 'ps2pdf') run_subprocess( - 'ps2pdf -sPAPERSIZE=letter -dMaxSubsetPct=100 ' - '-dSubsetFonts=true -dCompatibilityLevel=1.2 ' - '-dEmbedAllFonts=true api.ps api.pdf') + 'ps2pdf -sPAPERSIZE#letter -dMaxSubsetPct#100 ' + '-dSubsetFonts#true -dCompatibilityLevel#1.2 ' + '-dEmbedAllFonts#true api.ps api.pdf') except RunSubprocessError, e: if running == 'latex': e.out = re.sub(r'(?sm)\A.*?!( LaTeX Error:)?', r'', e.out) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 20:27:32
|
Revision: 1477 http://svn.sourceforge.net/epydoc/?rev=1477&view=rev Author: edloper Date: 2007-02-13 12:27:31 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Removed regexp colorizer (it's been replaced by epydoc.markup.pyval_repr) 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 2007-02-13 20:26:12 UTC (rev 1476) +++ trunk/epydoc/src/epydoc/docwriter/html_colorize.py 2007-02-13 20:27:31 UTC (rev 1477) @@ -8,300 +8,20 @@ """ Functions to produce colorized HTML code for various objects. -Currently, C{colorize} defines functions to colorize regular -expressions and doctest blocks. - -@group Regular Expression Tags: *_TAG +Currently, C{html_colorize} defines functions to colorize +Python source code. """ __docformat__ = 'epytext en' -import sys, sre_parse, re, codecs -import sre_constants +import re, codecs from epydoc import log -from epydoc.util import decode_with_backslashreplace, plaintext_to_html from epydoc.util import py_src_filename from epydoc.apidoc import * +import tokenize, token, cgi, keyword +try: from cStringIO import StringIO +except: from StringIO import StringIO ###################################################################### -## Regular expression colorizer -###################################################################### - -# HTML tags for colorize_re - -RE_TAG = 're' -r'''The CSS class for colorizing regular expressions.''' - -ANY_TAG = 're-char' -r'''The CSS class for colorizing C{"."} in regexps.''' - -ESCAPE_TAG = 're-char' -r'''The CSS class for colorizing escaped characters (such as C{r"\("}) -in regexps.''' - -CATEGORY_TAG = 're-char' -r'''The CSS class for colorizing character categories (such as -C{r"\d"})) in regexps.''' - -AT_TAG = 're-char' -r'''The CSS class for colorizing character locations (such as C{"^"}) -in regexps.''' - -BRANCH_TAG = 're-op' -r'''The CSS class for colorizing C{"|"} in regexps.''' - -STAR_TAG = 're-op' -r'''The CSS class for colorizing C{"*"} and C{"*?"} in regexps.''' - -PLUS_TAG = 're-op' -r'''The CSS class for colorizing C{"+"} and C{"+?"} in regexps.''' - -QMRK_TAG = 're-op' -r'''The CSS class for colorizing C{"?"} and C{"??"} in regexps.''' - -RNG_TAG = 're-op' -r'''The CSS class for colorizing repeat ranges (such as C{"a{3,8}"}) in -regexps.''' - -PAREN_TAG = 're-group' -r'''The CSS class for colorizing parenthases in regexps.''' - -CHOICE_TAG = 're-group' -r'''The CSS class for colorizing character choice expressions (such as -C{"[abc]"}) in regexps.''' - -ASSERT_TAG = 're-group' -r'''The CSS class for colorizing assertions (such as C{"(?=abc)"}) in -regexps.''' - -REF_TAG = 're-ref' -r'''The CSS class for colorizing references (such as C{r"\1"}) in -regexps.''' - -def colorize_re(regexp): - r""" - @return: The HTML code for a colorized version of the pattern for - the given SRE regular expression. If C{colorize_re} can't - figure out how to colorize the regexp, then it will simply return - the (uncolorized) pattern, with C{'&'}, C{'<'}, and C{'>'} - escaped as HTML entities. The colorized expression includes - spans with the following css classes: - - X{re}: The entire regular expression. - - X{re-char}: Special characters (such as C{'.'}, C{'\('}), - character categories (such as C{'\w'}), and locations - (such as C{'\b'}). - - X{re-op}: Operators (such as C{'*'} and C{'|'}). - - X{re-group}: Grouping constructs (such as C{'(...)'}). - - X{re-ref} References (such as C{'\1'}) - @rtype: C{string} - @param regexp: The regular expression to colorize. - @type regexp: C{SRE_Pattern} or C{string} - @raise sre_constants.error: If regexp is not a valid regular - expression. - """ - if isinstance(regexp, str): - pat = decode_with_backslashreplace(regexp) - tree = sre_parse.parse(pat) - - elif isinstance(regexp, unicode): - tree = sre_parse.parse(regexp) - - elif hasattr(regexp, 'pattern') and hasattr(regexp, 'flags'): - if isinstance(regexp.pattern, str): - pat = decode_with_backslashreplace(regexp.pattern) - tree = sre_parse.parse(pat, regexp.flags) - - elif isinstance(regexp.pattern, unicode): - tree = sre_parse.parse(regexp.pattern, regexp.flags) - - else: - raise TypeError("Bad regexp object -- pattern is not a string") - else: - raise TypeError("Expected a regexp or a string") - - return ('<span class="%s">%s</span>' % - (RE_TAG, _colorize_re(tree, 1))) - -def _colorize_re(tree, noparen=0): - """ - Recursively descend the given regexp parse tree to produce the - HTML code for a colorized version of the regexp. - - @param tree: The regexp parse tree for the regexp that should be - colorized. - @type tree: L{sre_parse.SubPattern} - @param noparen: If true, then don't include parenthases around the - expression in C{tree}, even if it contains multiple elements. - @type noparen: C{boolean} - @return: The HTML code for a colorized version of C{tree} - @rtype: C{string} - """ - result = [] - out = result.append - - if len(tree) > 1 and not noparen: - out('<span class="%s">(</span>' % PAREN_TAG) - for elt in tree: - op = elt[0] - args = elt[1] - - if op == sre_constants.LITERAL: - c = unichr(args) - if c == '\t': out(r'<span class="%s">\t</span>' % ESCAPE_TAG) - elif c == '\n': out(r'<span class="%s">\n</span>' % ESCAPE_TAG) - elif c == '\r': out(r'<span class="%s">\r</span>' % ESCAPE_TAG) - elif c == '\f': out(r'<span class="%s">\f</span>' % ESCAPE_TAG) - elif c == '\v': out(r'<span class="%s">\v</span>' % ESCAPE_TAG) - elif ord(c)<32 or ord(c)>=127: - if c < 256: template = r'<span class="%s">\x%02x</span>' - else: template = r'<span class="%s">\u%04x</span>' - out(template % (ESCAPE_TAG,ord(c))) - elif c in '.^$\\*+?{}[]|()': - out(r'<span class="%s">\%c</span>' % (ESCAPE_TAG, c)) - else: out(plaintext_to_html(unichr(args))) - continue - - elif op == sre_constants.ANY: - out('<span class="%s">.</span>' % ANY_TAG) - - elif op == sre_constants.BRANCH: - if args[0] is not None: - raise ValueError('Branch expected None arg but got %s' - % args[0]) - VBAR = '<span class="%s">|</span>' % BRANCH_TAG - out(VBAR.join([_colorize_re(item,1) for item in args[1]])) - - elif op == sre_constants.IN: - if (len(args) == 1 and args[0][0] == sre_constants.CATEGORY): - out(_colorize_re(args)) - else: - out('<span class="%s">[</span>' % CHOICE_TAG) - out(_colorize_re(args, 1)) - out('<span class="%s">]</span>' % CHOICE_TAG) - - elif op == sre_constants.CATEGORY: - out('<span class="%s">' % CATEGORY_TAG) - if args == sre_constants.CATEGORY_DIGIT: out(r'\d') - elif args == sre_constants.CATEGORY_NOT_DIGIT: out(r'\D') - elif args == sre_constants.CATEGORY_SPACE: out(r'\s') - elif args == sre_constants.CATEGORY_NOT_SPACE: out(r'\S') - elif args == sre_constants.CATEGORY_WORD: out(r'\w') - elif args == sre_constants.CATEGORY_NOT_WORD: out(r'\W') - else: raise ValueError('Unknown category %s' % args) - out('</span>') - - elif op == sre_constants.AT: - out('<span class="%s">' % AT_TAG) - if args == sre_constants.AT_BEGINNING_STRING: out(r'\A') - elif args == sre_constants.AT_BEGINNING: out(r'^') - elif args == sre_constants.AT_END: out(r'$') - elif args == sre_constants.AT_BOUNDARY: out(r'\b') - elif args == sre_constants.AT_NON_BOUNDARY: out(r'\B') - elif args == sre_constants.AT_END_STRING: out(r'\Z') - else: raise ValueError('Unknown position %s' % args) - out('</span>') - - elif op == sre_constants.MAX_REPEAT: - min = args[0] - max = args[1] - if max == sre_constants.MAXREPEAT: - if min == 0: - out(_colorize_re(args[2])) - out('<span class="%s">*</span>' % STAR_TAG) - elif min == 1: - out(_colorize_re(args[2])) - out('<span class="%s">+</span>' % PLUS_TAG) - else: - out(_colorize_re(args[2])) - out('<span class="%s">{%d,}</span>' % (RNG_TAG, min)) - elif min == 0: - if max == 1: - out(_colorize_re(args[2])) - out('<span class="%s">?</span>' % QMRK_TAG) - else: - out(_colorize_re(args[2])) - out('<span class="%s">{,%d}</span>' % (RNG_TAG, max)) - elif min == max: - out(_colorize_re(args[2])) - out('<span class="%s">{%d}</span>' % (RNG_TAG, max)) - else: - out(_colorize_re(args[2])) - out('<span class="%s">{%d,%d}</span>' % (RNG_TAG, min, max)) - - elif op == sre_constants.MIN_REPEAT: - min = args[0] - max = args[1] - if max == sre_constants.MAXREPEAT: - if min == 0: - out(_colorize_re(args[2])) - out('<span class="%s">*?</span>' % STAR_TAG) - elif min == 1: - out(_colorize_re(args[2])) - out('<span class="%s">+?</span>' % PLUS_TAG) - else: - out(_colorize_re(args[2])) - out('<span class="%s">{%d,}?</span>' % (RNG_TAG, min)) - elif min == 0: - if max == 1: - out(_colorize_re(args[2])) - out('<span class="%s">??</span>' % QMRK_TAG) - else: - out(_colorize_re(args[2])) - out('<span class="%s">{,%d}?</span>' % (RNG_TAG, max)) - elif min == max: - out(_colorize_re(args[2])) - out('<span class="%s">{%d}?</span>' % (RNG_TAG, max)) - else: - out(_colorize_re(args[2])) - out('<span class="%s">{%d,%d}?</span>'%(RNG_TAG, min, max)) - - elif op == sre_constants.SUBPATTERN: - if args[0] is None: - out('<span class="%s">(?:</span>' % PAREN_TAG) - elif isinstance(args[0], (int, long)): - # This is cheating: - out('<span class="%s">(</span>' % PAREN_TAG) - else: - out('<span class="%s">(?P<</span>' % PAREN_TAG) - out('<span class="%s">%s</span>' % - (REF_TAG, plaintext_to_html(args[0]))) - out('<span class="%s">></span>' % PAREN_TAG) - out(_colorize_re(args[1], 1)) - out('<span class="%s">)</span>' % PAREN_TAG) - - elif op == sre_constants.GROUPREF: - out('<span class="%s">\\%d</span>' % (REF_TAG, args)) - - elif op == sre_constants.RANGE: - start = _colorize_re( ((sre_constants.LITERAL, args[0]),) ) - end = _colorize_re( ((sre_constants.LITERAL, args[1]),) ) - out('%s<span class="%s">-</span>%s' % (start, CHOICE_TAG, end)) - - elif op == sre_constants.NEGATE: - out('<span class="%s">^</span>' % CHOICE_TAG) - - elif op == sre_constants.ASSERT: - if args[0]: out('<span class="%s">(?=</span>' % ASSERT_TAG) - else: out('<span class="%s">(?<=</span>' % ASSERT_TAG) - out(''.join(_colorize_re(args[1], 1))) - out('<span class="%s">)</span>' % ASSERT_TAG) - - elif op == sre_constants.ASSERT_NOT: - if args[0]: out('<span class="%s">(?!</span>' % ASSERT_TAG) - else: out('<span class="%s">(?<!</span>' % ASSERT_TAG) - out(''.join(_colorize_re(args[1], 1))) - out('<span class="%s">)</span>' % ASSERT_TAG) - - elif op == sre_constants.NOT_LITERAL: - lit = _colorize_re( ((sre_constants.LITERAL, args),) ) - out('<span class="%s">[^</span>%s<span class="%s">]</span>' % - (CHOICE_TAG, lit, CHOICE_TAG)) - else: - log.error("Error colorizing regexp: unknown elt %r" % elt) - if len(tree) > 1 and not noparen: - out('<span class="%s">)</span>' % PAREN_TAG) - return u''.join(result) - -###################################################################### ## Python source colorizer ###################################################################### """ @@ -495,10 +215,6 @@ </script> ''' -import tokenize, sys, token, cgi, keyword -try: from cStringIO import StringIO -except: from StringIO import StringIO - class PythonSourceColorizer: """ A class that renders a python module's source code into HTML @@ -1152,14 +868,7 @@ else: return '%s-module.html#%s' % (self.module_name, func_name) -# if __name__=='__main__': -# s = PythonSourceColorizer('../apidoc.py', 'epydoc.apidoc').colorize() -# import codecs -# f = codecs.open('/home/edloper/public_html/color.html', 'w', 'ascii', 'xmlcharrefreplace') -# f.write(s) -# f.close() - -HDR = '''\ +_HDR = '''\ <?xml version="1.0" encoding="ascii"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd"> @@ -1173,12 +882,12 @@ <body bgcolor="white" text="black" link="blue" vlink="#204080" alink="#204080"> ''' -FOOT = '</body></html>' +_FOOT = '</body></html>' if __name__=='__main__': #s = PythonSourceColorizer('../apidoc.py', 'epydoc.apidoc').colorize() s = PythonSourceColorizer('/tmp/fo.py', 'epydoc.apidoc').colorize() #print s import codecs f = codecs.open('/home/edloper/public_html/color3.html', 'w', 'ascii', 'xmlcharrefreplace') - f.write(HDR+'<pre id="py-src-top" class="py-src">'+s+'</pre>'+FOOT) + f.write(_HDR+'<pre id="py-src-top" class="py-src">'+s+'</pre>'+_FOOT) f.close() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 20:26:14
|
Revision: 1476 http://svn.sourceforge.net/epydoc/?rev=1476&view=rev Author: edloper Date: 2007-02-13 12:26:12 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Removed unused import Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/html.py Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-13 20:22:12 UTC (rev 1475) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-13 20:26:12 UTC (rev 1476) @@ -20,7 +20,6 @@ from epydoc.apidoc import * import epydoc.docstringparser import time, epydoc, epydoc.markup, epydoc.markup.epytext -from epydoc.docwriter.html_colorize import colorize_re from epydoc.docwriter.html_colorize import PythonSourceColorizer from epydoc.docwriter import html_colorize from epydoc.docwriter.html_css import STYLESHEETS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 20:22:19
|
Revision: 1475 http://svn.sourceforge.net/epydoc/?rev=1475&view=rev Author: edloper Date: 2007-02-13 12:22:12 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Fixed bug caused by previous checkin Modified Paths: -------------- trunk/epydoc/src/epydoc/docwriter/latex.py Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2007-02-13 19:53:08 UTC (rev 1474) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2007-02-13 20:22:12 UTC (rev 1475) @@ -815,7 +815,7 @@ out('\\raggedright ') if has_descr: out(self.docstring_to_latex(var_doc.descr, 10).strip()) - if has_type or has_repr: out('\n\n') + out('\n\n') out('\\textbf{Value:} \n') out(self._pprint_var_value(var_doc)) if has_type: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 19:53:10
|
Revision: 1474 http://svn.sourceforge.net/epydoc/?rev=1474&view=rev Author: edloper Date: 2007-02-13 11:53:08 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - added "rm profile.out" to "make clean" Modified Paths: -------------- trunk/epydoc/Makefile Modified: trunk/epydoc/Makefile =================================================================== --- trunk/epydoc/Makefile 2007-02-13 19:46:05 UTC (rev 1473) +++ trunk/epydoc/Makefile 2007-02-13 19:53:08 UTC (rev 1474) @@ -74,6 +74,7 @@ $(MAKE) -C src clean rm -rf $(WEBDIR) $(HTML) $(LATEX) rm -rf .*.up2date + rm -rf profile.out ##////////////////////////////////////////////////////////////////////// ## Distributions This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 19:46:10
|
Revision: 1473 http://svn.sourceforge.net/epydoc/?rev=1473&view=rev Author: edloper Date: 2007-02-13 11:46:05 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Changed ValueDoc.pyval_repr and summary_pval_repr to return ParsedDocstring's instead of string. These ParsedDocstrings are generated by epydoc.markup.pyval_repr. Instead of returning a separate value to indicate whether there's left-over (for GenericValueDoc.is_detailed), add an 'is_complete' attribute to the parsed docstring. - Defer importing of dotgraph from epydoc.markup.epytext to avoid a circular dependency. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py trunk/epydoc/src/epydoc/docwriter/dotgraph.py trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/html_css.py trunk/epydoc/src/epydoc/docwriter/latex.py trunk/epydoc/src/epydoc/docwriter/plaintext.py trunk/epydoc/src/epydoc/markup/epytext.py trunk/epydoc/src/epydoc/markup/pyval_repr.py trunk/epydoc/src/epydoc/test/docbuilder.doctest trunk/epydoc/src/epydoc/test/pyval_repr.doctest Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-02-13 19:46:05 UTC (rev 1473) @@ -44,6 +44,7 @@ import __builtin__ from epydoc.compat import * # Backwards compatibility from epydoc.util import decode_with_backslashreplace, py_src_filename +import epydoc.markup.pyval_repr ###################################################################### # Dotted Names @@ -726,8 +727,30 @@ the initial assignment). @type: C{unicode}""" - summary_linelen = 75 - """@cvar: The maximum length of a row to fit in a summary.""" + REPR_MAXLINES = 5 + """@cvar: The maximum number of lines of text that should be + generated by L{pyval_repr()}. If the string representation does + not fit in this number of lines, an ellpsis marker (...) will + be placed at the end of the formatted representation.""" + + REPR_LINELEN = 75 + """@cvar: The maximum number of characters for lines of text that + should be generated by L{pyval_repr()}. Any lines that exceed + this number of characters will be line-wrappped; The S{crarr} + symbol will be used to indicate that the line was wrapped.""" + + SUMMARY_REPR_LINELEN = 75 + """@cvar: The maximum number of characters for the single-line + text representation generated by L{summary_pyval_repr()}. If + the value's representation does not fit in this number of + characters, an ellipsis marker (...) will be placed at the end + of the formatted representation.""" + + REPR_MIN_SCORE = 0 + """@cvar: The minimum score that a value representation based on + L{pyval} should have in order to be used instead of L{parse_repr} + as the canonical representation for this C{ValueDoc}'s value. + @see: L{epydoc.markup.pyval_repr}""" #} end of "value representation" group #{ Context @@ -767,7 +790,8 @@ if self.canonical_name is not UNKNOWN: return '<%s %s>' % (self.__class__.__name__, self.canonical_name) else: - return '<%s %s>' % (self.__class__.__name__, self.pyval_repr()) + return '<%s %s>' % (self.__class__.__name__, + self.summary_pyval_repr().to_plaintext(None)) def __setstate__(self, state): self.__dict__ = state @@ -782,101 +806,64 @@ # as a private attribute, so we can reuse it later, since # merged objects need to share a single dictionary. if not hasattr(self, '_ValueDoc__pickle_state'): + # Make sure __pyval_repr & __summary_pyval_repr are cached: + self.pyval_repr(), self.summary_pyval_repr() + # Construct the dictionary; leave out 'pyval'. self.__pickle_state = self.__dict__.copy() self.__pickle_state['pyval'] = UNKNOWN - self.__pickle_state['_ValueDoc__pyval_repr'] = self.pyval_repr() if not isinstance(self, GenericValueDoc): assert self.__pickle_state != {} # Return the pickle state. return self.__pickle_state - UNKNOWN_REPR = "??" - """@cvar: The string representation of an unknown value.""" - - STOCK_REPR = re.compile(r"(?i)^<.+\bat\b.+[0-9a-f]+.*>$") - """Match the return of repr() for object that didn't customize it.""" - + #{ Value Representation def pyval_repr(self): - """Return a string representation of the python value. - - The string representation may include data from introspection, parsing - and is authoritative as "the best way to represent a Python value." - - @return: A nice string representation. Never C{None} nor L{UNKNOWN} - @rtype: C{str} - - @todo: String representation can be made better here. """ - if hasattr(self, '_pyval_repr'): - return self._pyval_repr + Return a formatted representation of the Python object + described by this C{ValueDoc}. This representation may + include data from introspection or parsing, and is authorative + as 'the best way to represent a Python value.' Any lines that + go beyond L{REPR_LINELEN} characters will be wrapped; and if + the representation as a whole takes more than L{REPR_MAXLINES} + lines, then it will be truncated (with an ellipsis marker). + This function will never return L{UNKNOWN} or C{None}. + + @rtype: L{ColorizedPyvalRepr} + """ + # Use self.__pyval_repr to cache the result. + if not hasattr(self, '_ValueDoc__pyval_repr'): + self.__pyval_repr = epydoc.markup.pyval_repr.colorize_pyval( + self.pyval, self.parse_repr, self.REPR_MIN_SCORE, + self.REPR_LINELEN, self.REPR_MAXLINES, linebreakok=True) + return self.__pyval_repr - rv = self._get_pyval_repr() - if rv is UNKNOWN: - rv = self.parse_repr - - elif self.STOCK_REPR.match(rv) and self.parse_repr is not UNKNOWN: - rv = self.parse_repr - - if rv is UNKNOWN: - rv = self.UNKNOWN_REPR - - assert isinstance(rv, basestring) - self._pyval_repr = rv - return rv - def summary_pyval_repr(self, max_len=None): - """Return a short version of L{pyval_repr}, fitting on a single line. - - Notice that L{GenericValueDoc.is_detailed()} uses this function to - return an answer leavling C{max_len} to the default value. So, if - a writer is to decide whether to emit a complete representation or - limit itself to the summary, it should call this function leaving - C{max_len} to its default value too, if it wants to generate consistent - results. - - @param max_len: The maximum length allowed. If None, use - L{summary_linelen} - - @return: the short representation and a boolean value stating if there - is further value to represent after such representation or not. - - @rtype: C{(str, bool)} """ - ro = self.pyval_repr() - lo = False - - # Reduce to a single line - if "\n" in ro: - ro = ro.split("\n",1)[0] - lo = True - - # Truncate a long line - if max_len is None: - max_len = self.summary_linelen - if len(ro) > max_len: - ro = ro[:max_len-3]+'...' - lo = True - - return (ro, lo) - - def _get_pyval_repr(self): + Return a single-line formatted representation of the Python + object described by this C{ValueDoc}. This representation may + include data from introspection or parsing, and is authorative + as 'the best way to summarize a Python value.' If the + representation takes more then L{SUMMARY_REPR_LINELEN} + characters, then it will be truncated (with an ellipsis + marker). This function will never return L{UNKNOWN} or + C{None}. + + @rtype: L{ColorizedPyvalRepr} """ - Return a string representation of this value based on its pyval; - or UNKNOWN if we don't succeed. This should probably eventually - be replaced by more of a safe-repr variant. - """ - if self.pyval is UNKNOWN: - if hasattr(self, '_ValueDoc__pyval_repr'): - return self.__pyval_repr # used after unpickling. - return UNKNOWN - try: - s = '%r' % (self.pyval,) - if isinstance(s, str): - s = decode_with_backslashreplace(s) - return s - except KeyboardInterrupt: raise - except: return UNKNOWN + # If max_len is specified, then do *not* cache the result. + if max_len is not None: + return epydoc.markup.pyval_repr.colorize_pyval( + self.pyval, self.parse_repr, self.REPR_MIN_SCORE, + max_len, maxlines=1, linebreakok=False) + + # Use self.__summary_pyval_repr to cache the result. + if not hasattr(self, '_ValueDoc__summary_pyval_repr'): + self.__summary_pyval_repr = epydoc.markup.pyval_repr.colorize_pyval( + self.pyval, self.parse_repr, self.REPR_MIN_SCORE, + self.SUMMARY_REPR_LINELEN, maxlines=1, linebreakok=False) + return self.__summary_pyval_repr + #} end of "value representation" group def apidoc_links(self, **filters): return [] @@ -891,7 +878,7 @@ canonical_name = None def is_detailed(self): - return self.summary_pyval_repr()[1] + return (not self.summary_pyval_repr().is_complete) class NamespaceDoc(ValueDoc): """ Modified: trunk/epydoc/src/epydoc/docwriter/dotgraph.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/docwriter/dotgraph.py 2007-02-13 19:46:05 UTC (rev 1473) @@ -694,7 +694,7 @@ if default is None: return '%s' % name else: - pyval_repr = default.summary_pyval_repr()[0] + pyval_repr = default.summary_pyval_repr().to_plaintext(None) return '%s=%s' % (name, pyval_repr) def _qualifier_cell(self, key_label, port): Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-13 19:46:05 UTC (rev 1473) @@ -19,7 +19,7 @@ import __builtin__ from epydoc.apidoc import * import epydoc.docstringparser -import time, epydoc, epydoc.markup +import time, epydoc, epydoc.markup, epydoc.markup.epytext from epydoc.docwriter.html_colorize import colorize_re from epydoc.docwriter.html_colorize import PythonSourceColorizer from epydoc.docwriter import html_colorize @@ -330,7 +330,7 @@ """Max line length for variable values""" self._variable_summary_linelen = \ - kwargs.get('variable_summary_linelength', 55) + kwargs.get('variable_summary_linelength', 65) """Max length for variable value summaries""" self._variable_tooltip_linelen = \ @@ -501,6 +501,21 @@ # For progress reporting: self._files_written = 0. + # Set the default values for ValueDoc formatted representations. + orig_valdoc_defaults = (ValueDoc.SUMMARY_REPR_LINELEN, + ValueDoc.REPR_LINELEN, + ValueDoc.REPR_MAXLINES) + ValueDoc.SUMMARY_REPR_LINELEN = self._variable_summary_linelen + ValueDoc.REPR_LINELEN = self._variable_linelen + ValueDoc.REPR_MAXLINES = self._variable_maxlines + + # Use an image for the crarr symbol. + from epydoc.markup.epytext import ParsedEpytextDocstring + orig_crarr_html = ParsedEpytextDocstring.SYMBOL_TO_HTML['crarr'] + ParsedEpytextDocstring.SYMBOL_TO_HTML['crarr'] = ( + r'<span class="variable-linewrap">' + r'<img src="crarr.png" alt="\" /></span>') + # Keep track of failed xrefs, and report them at the end. self._failed_xrefs = {} @@ -509,11 +524,6 @@ self._mkdir(directory) self._directory = directory - # Set the default value for L{ValueDoc.summary_linelen} so that - # L{ValueDoc.summary_pyval_repr()} return value is consistent with - # L{ValueDoc.is_detailed()} - ValueDoc.summary_linelen = self._variable_summary_linelen - # Write the CSS file. self._files_written += 1 log.progress(self._files_written/self._num_files, 'epydoc.css') @@ -524,7 +534,7 @@ log.progress(self._files_written/self._num_files, 'epydoc.js') self.write_javascript(directory) - # Write images. + # Write images self.write_images(directory) # Build the indices. @@ -656,6 +666,11 @@ "wrote %d files" % (self._num_files, int(self._files_written))) + # Restore defaults that we changed. + (ValueDoc.SUMMARY_REPR_LINELEN, ValueDoc.REPR_LINELEN, + ValueDoc.REPR_MAXLINES) = orig_valdoc_defaults + ParsedEpytextDocstring.SYMBOL_TO_HTML['crarr'] = orig_crarr_html + def _write(self, write_func, directory, filename, *args): # Display our progress. self._files_written += 1 @@ -1920,12 +1935,12 @@ description = self.summary_name(var_doc, link_name=True) if isinstance(var_doc.value, GenericValueDoc): # The summary max length has been chosen setting - # L{ValueDoc.summary_linelen} when L{write()} was called - val_repr = var_doc.value.summary_pyval_repr()[0] - val_repr = plaintext_to_html(val_repr) + # L{ValueDoc.SUMMARY_REPR_LINELEN} in the constructor + max_len=self._variable_summary_linelen-3-len(var_doc.name) + val_repr = var_doc.value.summary_pyval_repr(max_len) tooltip = self.variable_tooltip(var_doc) description += (' = <code%s>%s</code>' % - (tooltip, val_repr)) + (tooltip, val_repr.to_html(None))) # Add the summary to the description (if there is one). summary = self.summary(var_doc, indent=6) @@ -2058,9 +2073,7 @@ if isinstance(val_doc, RoutineDoc): return self.function_signature(val_doc, True, True) elif isinstance(val_doc, GenericValueDoc): - return ('<table><tr><td><pre class="variable">\n' + - self.pprint_value(val_doc) + - '\n</pre></td></tr></table>\n') + return self.pprint_value(val_doc) else: return self.href(val_doc) else: @@ -2272,9 +2285,7 @@ >>> self.write_standard_fields(out, var_doc) >>> if var_doc.value is not UNKNOWN: <dl><dt>Value:</dt> - <dd><table><tr><td><pre class="variable"> - $self.pprint_value(var_doc.value)$ - </pre></td></tr></table></dd> + <dd>$self.pprint_value(var_doc.value)$</dd> </dl> >>> #endif </dd></dl> @@ -2286,168 +2297,21 @@ def variable_tooltip(self, var_doc): if var_doc.value in (None, UNKNOWN): return '' - - s = var_doc.value.pyval_repr() + s = var_doc.value.pyval_repr().to_plaintext(None) if len(s) > self._variable_tooltip_linelen: s = s[:self._variable_tooltip_linelen-3]+'...' return ' title="%s"' % plaintext_to_html(s) def pprint_value(self, val_doc): - if val_doc is UNKNOWN: return '' - if val_doc.pyval is not UNKNOWN: - return self.pprint_pyval(val_doc.pyval) + if val_doc is UNKNOWN: + return '??' elif isinstance(val_doc, GenericValueDoc): - s = plaintext_to_html(val_doc.pyval_repr()) + return ('<table><tr><td><pre class="variable">\n' + + val_doc.pyval_repr().to_html(None) + + '\n</pre></td></tr></table>\n') else: - s = self.href(val_doc) - return self._linewrap_html(s, self._variable_linelen, - self._variable_maxlines) + return self.href(val_doc) - def pprint_pyval(self, pyval): - # Handle the most common cases first. The following types - # will never need any line wrapping, etc; and they cover most - # variable values (esp int, for constants). I leave out - # LongType on purpose, since long values may need line- - # wrapping. - if (type(pyval) is types.IntType or type(pyval) is types.FloatType or - type(pyval) is types.NoneType or type(pyval) is types.ComplexType): - # none of these should contain '&', '<' or '>'. - vstr = repr(pyval) - return vstr + ' ' * (self._variable_linelen-len(vstr)) - - # For strings, use repr. Use tripple-quoted-strings where - # appropriate. - elif isinstance(pyval, basestring): - vstr = repr(pyval) - # Find the left quote. - lquote = vstr.find(vstr[-1]) - # Use tripple quotes if the string is multi-line: - if vstr.find(r'\n') >= 0: - body = vstr[lquote+1:-1].replace(r'\n', '\n') - vstr = ('<span class="variable-quote">'+vstr[:lquote]+ - vstr[lquote]*3+'</span>'+ - plaintext_to_html(body) + - '<span class="variable-quote">'+vstr[-1]*3+'</span>') - # Use single quotes if the string is single-line: - else: - vstr = ('<span class="variable-quote">'+vstr[:lquote+1]+ - '</span>'+ plaintext_to_html(vstr[lquote+1:-1])+ - '<span class="variable-quote">'+vstr[-1:]+'</span>') - - # For lists, tuples, and dicts, use pprint. When possible, - # restrict the amount of stuff that pprint needs to look at, - # since pprint is surprisingly slow. - elif type(pyval) is types.TupleType or type(pyval) is types.ListType: - try: vstr = repr(pyval) - except: vstr = '...' - if len(vstr) > self._variable_linelen: - vstr = pprint.pformat(pyval[:self._variable_maxlines+1]) - vstr = plaintext_to_html(vstr) - elif type(pyval) is type({}): - try: vstr = repr(pyval) - except: vstr = '...' - if len(vstr) > self._variable_linelen: - if len(pyval) < self._variable_maxlines+50: - vstr = pprint.pformat(pyval) - else: - shortval = {} - for (k,v) in pyval.items()[:self._variable_maxlines+1]: - shortval[k]=v - vstr = pprint.pformat(shortval) - vstr = plaintext_to_html(vstr) - - # For regexps, use colorize_re. - elif type(pyval).__name__ == 'SRE_Pattern': - try: vstr = colorize_re(pyval) - except TypeError, sre_constants.error: - try: vstr = plaintext_to_html(repr(pyval)) - except: vstr = '...' - - # For other objects, use repr to generate a representation. - else: - try: vstr = plaintext_to_html(repr(pyval)) - except: vstr = '...' - - # Encode vstr, if necessary. - if isinstance(vstr, str): - vstr = decode_with_backslashreplace(vstr) - - # Do line-wrapping. - return self._linewrap_html(vstr, self._variable_linelen, - self._variable_maxlines) - - def _linewrap_html(self, s, linelen, maxlines): - """ - Add line-wrapping to the HTML string C{s}. Line length is - determined by C{linelen}; and the maximum number of - lines to display is determined by C{maxlines}. This - function treats HTML entities (e.g., C{&}) as single - characters; and ignores HTML tags (e.g., C{<p>}). - """ - LINEWRAP_MARKER = (r'<span class="variable-linewrap">' - '<img src="crarr.png" alt="\" /></span>') - ELLIPSIS_MARKER = r'<span class="variable-ellipsis">...</span>' - - open_elements = [] # tag stack - lines = [] - start = end = cnum = 0 - while len(lines) <= maxlines and end < len(s): - # Skip over HTML tags. - if s[end] == '<': - newend = s.find('>', end) - tag = s[end+1:newend] - if tag[-1]!="/": - # non-empty tag - tagname = tag.split(None,1)[0] - if tagname[0] == "/": - open_elements.pop() - else: - open_elements.append(tagname) - end = newend - cnum -= 1 - - # HTML entities just count as 1 char. - elif s[end] == '&': - end = s.find(';', end) - - # Go on to the next character. - cnum += 1 - end += 1 - - # Check for end-of-line. - if s[end-1] == '\n': - lines.append(s[start:end-1]) - cnum = 0 - start = end - - # Check for line-wrap - if cnum == linelen and end<len(s) and s[end] != '\n': - if maxlines == 1: - closing_tags = "" - for tag in open_elements: - closing_tags += "</%s>" % (tag,) - return s[start:end]+closing_tags+ELLIPSIS_MARKER - lines.append(s[start:end]+LINEWRAP_MARKER) - cnum = 0 - start = end - - # Add on anything that's left. - if end == len(s): - lines.append(s[start:end]) - - # Use the ellipsis marker if the string is too long. - if len(lines) > maxlines: - closing_tags = "" - for tag in open_elements: - closing_tags += "</%s>" % (tag,) - lines[-1] = closing_tags+ELLIPSIS_MARKER - cnum = 3 - - # Pad the last line to linelen. - lines[-1] += ' '*(linelen-cnum+1) - - return ('\n').join(lines) - #//////////////////////////////////////////////////////////// #{ Base Tree #//////////////////////////////////////////////////////////// @@ -2573,8 +2437,7 @@ s = '<span class="%s-arg">%s</span>' % (css_class, name) if default is not None: s += ('=<span class="%s-default">%s</span>' % - (css_class, plaintext_to_html( - default.summary_pyval_repr()[0]))) + (css_class, default.summary_pyval_repr().to_html(None))) return s def _arg_name(self, arg): Modified: trunk/epydoc/src/epydoc/docwriter/html_css.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html_css.py 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/docwriter/html_css.py 2007-02-13 19:46:05 UTC (rev 1473) @@ -69,6 +69,7 @@ font-weight: bold; } h3 { font-size: +110%; font-style: italic; font-weight: normal; } +code { font-size: 100%; } /* Page Header & Footer * - The standard page header consists of a navigation bar (with @@ -210,6 +211,10 @@ .variable-linewrap { color: $variable_linewrap; font-weight: bold; } .variable-ellipsis { color: $variable_ellipsis; font-weight: bold; } .variable-quote { color: $variable_quote; font-weight: bold; } +.variable-group { color: $variable_group; font-weight: bold; } +.variable-op { color: $variable_op; font-weight: bold; } +.variable-string { color: $variable_string; } +.variable-unknown { color: $variable_unknown; font-weight: bold; } .re { color: $re; } .re-char { color: $re_char; } .re-op { color: $re_op; } @@ -384,6 +389,10 @@ variable_linewrap = '#604000', variable_ellipsis = '#604000', variable_quote = '#604000', + variable_group = '#008000', + variable_string = '#006030', + variable_op = '#604000', + variable_unknown = '#a00000', re = '#000000', re_char = '#006030', re_op = '#600000', Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2007-02-13 19:46:05 UTC (rev 1473) @@ -144,6 +144,14 @@ # For progress reporting: self._files_written = 0. + # Set the default values for ValueDoc formatted representations. + orig_valdoc_defaults = (ValueDoc.SUMMARY_REPR_LINELEN, + ValueDoc.REPR_LINELEN, + ValueDoc.REPR_MAXLINES) + ValueDoc.SUMMARY_REPR_LINELEN = 60 + ValueDoc.REPR_LINELEN = 52 + ValueDoc.REPR_MAXLINES = 5 + # Create destination directories, if necessary if not directory: directory = os.curdir self._mkdir(directory) @@ -162,6 +170,10 @@ filename = '%s-class.tex' % val_doc.canonical_name self._write(self.write_class, directory, filename, val_doc) + # Restore defaults that we changed. + (ValueDoc.SUMMARY_REPR_LINELEN, ValueDoc.REPR_LINELEN, + ValueDoc.REPR_MAXLINES) = orig_valdoc_defaults + def _write(self, write_func, directory, filename, *args): # Display our progress. self._files_written += 1 @@ -727,8 +739,7 @@ def func_arg(self, name, default): s = '\\textit{%s}' % plaintext_to_latex(self._arg_name(name)) if default is not None: - s += '=\\texttt{%s}' % plaintext_to_latex( - default.summary_pyval_repr()[0]) + s += '=\\texttt{%s}' % default.summary_pyval_repr().to_latex(None) return s def _arg_name(self, arg): @@ -801,31 +812,28 @@ out(' & ') has_descr = var_doc.descr not in (None, UNKNOWN) has_type = var_doc.type_descr not in (None, UNKNOWN) - has_repr = (var_doc.value not in (None, UNKNOWN) and - var_doc.value.pyval_repr() != var_doc.value.UNKNOWN_REPR) - if has_descr or has_type: - out('\\raggedright ') + out('\\raggedright ') if has_descr: out(self.docstring_to_latex(var_doc.descr, 10).strip()) if has_type or has_repr: out('\n\n') - if has_repr: - out('\\textbf{Value:} \n') - pyval_repr = var_doc.value.pyval_repr() - out(self._pprint_var_value(pyval_repr, 80)) + out('\\textbf{Value:} \n') + out(self._pprint_var_value(var_doc)) if has_type: ptype = self.docstring_to_latex(var_doc.type_descr, 12).strip() out('%s\\textit{(type=%s)}' % (' '*12, ptype)) out('&\\\\\n') out('\\cline{1-2}\n') - def _pprint_var_value(self, s, maxwidth=100): - if len(s) > maxwidth: s = s[:maxwidth-3] + '...' - if '\n' in s: + def _pprint_var_value(self, var_doc): + pyval_repr = var_doc.value.pyval_repr().to_latex(None) + if '\n' in pyval_repr: return ('\\begin{alltt}\n%s\\end{alltt}' % - plaintext_to_latex(s, nbsp=False, breakany=True)) + pyval_repr) + #plaintext_to_latex(pyval_repr, nbsp=False, breakany=True)) else: - return '{\\tt %s}' % plaintext_to_latex(s, nbsp=True, - breakany=True) + return '{\\tt %s}' % pyval_repr + #plaintext_to_latex(pyval_repr, nbsp=True, + #breakany=True) def write_property_list_line(self, out, var_doc): prop_doc = var_doc.value Modified: trunk/epydoc/src/epydoc/docwriter/plaintext.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/plaintext.py 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/docwriter/plaintext.py 2007-02-13 19:46:05 UTC (rev 1473) @@ -15,10 +15,12 @@ import re class PlaintextWriter: - def write(self, api_doc): + def write(self, api_doc, **options): result = [] out = result.append + self._cols = options.get('cols', 75) + try: if isinstance(api_doc, ModuleDoc): self.write_module(out, api_doc) @@ -128,7 +130,7 @@ self.write_list(out, 'Inherited Nested Classes', class_doc, value_type='class', prefix=prefix, inherited=True, verbose=False) - + def write_variable(self, out, var_doc, name=None, prefix='', verbose=True): if name is None: name = var_doc.name out(prefix+self.bold(str(name))) @@ -137,8 +139,9 @@ var_doc.value.canonical_name not in (None, UNKNOWN)): out(' = %s' % var_doc.value.canonical_name) elif var_doc.value not in (UNKNOWN, None): - val_repr = var_doc.value.summary_pyval_repr(max_len=len(name)-75)[0] - out(' = %s' % val_repr.expandtabs()) + val_repr = var_doc.value.summary_pyval_repr( + max_len=self._cols-len(name)-len(prefix)-3) + out(' = %s' % val_repr.to_plaintext(None)) out('\n') if not verbose: return prefix += ' ' # indent the body. @@ -199,7 +202,8 @@ if default is None: return '%s' % name else: - return '%s=%s' % (name, default.summary_pyval_repr()[0]) + default_repr = default.summary_pyval_repr() + return '%s=%s' % (name, default_repr.to_plaintext(None)) def write_list(self, out, heading, doc, value_type=None, imported=False, inherited=False, prefix='', noindent=False, Modified: trunk/epydoc/src/epydoc/markup/epytext.py =================================================================== --- trunk/epydoc/src/epydoc/markup/epytext.py 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/markup/epytext.py 2007-02-13 19:46:05 UTC (rev 1473) @@ -148,6 +148,11 @@ ''.join([str(child) for child in self.children]) + '</%s>' % self.tag) + def __repr__(self): + attribs = ''.join([', %s=%r' % t for t in self.attribs.items()]) + args = ''.join([', %r' % c for c in self.children]) + return 'Element(%s%s%s)' % (self.tag, args, attribs) + ################################################## ## Constants ################################################## @@ -1591,7 +1596,6 @@ ################################################################# ## SUPPORT FOR EPYDOC ################################################################# -from epydoc.docwriter.dotgraph import * def parse_docstring(docstring, errors, **options): """ @@ -1854,6 +1858,7 @@ log.warning("Could not construct class tree: you must " "specify one or more base classes.") return None + from epydoc.docwriter.dotgraph import class_tree_graph return class_tree_graph(bases, linker, context) elif graph_type == 'packagetree': if graph_args: @@ -1865,9 +1870,11 @@ log.warning("Could not construct package tree: you must " "specify one or more root packages.") return None + from epydoc.docwriter.dotgraph import package_tree_graph return package_tree_graph(packages, linker, context) elif graph_type == 'importgraph': modules = [d for d in docindex.root if isinstance(d, ModuleDoc)] + from epydoc.docwriter.dotgraph import import_graph return import_graph(modules, docindex, linker, context) elif graph_type == 'callgraph': @@ -1876,6 +1883,7 @@ docs = [doc for doc in docs if doc is not None] else: docs = [context] + from epydoc.docwriter.dotgraph import call_graph return call_graph(docs, docindex, linker, context) else: log.warning("Unknown graph type %s" % graph_type) Modified: trunk/epydoc/src/epydoc/markup/pyval_repr.py =================================================================== --- trunk/epydoc/src/epydoc/markup/pyval_repr.py 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/markup/pyval_repr.py 2007-02-13 19:46:05 UTC (rev 1473) @@ -79,28 +79,44 @@ generates a string containing a newline, but the state object's linebreakok variable is False.""" +class ColorizedPyvalRepr(ParsedEpytextDocstring): + """ + @ivar score: A score, evaluating how good this repr is. + @ivar is_complete: True if this colorized repr completely describes + the object. + """ + def __init__(self, tree, score, is_complete): + ParsedEpytextDocstring.__init__(self, tree) + self.score = score + self.is_complete = is_complete +def colorize_pyval(pyval, parse_repr=None, min_score=None, + linelen=75, maxlines=5, linebreakok=True, sort=True): + return PyvalColorizer(linelen, maxlines, linebreakok, sort).colorize( + pyval, parse_repr, min_score) + class PyvalColorizer: """ Syntax highlighter for Python values. """ - def __init__(self, linelen=75, maxlines=5, sort=True): + def __init__(self, linelen=75, maxlines=5, linebreakok=True, sort=True): self.linelen = linelen self.maxlines = maxlines + self.linebreakok = linebreakok self.sort = sort #//////////////////////////////////////////////////////////// - # Colorization Tags + # Colorization Tags & other constants #//////////////////////////////////////////////////////////// - GROUP_TAG = 'val-group' # e.g., "[" and "]" - COMMA_TAG = 'val-op' # The "," that separates elements - COLON_TAG = 'val-op' # The ":" in dictionaries - CONST_TAG = None # None, True, False - NUMBER_TAG = None # ints, floats, etc - QUOTE_TAG = 'val-quote' # Quotes around strings. - STRING_TAG = 'val-string' # Body of string literals + GROUP_TAG = 'variable-group' # e.g., "[" and "]" + COMMA_TAG = 'variable-op' # The "," that separates elements + COLON_TAG = 'variable-op' # The ":" in dictionaries + CONST_TAG = None # None, True, False + NUMBER_TAG = None # ints, floats, etc + QUOTE_TAG = 'variable-quote' # Quotes around strings. + STRING_TAG = 'variable-string' # Body of string literals RE_CHAR_TAG = None RE_GROUP_TAG = 're-group' @@ -108,45 +124,60 @@ RE_OP_TAG = 're-op' RE_FLAGS_TAG = 're-flags' - # Should these use symbols instead? - ELLIPSIS = Element('code', '...', style='ellipsis') - LINEWRAP = Element('symbol', 'crarr') + ELLIPSIS = Element('code', u'...', style='variable-ellipsis') + LINEWRAP = Element('symbol', u'crarr') + UNKNOWN_REPR = Element('code', u'??', style='variable-unknown') + GENERIC_OBJECT_RE = re.compile(r'^<.* at 0x[0-9a-f]+>$', re.IGNORECASE) + #//////////////////////////////////////////////////////////// # Entry Point #//////////////////////////////////////////////////////////// - def colorize(self, pyval, min_score=None): - pds, score = self.colorize_and_score(pyval) - if min_score is None or score >= min_score: - return pds - else: - return None - - def colorize_and_score(self, pyval): + def colorize(self, pyval, parse_repr=None, min_score=None): """ - @return: A tuple (parsed_docstring, score). + @return: A L{ColorizedPyvalRepr} describing the given pyval. """ + UNKNOWN = epydoc.apidoc.UNKNOWN # Create an object to keep track of the colorization. state = _ColorizerState() + state.linebreakok = self.linebreakok # Colorize the value. If we reach maxlines, then add on an # ellipsis marker and call it a day. try: - self._colorize(pyval, state) - except _Maxlines: - state.result.append(self.ELLIPSIS) + if pyval is not UNKNOWN: + self._colorize(pyval, state) + elif parse_repr not in (None, UNKNOWN): + self._output(parse_repr, None, state) + else: + state.result.append(PyvalColorizer.UNKNOWN_REPR) + is_complete = True + except (_Maxlines, _Linebreak): + if self.linebreakok: + state.result.append('\n') + state.result.append(self.ELLIPSIS) + else: + if state.result[-1] is self.LINEWRAP: + state.result.pop() + self._trim_result(state.result, 3) + state.result.append(self.ELLIPSIS) + is_complete = False + # If we didn't score high enough, then try again. + if (pyval is not UNKNOWN and parse_repr not in (None, UNKNOWN) + and min_score is not None and state.score < min_score): + return self.colorize(UNKNOWN, parse_repr) # Put it all together. tree = Element('epytext', *state.result) - return ParsedEpytextDocstring(tree), state.score + return ColorizedPyvalRepr(tree, state.score, is_complete) def _colorize(self, pyval, state): pyval_type = type(pyval) state.score += 1 if pyval is None or pyval is True or pyval is False: - self._output(str(pyval), self.CONST_TAG, state) + self._output(unicode(pyval), self.CONST_TAG, state) elif pyval_type in (int, float, long, types.ComplexType): - self._output(str(pyval), self.NUMBER_TAG, state) + self._output(unicode(pyval), self.NUMBER_TAG, state) elif pyval_type is str: self._colorize_str(pyval, state, '', 'string-escape') elif pyval_type is unicode: @@ -156,34 +187,56 @@ elif pyval_type is tuple: self._multiline(self._colorize_iter, pyval, state, '(', ')') elif pyval_type is set: - if self.sort: pyval = sorted(pyval) - self._multiline(self._colorize_iter, pyval, state, - 'set([', '])') + self._multiline(self._colorize_iter, self._sort(pyval), + state, 'set([', '])') elif pyval_type is frozenset: - if self.sort: pyval = sorted(pyval) - self._multiline(self._colorize_iter, pyval, state, - 'frozenset([', '])') + self._multiline(self._colorize_iter, self._sort(pyval), + state, 'frozenset([', '])') elif pyval_type is dict: - items = pyval.items() - if self.sort: items = sorted(items) - self._multiline(self._colorize_dict, items, state, '{', '}') + self._multiline(self._colorize_dict, self._sort(pyval.items()), + state, '{', '}') elif is_re_pattern(pyval): self._colorize_re(pyval, state) else: try: pyval_repr = repr(pyval) - self._output(pyval_repr, None, state) - if self.GENERIC_OBJECT_RE.match(pyval_repr): - state.score -= 5 + if not isinstance(pyval_repr, (str, unicode)): + pyval_repr = unicode(pyval_repr) + pyval_repr_ok = True except KeyboardInterrupt: raise except: - pyval_repr = '...' + pyval_repr_ok = False state.score -= 100 - GENERIC_OBJECT_RE = re.compile(r'^<.* at 0x[0-9a-f]+>$', - re.IGNORECASE) + if pyval_repr_ok: + self._output(pyval_repr, None, state) + if self.GENERIC_OBJECT_RE.match(pyval_repr): + state.score -= 5 + else: + state.result.append(self.UNKNOWN_REPR) + + def _sort(self, items): + if not self.sort: return items + try: return sorted(items) + except KeyboardInterrupt: raise + except: return items + def _trim_result(self, result, num_chars): + while num_chars > 0: + if not result: return + if isinstance(result[-1], Element): + assert len(result[-1].children) == 1 + trim = min(num_chars, len(result[-1].children[0])) + result[-1].children[0] = result[-1].children[0][:-trim] + if not result[-1].children[0]: result.pop() + num_chars -= trim + else: + trim = min(num_chars, len(result[-1])) + result[-1] = result[-1][:-trim] + if not result[-1]: result.pop() + num_chars -= trim + #//////////////////////////////////////////////////////////// # Object Colorization Functions #//////////////////////////////////////////////////////////// @@ -238,12 +291,17 @@ def _colorize_str(self, pyval, state, prefix, encoding): # Decide which quote to use. - if '\n' in pyval: quote = "'''" + if '\n' in pyval and state.linebreakok: quote = "'''" else: quote = "'" + # Divide the string into lines. + if state.linebreakok: + lines = pyval.split('\n') + else: + lines = [pyval] # Open quote. self._output(prefix+quote, self.QUOTE_TAG, state) # Body - for i, line in enumerate(pyval.split('\n')): + for i, line in enumerate(lines): if i>0: self._output('\n', None, state) self._output(line.encode(encoding), self.STRING_TAG, state) # Close quote. @@ -260,8 +318,10 @@ groups = dict([(num,name) for (name,num) in tree.pattern.groupdict.items()]) # Colorize it! + self._output("re.compile(r'", None, state) self._colorize_re_flags(tree.pattern.flags, state) self._colorize_re_tree(tree, state, True, groups) + self._output("')", None, state) def _colorize_re_flags(self, flags, state): if flags: @@ -281,7 +341,7 @@ if op == sre_constants.LITERAL: c = unichr(args) # Add any appropriate escaping. - if c in '.^$\\*+?{}[]|()': c = '\\'+c + if c in '.^$\\*+?{}[]|()\'': c = '\\'+c elif c == '\t': c = '\\t' elif c == '\r': c = '\\r' elif c == '\n': c = '\\n' @@ -419,8 +479,9 @@ be line-wrapped. If the total number of lines exceeds `self.maxlines`, then raise a `_Maxlines` exception. """ - if '\n' in s and not state.linebreakok: - raise _Linebreak() + # Make sure the string is unicode. + if isinstance(s, str): + s = decode_with_backslashreplace(s) # Split the string into segments. The first segment is the # content to add to the current line, and the remaining @@ -431,13 +492,13 @@ # If this isn't the first segment, then add a newline to # split it from the previous segment. if i > 0: + if (state.lineno+1) > self.maxlines: + raise _Maxlines() if not state.linebreakok: raise _Linebreak() - state.result.append('\n') + state.result.append(u'\n') state.lineno += 1 state.charpos = 0 - if state.lineno > self.maxlines: - raise _Maxlines() # If the segment fits on the current line, then just call # markup to tag it, and store the result. Modified: trunk/epydoc/src/epydoc/test/docbuilder.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docbuilder.doctest 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/test/docbuilder.doctest 2007-02-13 19:46:05 UTC (rev 1473) @@ -300,17 +300,39 @@ >>> from epydoc.test.util import buildvaluedoc >>> def print_py_reprs(s): ... value_doc = buildvaluedoc(s) + ... print 'Var Score Repr\n'+'-'*50 ... for (name, var_doc) in sorted(value_doc.variables.items()): - ... print "%-5s %r" % (name, var_doc.value.pyval_repr()) + ... if len(name) > 1: continue + ... var_repr = var_doc.value.pyval_repr() + ... print " %s %4s %r" % (name, var_repr.score, + ... var_repr.to_plaintext(None)) >>> print_py_reprs(''' + ... import re ... class Foo: pass - ... a = Foo() - ... b = [1, 2, 3] - ... c = 3+5 - ... b.append(99) + ... class Bar: + ... def __repr__(self): return "<specialized repr>" + ... class Baz: + ... def __repr__(self): raise ValueError() + ... a = Foo() # pyval score < 0; use parse repr. + ... b = Bar() # pyval score > 0; use pyval repr. + ... c = Baz() # pyval score < 0; use parse repr. + ... d = [1, 2, 3] # pyval score > 0; use pyval repr. + ... d.append(99) + ... e = 3+5 # pyval score > 0; use pyval repr. + ... f = re.compile('hi+') # pyval score > 0; use pyval repr. + ... globals()['h'] = Baz() # pyval score < 0; can't be parsed. + ... i = [Foo(), 1, 2] # pyval score < 0; use parse repr. + ... j = [Foo(), 1, 2, 3] # pyval score = 0; use pyval repr. ... ''') - Foo u'<class epydoc_test.Foo at ...>' - a u'Foo()' - b u'[1, 2, 3, 99]' - c u'8' + Var Score Repr + -------------------------------------------------- + a 0 u'Foo()' + b 1 u'<specialized repr>' + c 0 u'Baz()' + d 5 u'[1, 2, 3, 99]' + e 1 u'8' + f 1 u"re.compile(r'hi+')" + h -99 u'??' + i 0 u'[Foo(), 1, 2]' + j 0 u'[<epydoc_test.Foo instance at ...>, 1, 2, 3]' Modified: trunk/epydoc/src/epydoc/test/pyval_repr.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/pyval_repr.doctest 2007-02-13 15:27:45 UTC (rev 1472) +++ trunk/epydoc/src/epydoc/test/pyval_repr.doctest 2007-02-13 19:46:05 UTC (rev 1473) @@ -3,7 +3,10 @@ >>> from epydoc.markup.pyval_repr import * >>> colorizer = PyvalColorizer(linelen=40) - >>> def color(s): print colorizer.colorize(s).to_html(None).rstrip() + >>> def color(v, linebreakok=True): + ... colorizer = PyvalColorizer(linelen=40, linebreakok=linebreakok) + ... pds = colorizer.colorize(v, None) + ... print pds.to_html(None).rstrip() Simple Types ============ @@ -27,6 +30,7 @@ 1000000000000000000000000000000000000000↵ 0000000000000000000000000000000000000000↵ 00000000000 + >>> colorizer = PyvalColorizer(linelen=40) >>> print '-'*40+'\n'+colorizer.colorize(10**90).to_plaintext(None) ---------------------------------------- 1000000000000000000000000000000000000000\ @@ -39,37 +43,42 @@ escaped using the 'string-escape' encoding. >>> color(''.join(chr(i) for i in range(256))) - <code class="val-quote">'''</code><code class="val-string">\x00\x01\x02\x03\x04\x05\x06\x07\x08\</code>↵ - <code class="val-string">t</code> - <code class="val-string">\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x</code>↵ - <code class="val-string">15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x</code>↵ - <code class="val-string">1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCD</code>↵ - <code class="ellipsis">...</code> + <code class="variable-quote">'''</code><code class="variable-string">\x00\x01\x02\x03\x04\x05\x06\x07\x08\</code>↵ + <code class="variable-string">t</code> + <code class="variable-string">\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x</code>↵ + <code class="variable-string">15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x</code>↵ + <code class="variable-string">1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCD</code>↵ + <code class="variable-ellipsis">...</code> Currently, the "'" quote is always used, because that's what the 'string-escape' encoding expects. >>> color('Hello') - <code class="val-quote">'</code><code class="val-string">Hello</code><code class="val-quote">'</code> + <code class="variable-quote">'</code><code class="variable-string">Hello</code><code class="variable-quote">'</code> >>> color('"Hello"') - <code class="val-quote">'</code><code class="val-string">"Hello"</code><code class="val-quote">'</code> + <code class="variable-quote">'</code><code class="variable-string">"Hello"</code><code class="variable-quote">'</code> >>> color("'Hello'") - <code class="val-quote">'</code><code class="val-string">\'Hello\'</code><code class="val-quote">'</code> + <code class="variable-quote">'</code><code class="variable-string">\'Hello\'</code><code class="variable-quote">'</code> Strings containing newlines are automatically rendered as multiline strings. >>> color("This\n is a multiline\n string!") - <code class="val-quote">'''</code><code class="val-string">This</code> - <code class="val-string"> is a multiline</code> - <code class="val-string"> string!</code><code class="val-quote">'''</code> + <code class="variable-quote">'''</code><code class="variable-string">This</code> + <code class="variable-string"> is a multiline</code> + <code class="variable-string"> string!</code><code class="variable-quote">'''</code> +Unless we ask for them not to be: + + >>> color("This\n is a multiline\n string!", linebreakok=False) + <code class="variable-quote">'</code><code class="variable-string">This\n is a multiline\n string!</code><code class="variable-quote">'</code> + Unicode strings are handled properly. >>> color(u"Hello world") - <code class="val-quote">u'</code><code class="val-string">Hello world</code><code class="val-quote">'</code> + <code class="variable-quote">u'</code><code class="variable-string">Hello world</code><code class="variable-quote">'</code> >>> color(u"\uaaaa And \ubbbb") - <code class="val-quote">u'</code><code class="val-string">\uaaaa And \ubbbb</code><code class="val-quote">'</code> + <code class="variable-quote">u'</code><code class="variable-string">\uaaaa And \ubbbb</code><code class="variable-quote">'</code> Lists, Tuples, etc. =================== @@ -79,28 +88,28 @@ listed on a separate line, indented by the size of the open-bracket. >>> color(range(10)) - <code class="val-group">[</code>0<code class="val-op">, </code>1<code class="val-op">, </code>2<code class="val-op">, </code>3<code class="val-op">, </code>4<code class="val-op">, </code>5<code class="val-op">, </code>6<code class="val-op">, </code>7<code class="val-op">, </code>8<code class="val-op">, </code>9<code class="val-group">]</code> + <code class="variable-group">[</code>0<code class="variable-op">, </code>1<code class="variable-op">, </code>2<code class="variable-op">, </code>3<code class="variable-op">, </code>4<code class="variable-op">, </code>5<code class="variable-op">, </code>6<code class="variable-op">, </code>7<code class="variable-op">, </code>8<code class="variable-op">, </code>9<code class="variable-group">]</code> >>> color(range(100)) - <code class="val-group">[</code>0<code class="val-op">,</code> - 1<code class="val-op">,</code> - 2<code class="val-op">,</code> - 3<code class="val-op">,</code> - 4<code class="val-op">,</code> - <code class="ellipsis">...</code> + <code class="variable-group">[</code>0<code class="variable-op">,</code> + 1<code class="variable-op">,</code> + 2<code class="variable-op">,</code> + 3<code class="variable-op">,</code> + 4<code class="variable-op">,</code> + <code class="variable-ellipsis">...</code> >>> color([1,2,[5,6,[(11,22,33),9],10],11]+[99,98,97,96,95]) - <code class="val-group">[</code>1<code class="val-op">,</code> - 2<code class="val-op">,</code> - <code class="val-group">[</code>5<code class="val-op">, </code>6<code class="val-op">, </code><code class="val-group">[</code><code class="val-group">(</code>11<code class="val-op">, </code>22<code class="val-op">, </code>33<code class="val-group">)</code><code class="val-op">, </code>9<code class="val-group">]</code><code class="val-op">, </code>10<code class="val-group">]</code><code class="val-op">,</code> - 11<code class="val-op">,</code> - 99<code class="val-op">,</code> - <code class="ellipsis">...</code> + <code class="variable-group">[</code>1<code class="variable-op">,</code> + 2<code class="variable-op">,</code> + <code class="variable-group">[</code>5<code class="variable-op">, </code>6<code class="variable-op">, </code><code class="variable-group">[</code><code class="variable-group">(</code>11<code class="variable-op">, </code>22<code class="variable-op">, </code>33<code class="variable-group">)</code><code class="variable-op">, </code>9<code class="variable-group">]</code><code class="variable-op">, </code>10<code class="variable-group">]</code><code class="variable-op">,</code> + 11<code class="variable-op">,</code> + 99<code class="variable-op">,</code> + <code class="variable-ellipsis">...</code> >>> color(set(range(20))) - <code class="val-group">set([</code>0<code class="val-op">,</code> - 1<code class="val-op">,</code> - 2<code class="val-op">,</code> - 3<code class="val-op">,</code> - 4<code class="val-op">,</code> - <code class="ellipsis">...</code> + <code class="variable-group">set([</code>0<code class="variable-op">,</code> + 1<code class="variable-op">,</code> + 2<code class="variable-op">,</code> + 3<code class="variable-op">,</code> + 4<code class="variable-op">,</code> + <code class="variable-ellipsis">...</code> Dictionaries ============ @@ -108,12 +117,12 @@ "op". >>> color({1:33, 2:[1,2,3,{7:'oo'*20}]}) - <code class="val-group">{</code>1<code class="val-op">: </code>33<code class="val-op">,</code> - 2<code class="val-op">: </code><code class="val-group">[</code>1<code class="val-op">,</code> - 2<code class="val-op">,</code> - 3<code class="val-op">,</code> - <code class="val-group">{</code>7<code class="val-op">: </code><code class="val-quote">'</code><code class="val-string">oooooooooooooooooooooooooooooo</code>↵ - <code class="ellipsis">...</code> + <code class="variable-group">{</code>1<code class="variable-op">: </code>33<code class="variable-op">,</code> + 2<code class="variable-op">: </code><code class="variable-group">[</code>1<code class="variable-op">,</code> + 2<code class="variable-op">,</code> + 3<code class="variable-op">,</code> + <code class="variable-group">{</code>7<code class="variable-op">: </code><code class="variable-quote">'</code><code class="variable-string">oooooooooooooooooooooooooooooo</code>↵ + <code class="variable-ellipsis">...</code> Regular Expressions =================== @@ -124,16 +133,17 @@ >>> import re >>> def color_re(s, check_roundtrip=True): + ... colorizer = PyvalColorizer(linelen=55) ... val = colorizer.colorize(re.compile(s)) ... if check_roundtrip: - ... assert textcontent(val._tree) == s, val._tree - ... print val.to_html(None).rstrip() + ... assert textcontent(val._tree)[13:-2] == s, val._tree + ... print val.to_html(None).rstrip()[13:-2] >>> # Literal characters - >>> color_re(u'abc \t\r\n\f\v \xff \uffff \U000fffff', False) - abc \t\r\n\f\v \xff \uffff \U000fffff - >>> color_re(r'\.\^\$\\\*\+\?\{\}\[\]\|\(\)') - \.\^\$\\\*\+\?\{\}\[\]\|\(\) + >>> color_re(u'abc \t\r\n\f\v \xff \uffff', False) + abc \t\r\n\f\v \xff \uffff + >>> color_re(r'\.\^\$\\\*\+\?\{\}\[\]\|\(\)\'') + \.\^\$\\\*\+\?\{\}\[\]\|\(\)\' >>> # Any character & character classes >>> color_re(r".\d\D\s\S\w\W\A^$\b\B\Z") @@ -193,6 +203,33 @@ >>> color_re(r"(?x)This is verbose", False) <code class="re-flags">(?x)</code>Thisisverbose +Line Wrapping +============= +If a line goes beyond linelen, it is wrapped using ``↵`` (which +gets translated to ``\\`` by `to_plaintext()`). + + >>> colorizer = PyvalColorizer(linelen=40) + >>> print colorizer.colorize('x'*100).to_plaintext(None) + 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxx' + +Check that the last line gets a ``↵`` when maxlines is exceeded: + + >>> print colorizer.colorize('x'*1000).to_plaintext(None) + 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\ + ... + +If linebreakok is False, then line wrapping gives an ellipsis instead: + + >>> colorizer = PyvalColorizer(linelen=40, linebreakok=False) + >>> print colorizer.colorize('x'*100).to_plaintext(None) + 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx... + Representation Scores ===================== When colorized representations are built, a score is computed @@ -211,9 +248,10 @@ scores; if the score is too low, then `colorize` will return `None`. >>> def color2(v): - ... pds, score = colorizer.colorize_and_score(v) + ... colorizer = PyvalColorizer(linelen=40) + ... pds = colorizer.colorize(v) ... print 'repr: %s' % pds.to_plaintext(None) - ... print 'score: %s (%s)' % (score, score>0 and 'ok' or 'bad') + ... print 'score: %s (%s)' % (pds.score, pds.score>0 and 'ok' or 'bad') >>> class A: pass @@ -242,3 +280,19 @@ ... score: 1 (ok) +Summary +======= +To generate summary-reprs, use maxlines=1 and linebreakok=False: + + >>> summarizer = PyvalColorizer(linelen=60, maxlines=1, linebreakok=False) + >>> def summarize(v): + ... print summarizer.colorize(v).to_plaintext(None) + + >>> summarize(range(100)) + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16... + >>> summarize('hello\nworld') + 'hello\nworld' + >>> summarize('hello\nworld'*100) + 'hello\nworldhello\nworldhello\nworldhello\nworldhello\nw... + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-02-13 15:27:54
|
Revision: 1472 http://svn.sourceforge.net/epydoc/?rev=1472&view=rev Author: dvarrazzo Date: 2007-02-13 07:27:45 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - All tests pass again. Modified Paths: -------------- trunk/epydoc/src/epydoc/test/docbuilder.doctest trunk/epydoc/src/epydoc/test/docparser.doctest trunk/epydoc/src/epydoc/test/epytext.doctest trunk/epydoc/src/epydoc/test/util.py Property Changed: ---------------- trunk/epydoc/src/epydoc/test/docbuilder.doctest trunk/epydoc/src/epydoc/test/javadoc.doctest trunk/epydoc/src/epydoc/test/plaintext.doctest trunk/epydoc/src/epydoc/test/pyval_repr.doctest trunk/epydoc/src/epydoc/test/restructuredtext.doctest Modified: trunk/epydoc/src/epydoc/test/docbuilder.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docbuilder.doctest 2007-02-13 14:27:23 UTC (rev 1471) +++ trunk/epydoc/src/epydoc/test/docbuilder.doctest 2007-02-13 15:27:45 UTC (rev 1472) @@ -310,7 +310,7 @@ ... c = 3+5 ... b.append(99) ... ''') - Foo u'<class epydoc_test.Foo at 0x40484bfc>' - a u'<epydoc_test.Foo instance at 0x4069ca4c>' + Foo u'<class epydoc_test.Foo at ...>' + a u'Foo()' b u'[1, 2, 3, 99]' c u'8' Property changes on: trunk/epydoc/src/epydoc/test/docbuilder.doctest ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/epydoc/src/epydoc/test/docparser.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docparser.doctest 2007-02-13 14:27:23 UTC (rev 1471) +++ trunk/epydoc/src/epydoc/test/docparser.doctest 2007-02-13 15:27:45 UTC (rev 1472) @@ -36,10 +36,10 @@ ... y = [1,2,3] + [4,5] ... z = f(x,y) ... """) - ModuleDoc for test [0] - +- canonical_name = DottedName('test') + ModuleDoc for epydoc_test [0] + +- canonical_name = DottedName('epydoc_test') +- defining_module - | +- ModuleDoc for test [0] (defined above) + | +- ModuleDoc for epydoc_test [0] (defined above) +- docs_extracted_by = 'parser' +- filename = ... +- imports = [] @@ -48,9 +48,9 @@ +- sort_spec = [u'x', u'y', u'z'] +- submodules = [] +- variables - +- x => VariableDoc for test.x [1] + +- x => VariableDoc for epydoc_test.x [1] | +- container - | | +- ModuleDoc for test [0] (defined above) + | | +- ModuleDoc for epydoc_test [0] (defined above) | +- docs_extracted_by = 'parser' | +- is_alias = False | +- is_imported = False @@ -60,13 +60,13 @@ | +- value | +- GenericValueDoc [2] | +- defining_module - | | +- ModuleDoc for test [0] (defined above) + | | +- ModuleDoc for epydoc_test [0] (defined above) | +- docs_extracted_by = 'parser' | +- parse_repr = u'12' | +- toktree = [(2, u'12')] - +- y => VariableDoc for test.y [3] + +- y => VariableDoc for epydoc_test.y [3] | +- container - | | +- ModuleDoc for test [0] (defined above) + | | +- ModuleDoc for epydoc_test [0] (defined above) | +- docs_extracted_by = 'parser' | +- is_alias = False | +- is_imported = False @@ -76,13 +76,13 @@ | +- value | +- GenericValueDoc [4] | +- defining_module - | | +- ModuleDoc for test [0] (defined above) + | | +- ModuleDoc for epydoc_test [0] (defined above) | +- docs_extracted_by = 'parser' | +- parse_repr = u'[1, 2, 3]+ [4, 5]' | +- toktree = [[(51, u'['), (2, u'1'), (51, u','), ... - +- z => VariableDoc for test.z [5] + +- z => VariableDoc for epydoc_test.z [5] +- container - | +- ModuleDoc for test [0] (defined above) + | +- ModuleDoc for epydoc_test [0] (defined above) +- docs_extracted_by = 'parser' +- is_alias = False +- is_imported = False @@ -92,7 +92,7 @@ +- value +- GenericValueDoc [6] +- defining_module - | +- ModuleDoc for test [0] (defined above) + | +- ModuleDoc for epydoc_test [0] (defined above) +- docs_extracted_by = 'parser' +- parse_repr = u'f(x, y)' +- toktree = [(1, u'f'), [(51, u'('), (1, u'x'), (... @@ -105,16 +105,16 @@ ... y = x ... """, ... attribs='variables is_alias name value parse_repr') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- parse_repr = <UNKNOWN> +- variables - +- x => VariableDoc for test.x [1] + +- x => VariableDoc for epydoc_test.x [1] | +- is_alias = False | +- name = u'x' | +- value | +- GenericValueDoc [2] | +- parse_repr = u'[1, 2]' - +- y => VariableDoc for test.y [3] + +- y => VariableDoc for epydoc_test.y [3] +- is_alias = True +- name = u'y' +- value @@ -128,33 +128,33 @@ ... [a,(b,[c,d],e),(f,g)] = [1,(2,[3,4],5),(6,7)] ... """, ... attribs='variables is_alias name value') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- a => VariableDoc for test.a [1] + +- a => VariableDoc for epydoc_test.a [1] | +- is_alias = False | +- name = u'a' | +- value = <UNKNOWN> - +- b => VariableDoc for test.b [2] + +- b => VariableDoc for epydoc_test.b [2] | +- is_alias = False | +- name = u'b' | +- value = <UNKNOWN> - +- c => VariableDoc for test.c [3] + +- c => VariableDoc for epydoc_test.c [3] | +- is_alias = False | +- name = u'c' | +- value = <UNKNOWN> - +- d => VariableDoc for test.d [4] + +- d => VariableDoc for epydoc_test.d [4] | +- is_alias = False | +- name = u'd' | +- value = <UNKNOWN> - +- e => VariableDoc for test.e [5] + +- e => VariableDoc for epydoc_test.e [5] | +- is_alias = False | +- name = u'e' | +- value = <UNKNOWN> - +- f => VariableDoc for test.f [6] + +- f => VariableDoc for epydoc_test.f [6] | +- is_alias = False | +- name = u'f' | +- value = <UNKNOWN> - +- g => VariableDoc for test.g [7] + +- g => VariableDoc for epydoc_test.g [7] +- is_alias = False +- name = u'g' +- value = <UNKNOWN> @@ -169,21 +169,21 @@ ... x = y = z = 0 ... """, ... attribs="variables is_alias name value parse_repr") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- parse_repr = <UNKNOWN> +- variables - +- x => VariableDoc for test.x [1] + +- x => VariableDoc for epydoc_test.x [1] | +- is_alias = True | +- name = u'x' | +- value | +- GenericValueDoc [2] | +- parse_repr = u'0' - +- y => VariableDoc for test.y [3] + +- y => VariableDoc for epydoc_test.y [3] | +- is_alias = True | +- name = u'y' | +- value | +- GenericValueDoc [2] (defined above) - +- z => VariableDoc for test.z [4] + +- z => VariableDoc for epydoc_test.z [4] +- is_alias = False +- name = u'z' +- value @@ -197,10 +197,10 @@ ... x = 33 ... """, ... attribs="variables name value parse_repr") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- parse_repr = <UNKNOWN> +- variables - +- x => VariableDoc for test.x [1] + +- x => VariableDoc for epydoc_test.x [1] +- name = u'x' +- value +- GenericValueDoc [2] @@ -216,17 +216,17 @@ ... self.bar = 0 ... """, ... attribs="variables name value") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- Foo => VariableDoc for test.Foo [1] + +- Foo => VariableDoc for epydoc_test.Foo [1] +- name = u'Foo' +- value - +- ClassDoc for test.Foo [2] + +- ClassDoc for epydoc_test.Foo [2] +- variables - +- __init__ => VariableDoc for test.Foo.__init__ [3] + +- __init__ => VariableDoc for epydoc_test.Foo.__init__ [3] +- name = u'__init__' +- value - +- RoutineDoc for test.Foo.__init__ [4] + +- RoutineDoc for epydoc_test.Foo.__init__ [4] Module Control Blocks ===================== @@ -256,15 +256,15 @@ ... else: ... else_gated = 'z'""", ... attribs="variables name") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- elif_gated => VariableDoc for test.elif_gated [1] + +- elif_gated => VariableDoc for epydoc_test.elif_gated [1] | +- name = u'elif_gated' - +- elif_gated2 => VariableDoc for test.elif_gated2 [2] + +- elif_gated2 => VariableDoc for epydoc_test.elif_gated2 [2] | +- name = u'elif_gated2' - +- else_gated => VariableDoc for test.else_gated [3] + +- else_gated => VariableDoc for epydoc_test.else_gated [3] | +- name = u'else_gated' - +- if_gated => VariableDoc for test.if_gated [4] + +- if_gated => VariableDoc for epydoc_test.if_gated [4] +- name = u'if_gated' >>> # DocParser looks inside try/except and try/finally blocks: @@ -279,15 +279,15 @@ ... finally: ... finally_gated = 'z'""", ... attribs="variables name") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- except_gated => VariableDoc for test.except_gated [1] + +- except_gated => VariableDoc for epydoc_test.except_gated [1] | +- name = u'except_gated' - +- except_gated2 => VariableDoc for test.except_gated2 [2] + +- except_gated2 => VariableDoc for epydoc_test.except_gated2 [2] | +- name = u'except_gated2' - +- finally_gated => VariableDoc for test.finally_gated [3] + +- finally_gated => VariableDoc for epydoc_test.finally_gated [3] | +- name = u'finally_gated' - +- try_gated => VariableDoc for test.try_gated [4] + +- try_gated => VariableDoc for epydoc_test.try_gated [4] +- name = u'try_gated' >>> # By default, DocParser does not look inside for blocks @@ -295,7 +295,7 @@ ... for itervar in [5]*3: ... for_gated = 'x'""", ... attribs="variables name") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables = {} >>> # By default, DocParser does not look inside while blocks @@ -303,7 +303,7 @@ ... while condition: ... while_gated = 'x'""", ... attribs="variables name") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables = {} The set of blocks that DocParser looks inside are controlled by a set @@ -318,20 +318,20 @@ ... for itervar in [5]*3: ... for_gated = 'x'""", ... attribs="variables name") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- for_gated => VariableDoc for test.for_gated [1] + +- for_gated => VariableDoc for epydoc_test.for_gated [1] | +- name = u'for_gated' - +- itervar => VariableDoc for test.itervar [2] + +- itervar => VariableDoc for epydoc_test.itervar [2] +- name = u'itervar' >>> runparser(s=""" ... while condition: ... while_gated = 'x'""", ... attribs="variables name") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- while_gated => VariableDoc for test.while_gated [1] + +- while_gated => VariableDoc for epydoc_test.while_gated [1] +- name = u'while_gated' >>> # reset the globals: @@ -353,20 +353,20 @@ ... '''docstring for x. ... (can be multiline)'''""", ... attribs="variables name docstring") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- docstring = <UNKNOWN> +- variables - +- x => VariableDoc for test.x [1] + +- x => VariableDoc for epydoc_test.x [1] +- docstring = u'docstring for x.\n(can be multiline)' +- name = u'x' >>> runparser(s=""" ... x = 12 #: comment docstring for x""", ... attribs="variables name docstring") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- docstring = <UNKNOWN> +- variables - +- x => VariableDoc for test.x [1] + +- x => VariableDoc for epydoc_test.x [1] +- docstring = u'comment docstring for x' +- name = u'x' @@ -375,10 +375,10 @@ ... #: (can be multiline) ... x = 12""", ... attribs="variables name docstring") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- docstring = <UNKNOWN> +- variables - +- x => VariableDoc for test.x [1] + +- x => VariableDoc for epydoc_test.x [1] +- docstring = u'comment docstring for x.\n(can be m... +- name = u'x' @@ -390,10 +390,10 @@ ... x = 12 #: comment2 ... '''string'''""", ... attribs="variables name docstring") - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- docstring = <UNKNOWN> +- variables - +- x => VariableDoc for test.x [1] + +- x => VariableDoc for epydoc_test.x [1] +- docstring = u'string' +- name = u'x' @@ -408,8 +408,8 @@ ... 'docstring for f' ... print 'inside f' ... """, show="f", exclude='defining_module') - RoutineDoc for test.f [0] - +- canonical_name = DottedName('test', u'f') + RoutineDoc for epydoc_test.f [0] + +- canonical_name = DottedName('epydoc_test', u'f') +- decorators = [] +- docs_extracted_by = 'parser' +- docstring = u'docstring for f' @@ -433,8 +433,8 @@ ... 'docstring for f' ... print 'inside f' ... """, show="f", exclude='defining_module') - RoutineDoc for test.f [0] - +- canonical_name = DottedName('test', u'f') + RoutineDoc for epydoc_test.f [0] + +- canonical_name = DottedName('epydoc_test', u'f') +- decorators = [] +- docs_extracted_by = 'parser' +- docstring = u'docstring for f' @@ -449,8 +449,8 @@ >>> runparser(s=""" ... def f( (x, (y,z)) ): pass ... """, show="f", exclude='defining_module') - RoutineDoc for test.f [0] - +- canonical_name = DottedName('test', u'f') + RoutineDoc for epydoc_test.f [0] + +- canonical_name = DottedName('epydoc_test', u'f') +- decorators = [] +- docs_extracted_by = 'parser' +- kwarg = None @@ -467,13 +467,13 @@ ... def f(cls, x): 'docstring for f' ... """, ... attribs='variables value docstring posargs') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- docstring = <UNKNOWN> +- variables - +- f => VariableDoc for test.f [1] + +- f => VariableDoc for epydoc_test.f [1] +- docstring = <UNKNOWN> +- value - +- ClassMethodDoc for test.f [2] + +- ClassMethodDoc for epydoc_test.f [2] +- docstring = u'docstring for f' +- posargs = [u'cls', u'x'] @@ -492,68 +492,68 @@ ... class Z(B.__bases__[0]): "calculated base" # not handled! ... """, ... attribs='variables value bases docstring') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- docstring = <UNKNOWN> +- variables - +- A => VariableDoc for test.A [1] + +- A => VariableDoc for epydoc_test.A [1] | +- docstring = <UNKNOWN> | +- value - | +- ClassDoc for test.A [2] + | +- ClassDoc for epydoc_test.A [2] | +- bases = [] | +- docstring = u'no bases' | +- variables - | +- Nested => VariableDoc for test.A.Nested [3] + | +- Nested => VariableDoc for epydoc_test.A.Nested [3] | +- docstring = <UNKNOWN> | +- value - | +- ClassDoc for test.A.Nested [4] + | +- ClassDoc for epydoc_test.A.Nested [4] | +- bases = [] | +- docstring = u'nested class' | +- variables = {} - +- B => VariableDoc for test.B [5] + +- B => VariableDoc for epydoc_test.B [5] | +- docstring = <UNKNOWN> | +- value - | +- ClassDoc for test.B [6] + | +- ClassDoc for epydoc_test.B [6] | +- bases - | | +- ClassDoc for test.A [2] (defined above) + | | +- ClassDoc for epydoc_test.A [2] (defined above) | +- docstring = u'single base' | +- variables = {} - +- C => VariableDoc for test.C [7] + +- C => VariableDoc for epydoc_test.C [7] | +- docstring = <UNKNOWN> | +- value - | +- ClassDoc for test.C [8] + | +- ClassDoc for epydoc_test.C [8] | +- bases - | | +- ClassDoc for test.A [2] (defined above) - | | +- ClassDoc for test.B [6] (defined above) + | | +- ClassDoc for epydoc_test.A [2] (defined above) + | | +- ClassDoc for epydoc_test.B [6] (defined above) | +- docstring = u'multiple bases' | +- variables = {} - +- D => VariableDoc for test.D [9] + +- D => VariableDoc for epydoc_test.D [9] | +- docstring = <UNKNOWN> | +- value - | +- ClassDoc for test.D [10] + | +- ClassDoc for epydoc_test.D [10] | +- bases - | | +- ClassDoc for test.A [2] (defined above) + | | +- ClassDoc for epydoc_test.A [2] (defined above) | +- docstring = u'extra parens around base' | +- variables = {} - +- E => VariableDoc for test.E [11] + +- E => VariableDoc for epydoc_test.E [11] | +- docstring = <UNKNOWN> | +- value - | +- ClassDoc for test.E [12] + | +- ClassDoc for epydoc_test.E [12] | +- bases - | | +- ClassDoc for test.A.Nested [4] (defined above) + | | +- ClassDoc for epydoc_test.A.Nested [4] (defined above) | +- docstring = u'dotted name' | +- variables = {} - +- F => VariableDoc for test.F [13] + +- F => VariableDoc for epydoc_test.F [13] | +- docstring = <UNKNOWN> | +- value - | +- ClassDoc for test.F [14] + | +- ClassDoc for epydoc_test.F [14] | +- bases - | | +- ClassDoc for test.A.Nested [4] (defined above) + | | +- ClassDoc for epydoc_test.A.Nested [4] (defined above) | +- docstring = u'parens with dotted name' | +- variables = {} - +- Z => VariableDoc for test.Z [15] + +- Z => VariableDoc for epydoc_test.Z [15] +- docstring = <UNKNOWN> +- value - +- ClassDoc for test.Z [16] + +- ClassDoc for epydoc_test.Z [16] +- bases = <UNKNOWN> +- docstring = u'calculated base' +- variables = {} @@ -572,10 +572,10 @@ ... del y ... """, ... attribs='variables value parse_repr is_alias') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- parse_repr = <UNKNOWN> +- variables - +- x => VariableDoc for test.x [1] + +- x => VariableDoc for epydoc_test.x [1] +- is_alias = True +- value +- GenericValueDoc [2] @@ -595,9 +595,9 @@ ... del [[[[f]]]] ... """, ... attribs='variables') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- g => VariableDoc for test.g [1] + +- g => VariableDoc for epydoc_test.g [1] >>> runparser(s=""" ... a=b=c=d=e=f=g=1 ... del a,b @@ -605,17 +605,17 @@ ... del [e,f] ... """, ... attribs='variables') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- g => VariableDoc for test.g [1] + +- g => VariableDoc for epydoc_test.g [1] >>> runparser(s=""" ... a=b=c=d=e=f=g=1 ... del ((a, (((((b, c)), d), [e]))), f) ... """, ... attribs='variables') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- g => VariableDoc for test.g [1] + +- g => VariableDoc for epydoc_test.g [1] The right-hand side of a `del` statement may contain a dotted name, in which case the named variable should be deleted from its containing @@ -626,13 +626,13 @@ ... del A.a ... """, ... attribs='variables value local_variables') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- A => VariableDoc for test.A [1] + +- A => VariableDoc for epydoc_test.A [1] +- value - +- ClassDoc for test.A [2] + +- ClassDoc for epydoc_test.A [2] +- variables - +- b => VariableDoc for test.A.b [3] + +- b => VariableDoc for epydoc_test.A.b [3] +- value +- GenericValueDoc [4] @@ -647,9 +647,9 @@ ... del ([b], a[1]) ... """, ... attribs='variables') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- a => VariableDoc for test.a [1] + +- a => VariableDoc for epydoc_test.a [1] Single-Line Blocks ================== @@ -660,13 +660,13 @@ ... ... """, ... attribs='variables value docstring') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- docstring = <UNKNOWN> +- variables - +- A => VariableDoc for test.A [1] + +- A => VariableDoc for epydoc_test.A [1] +- docstring = <UNKNOWN> +- value - +- ClassDoc for test.A [2] + +- ClassDoc for epydoc_test.A [2] +- docstring = u'docstring for A' +- variables = {} @@ -678,12 +678,12 @@ ... from re import match ... """, ... attribs='variables value is_imported') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- match => VariableDoc for test.match [1] + +- match => VariableDoc for epydoc_test.match [1] | +- is_imported = True | +- value = <UNKNOWN> - +- re => VariableDoc for test.re [2] + +- re => VariableDoc for epydoc_test.re [2] +- is_imported = True +- value = <UNKNOWN> @@ -691,15 +691,15 @@ ... from re import match as much, split, sub as scuba ... """, ... attribs='variables name imported_from') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- much => VariableDoc for test.much [1] + +- much => VariableDoc for epydoc_test.much [1] | +- imported_from = DottedName(u're', u'match') | +- name = u'much' - +- scuba => VariableDoc for test.scuba [2] + +- scuba => VariableDoc for epydoc_test.scuba [2] | +- imported_from = DottedName(u're', u'sub') | +- name = u'scuba' - +- split => VariableDoc for test.split [3] + +- split => VariableDoc for epydoc_test.split [3] +- imported_from = DottedName(u're', u'split') +- name = u'split' @@ -711,13 +711,13 @@ ... u"unicode in docstring: \u1000" ... """, ... attribs='variables value docstring') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- docstring = <UNKNOWN> +- variables - +- f => VariableDoc for test.f [1] + +- f => VariableDoc for epydoc_test.f [1] +- docstring = <UNKNOWN> +- value - +- RoutineDoc for test.f [2] + +- RoutineDoc for epydoc_test.f [2] +- docstring = u'unicode in docstring: \u1000' Instance Variables @@ -735,27 +735,27 @@ ... ... """, ... attribs='variables value is_instvar docstring local_variables') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- docstring = <UNKNOWN> +- variables - +- A => VariableDoc for test.A [1] + +- A => VariableDoc for epydoc_test.A [1] +- docstring = <UNKNOWN> +- is_instvar = <UNKNOWN> +- value - +- ClassDoc for test.A [2] + +- ClassDoc for epydoc_test.A [2] +- docstring = <UNKNOWN> +- variables - +- __init__ => VariableDoc for test.A.__init__ [3] + +- __init__ => VariableDoc for epydoc_test.A.__init__ [3] | +- docstring = <UNKNOWN> | +- is_instvar = <UNKNOWN> | +- value - | +- RoutineDoc for test.A.__init__ [4] + | +- RoutineDoc for epydoc_test.A.__init__ [4] | +- docstring = <UNKNOWN> - +- y => VariableDoc for test.A.y [5] + +- y => VariableDoc for epydoc_test.A.y [5] | +- docstring = u'docstring for y' | +- is_instvar = True | +- value = <UNKNOWN> - +- z => VariableDoc for test.A.z [6] + +- z => VariableDoc for epydoc_test.A.z [6] +- docstring = u'docstring for z' +- is_instvar = True +- value = <UNKNOWN> @@ -768,13 +768,13 @@ ... A.x = 22 ... """, ... attribs='variables value local_variables') - ModuleDoc for test [0] + ModuleDoc for epydoc_test [0] +- variables - +- A => VariableDoc for test.A [1] + +- A => VariableDoc for epydoc_test.A [1] +- value - +- ClassDoc for test.A [2] + +- ClassDoc for epydoc_test.A [2] +- variables - +- x => VariableDoc for test.A.x [3] + +- x => VariableDoc for epydoc_test.A.x [3] +- value +- GenericValueDoc [4] Modified: trunk/epydoc/src/epydoc/test/epytext.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/epytext.doctest 2007-02-13 14:27:23 UTC (rev 1471) +++ trunk/epydoc/src/epydoc/test/epytext.doctest 2007-02-13 15:27:45 UTC (rev 1472) @@ -295,14 +295,14 @@ ... return (v or '').rstrip() >>> print epytext2html("{1:{2:3}}") - {1:{2:3}} +{1:{2:3}} >>> print epytext2html("C{{1:{2:3}}}") <code>{1:{2:3}}</code> >>> print epytext2html("{1:C{{2:3}}}") {1:<code>{2:3}</code>} >>> print epytext2html("{{{}{}}{}}") - {{{}{}}{}} +{{{}{}}{}} >>> print epytext2html("{{E{lb}E{lb}E{lb}}}") - {{{{{}} +{{{{{}} Property changes on: trunk/epydoc/src/epydoc/test/javadoc.doctest ___________________________________________________________________ Name: svn:eol-style + native Property changes on: trunk/epydoc/src/epydoc/test/plaintext.doctest ___________________________________________________________________ Name: svn:eol-style + native Property changes on: trunk/epydoc/src/epydoc/test/pyval_repr.doctest ___________________________________________________________________ Name: svn:eol-style + native Property changes on: trunk/epydoc/src/epydoc/test/restructuredtext.doctest ___________________________________________________________________ Name: svn:eol-style + native Modified: trunk/epydoc/src/epydoc/test/util.py =================================================================== --- trunk/epydoc/src/epydoc/test/util.py 2007-02-13 14:27:23 UTC (rev 1471) +++ trunk/epydoc/src/epydoc/test/util.py 2007-02-13 15:27:45 UTC (rev 1472) @@ -79,7 +79,7 @@ # Write it to a temp file. tmp_dir = write_pystring_to_tmp_dir(s) # Parse it. - val_doc = parse_docs(out.name) + val_doc = parse_docs(os.path.join(tmp_dir, 'epydoc_test.py')) if show is not None: for name in show.split('.'): if isinstance(val_doc, ClassDoc): @@ -154,9 +154,8 @@ # Build docs for it docindex = build_doc_index([path], introspect, parse) if docindex is None: return - try: del sys.modules['enc_test'] - except: pass - # Write html output. + sys.modules.pop('enc_test', None) + # Write html output. writer = HTMLWriter(docindex, mark_docstrings=True) writer.write(tmp_dir) for file in os.listdir(tmp_dir): @@ -182,7 +181,7 @@ try: os.unlink(os.path.join(tmp_dir, 'epydoc_test.pyc')) except OSError: pass os.rmdir(tmp_dir) - del sys.modules['epydoc_test'] + sys.modules.pop('epydoc_test', None) def to_plain(docstring): """Conver a parsed docstring into plain text""" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-02-13 14:27:25
|
Revision: 1471 http://svn.sourceforge.net/epydoc/?rev=1471&view=rev Author: dvarrazzo Date: 2007-02-13 06:27:23 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - The parse representation is preferred if repr() returns a stock result, i.e. something like '<ClassName instance at 0x12345678>'. - Using LaTeX package fancyhdr instead of the deprecated fancyheadings. - Added missing escaping of LaTeX parameter default. - Dropped parse_repr/pyval_repr check in HTML parameters default. Modified Paths: -------------- trunk/epydoc/src/epydoc/apidoc.py trunk/epydoc/src/epydoc/docwriter/html.py trunk/epydoc/src/epydoc/docwriter/latex.py Modified: trunk/epydoc/src/epydoc/apidoc.py =================================================================== --- trunk/epydoc/src/epydoc/apidoc.py 2007-02-13 14:16:22 UTC (rev 1470) +++ trunk/epydoc/src/epydoc/apidoc.py 2007-02-13 14:27:23 UTC (rev 1471) @@ -794,6 +794,9 @@ UNKNOWN_REPR = "??" """@cvar: The string representation of an unknown value.""" + STOCK_REPR = re.compile(r"(?i)^<.+\bat\b.+[0-9a-f]+.*>$") + """Match the return of repr() for object that didn't customize it.""" + def pyval_repr(self): """Return a string representation of the python value. @@ -812,6 +815,9 @@ if rv is UNKNOWN: rv = self.parse_repr + elif self.STOCK_REPR.match(rv) and self.parse_repr is not UNKNOWN: + rv = self.parse_repr + if rv is UNKNOWN: rv = self.UNKNOWN_REPR Modified: trunk/epydoc/src/epydoc/docwriter/html.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-13 14:16:22 UTC (rev 1470) +++ trunk/epydoc/src/epydoc/docwriter/html.py 2007-02-13 14:27:23 UTC (rev 1471) @@ -2572,12 +2572,9 @@ name = self._arg_name(name) s = '<span class="%s-arg">%s</span>' % (css_class, name) if default is not None: - if default.parse_repr is not UNKNOWN: - s += ('=<span class="%s-default">%s</span>' % - (css_class, plaintext_to_html(default.parse_repr))) - else: - s += ('=<span class="%s-default">%s</span>' % - (css_class, plaintext_to_html(default.pyval_repr()))) + s += ('=<span class="%s-default">%s</span>' % + (css_class, plaintext_to_html( + default.summary_pyval_repr()[0]))) return s def _arg_name(self, arg): Modified: trunk/epydoc/src/epydoc/docwriter/latex.py =================================================================== --- trunk/epydoc/src/epydoc/docwriter/latex.py 2007-02-13 14:16:22 UTC (rev 1470) +++ trunk/epydoc/src/epydoc/docwriter/latex.py 2007-02-13 14:27:23 UTC (rev 1471) @@ -27,7 +27,7 @@ class LatexWriter: PREAMBLE = [ "\\documentclass{article}", - "\\usepackage{alltt, parskip, fancyheadings, boxedminipage}", + "\\usepackage{alltt, parskip, fancyhdr, boxedminipage}", "\\usepackage{makeidx, multirow, longtable, tocbibind, amssymb}", "\\usepackage{fullpage}", "\\usepackage[usenames]{color}", @@ -287,7 +287,7 @@ m = re.match(r'\\usepackage(\[.*?\])?{(.*?)}', line) if m and m.group(2) in ( 'babel', 'hyperref', 'color', 'alltt', 'parskip', - 'fancyheadings', 'boxedminipage', 'makeidx', + 'fancyhdr', 'boxedminipage', 'makeidx', 'multirow', 'longtable', 'tocbind', 'assymb', 'fullpage'): pass @@ -727,7 +727,8 @@ def func_arg(self, name, default): s = '\\textit{%s}' % plaintext_to_latex(self._arg_name(name)) if default is not None: - s += '=\\texttt{%s}' % default.summary_pyval_repr()[0] + s += '=\\texttt{%s}' % plaintext_to_latex( + default.summary_pyval_repr()[0]) return s def _arg_name(self, arg): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dva...@us...> - 2007-02-13 14:16:25
|
Revision: 1470 http://svn.sourceforge.net/epydoc/?rev=1470&view=rev Author: dvarrazzo Date: 2007-02-13 06:16:22 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Docstring fixed. Modified Paths: -------------- trunk/epydoc/src/epydoc/test/__init__.py Modified: trunk/epydoc/src/epydoc/test/__init__.py =================================================================== --- trunk/epydoc/src/epydoc/test/__init__.py 2007-02-13 08:22:43 UTC (rev 1469) +++ trunk/epydoc/src/epydoc/test/__init__.py 2007-02-13 14:16:22 UTC (rev 1470) @@ -35,7 +35,7 @@ def check_requirements(filename): """ - Search for strings of the form: + Search for strings of the form:: [Require: <module>] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 08:22:45
|
Revision: 1469 http://svn.sourceforge.net/epydoc/?rev=1469&view=rev Author: edloper Date: 2007-02-13 00:22:43 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Fixed docstring typo Modified Paths: -------------- trunk/epydoc/src/epydoc/docintrospecter.py Modified: trunk/epydoc/src/epydoc/docintrospecter.py =================================================================== --- trunk/epydoc/src/epydoc/docintrospecter.py 2007-02-13 08:22:28 UTC (rev 1468) +++ trunk/epydoc/src/epydoc/docintrospecter.py 2007-02-13 08:22:43 UTC (rev 1469) @@ -512,7 +512,7 @@ def is_future_feature(object): """ - Return True if C{object} results from a C{from __future__ import feature"} + Return True if C{object} results from a C{from __future__ import feature} statement. """ # Guard from unexpected implementation changes of the __future__ module. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 08:22:29
|
Revision: 1468 http://svn.sourceforge.net/epydoc/?rev=1468&view=rev Author: edloper Date: 2007-02-13 00:22:28 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Warn if @type is used in a bad context. Modified Paths: -------------- trunk/epydoc/src/epydoc/docstringparser.py Modified: trunk/epydoc/src/epydoc/docstringparser.py =================================================================== --- trunk/epydoc/src/epydoc/docstringparser.py 2007-02-13 08:21:20 UTC (rev 1467) +++ trunk/epydoc/src/epydoc/docstringparser.py 2007-02-13 08:22:28 UTC (rev 1468) @@ -641,6 +641,9 @@ if arg in api_doc.arg_types: raise ValueError(REDEFINED % ('type for '+arg)) api_doc.arg_types[arg] = descr + + else: + raise ValueError(BAD_CONTEXT % tag) def process_var_field(api_doc, docindex, tag, arg, descr): _check(api_doc, tag, arg, context=ModuleDoc, expect_arg=True) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 08:21:30
|
Revision: 1467 http://svn.sourceforge.net/epydoc/?rev=1467&view=rev Author: edloper Date: 2007-02-13 00:21:20 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Removed unnecessary <code class="pyval">...</pyval> wrapping element from the output of the PyvalColorizer. Modified Paths: -------------- trunk/epydoc/src/epydoc/markup/pyval_repr.py trunk/epydoc/src/epydoc/test/pyval_repr.doctest Modified: trunk/epydoc/src/epydoc/markup/pyval_repr.py =================================================================== --- trunk/epydoc/src/epydoc/markup/pyval_repr.py 2007-02-13 08:17:33 UTC (rev 1466) +++ trunk/epydoc/src/epydoc/markup/pyval_repr.py 2007-02-13 08:21:20 UTC (rev 1467) @@ -136,8 +136,7 @@ except _Maxlines: state.result.append(self.ELLIPSIS) # Put it all together. - tree = Element('epytext', Element('code', style='pyval', - *state.result)) + tree = Element('epytext', *state.result) return ParsedEpytextDocstring(tree), state.score def _colorize(self, pyval, state): Modified: trunk/epydoc/src/epydoc/test/pyval_repr.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/pyval_repr.doctest 2007-02-13 08:17:33 UTC (rev 1466) +++ trunk/epydoc/src/epydoc/test/pyval_repr.doctest 2007-02-13 08:21:20 UTC (rev 1467) @@ -11,22 +11,22 @@ with no syntax highlighting: >>> color(10) - <code class="pyval">10</code> + 10 >>> color(1./4) - <code class="pyval">0.25</code> + 0.25 >>> color(None) - <code class="pyval">None</code> + None >>> color(100) - <code class="pyval">100</code> + 100 Long ints will get wrapped if they're big enough: >>> color(10000000) - <code class="pyval">10000000</code> + 10000000 >>> color(10**90) - <code class="pyval">1000000000000000000000000000000000000000↵ + 1000000000000000000000000000000000000000↵ 0000000000000000000000000000000000000000↵ - 00000000000</code> + 00000000000 >>> print '-'*40+'\n'+colorizer.colorize(10**90).to_plaintext(None) ---------------------------------------- 1000000000000000000000000000000000000000\ @@ -39,37 +39,37 @@ escaped using the 'string-escape' encoding. >>> color(''.join(chr(i) for i in range(256))) - <code class="pyval"><code class="val-quote">'''</code><code class="val-string">\x00\x01\x02\x03\x04\x05\x06\x07\x08\</code>↵ + <code class="val-quote">'''</code><code class="val-string">\x00\x01\x02\x03\x04\x05\x06\x07\x08\</code>↵ <code class="val-string">t</code> <code class="val-string">\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x</code>↵ <code class="val-string">15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x</code>↵ <code class="val-string">1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCD</code>↵ - <code class="ellipsis">...</code></code> + <code class="ellipsis">...</code> Currently, the "'" quote is always used, because that's what the 'string-escape' encoding expects. >>> color('Hello') - <code class="pyval"><code class="val-quote">'</code><code class="val-string">Hello</code><code class="val-quote">'</code></code> + <code class="val-quote">'</code><code class="val-string">Hello</code><code class="val-quote">'</code> >>> color('"Hello"') - <code class="pyval"><code class="val-quote">'</code><code class="val-string">"Hello"</code><code class="val-quote">'</code></code> + <code class="val-quote">'</code><code class="val-string">"Hello"</code><code class="val-quote">'</code> >>> color("'Hello'") - <code class="pyval"><code class="val-quote">'</code><code class="val-string">\'Hello\'</code><code class="val-quote">'</code></code> + <code class="val-quote">'</code><code class="val-string">\'Hello\'</code><code class="val-quote">'</code> Strings containing newlines are automatically rendered as multiline strings. >>> color("This\n is a multiline\n string!") - <code class="pyval"><code class="val-quote">'''</code><code class="val-string">This</code> + <code class="val-quote">'''</code><code class="val-string">This</code> <code class="val-string"> is a multiline</code> - <code class="val-string"> string!</code><code class="val-quote">'''</code></code> + <code class="val-string"> string!</code><code class="val-quote">'''</code> Unicode strings are handled properly. >>> color(u"Hello world") - <code class="pyval"><code class="val-quote">u'</code><code class="val-string">Hello world</code><code class="val-quote">'</code></code> + <code class="val-quote">u'</code><code class="val-string">Hello world</code><code class="val-quote">'</code> >>> color(u"\uaaaa And \ubbbb") - <code class="pyval"><code class="val-quote">u'</code><code class="val-string">\uaaaa And \ubbbb</code><code class="val-quote">'</code></code> + <code class="val-quote">u'</code><code class="val-string">\uaaaa And \ubbbb</code><code class="val-quote">'</code> Lists, Tuples, etc. =================== @@ -79,28 +79,28 @@ listed on a separate line, indented by the size of the open-bracket. >>> color(range(10)) - <code class="pyval"><code class="val-group">[</code>0<code class="val-op">, </code>1<code class="val-op">, </code>2<code class="val-op">, </code>3<code class="val-op">, </code>4<code class="val-op">, </code>5<code class="val-op">, </code>6<code class="val-op">, </code>7<code class="val-op">, </code>8<code class="val-op">, </code>9<code class="val-group">]</code></code> + <code class="val-group">[</code>0<code class="val-op">, </code>1<code class="val-op">, </code>2<code class="val-op">, </code>3<code class="val-op">, </code>4<code class="val-op">, </code>5<code class="val-op">, </code>6<code class="val-op">, </code>7<code class="val-op">, </code>8<code class="val-op">, </code>9<code class="val-group">]</code> >>> color(range(100)) - <code class="pyval"><code class="val-group">[</code>0<code class="val-op">,</code> + <code class="val-group">[</code>0<code class="val-op">,</code> 1<code class="val-op">,</code> 2<code class="val-op">,</code> 3<code class="val-op">,</code> 4<code class="val-op">,</code> - <code class="ellipsis">...</code></code> + <code class="ellipsis">...</code> >>> color([1,2,[5,6,[(11,22,33),9],10],11]+[99,98,97,96,95]) - <code class="pyval"><code class="val-group">[</code>1<code class="val-op">,</code> + <code class="val-group">[</code>1<code class="val-op">,</code> 2<code class="val-op">,</code> <code class="val-group">[</code>5<code class="val-op">, </code>6<code class="val-op">, </code><code class="val-group">[</code><code class="val-group">(</code>11<code class="val-op">, </code>22<code class="val-op">, </code>33<code class="val-group">)</code><code class="val-op">, </code>9<code class="val-group">]</code><code class="val-op">, </code>10<code class="val-group">]</code><code class="val-op">,</code> 11<code class="val-op">,</code> 99<code class="val-op">,</code> - <code class="ellipsis">...</code></code> + <code class="ellipsis">...</code> >>> color(set(range(20))) - <code class="pyval"><code class="val-group">set([</code>0<code class="val-op">,</code> + <code class="val-group">set([</code>0<code class="val-op">,</code> 1<code class="val-op">,</code> 2<code class="val-op">,</code> 3<code class="val-op">,</code> 4<code class="val-op">,</code> - <code class="ellipsis">...</code></code> + <code class="ellipsis">...</code> Dictionaries ============ @@ -108,12 +108,12 @@ "op". >>> color({1:33, 2:[1,2,3,{7:'oo'*20}]}) - <code class="pyval"><code class="val-group">{</code>1<code class="val-op">: </code>33<code class="val-op">,</code> + <code class="val-group">{</code>1<code class="val-op">: </code>33<code class="val-op">,</code> 2<code class="val-op">: </code><code class="val-group">[</code>1<code class="val-op">,</code> 2<code class="val-op">,</code> 3<code class="val-op">,</code> <code class="val-group">{</code>7<code class="val-op">: </code><code class="val-quote">'</code><code class="val-string">oooooooooooooooooooooooooooooo</code>↵ - <code class="ellipsis">...</code></code> + <code class="ellipsis">...</code> Regular Expressions =================== @@ -131,67 +131,67 @@ >>> # Literal characters >>> color_re(u'abc \t\r\n\f\v \xff \uffff \U000fffff', False) - <code class="pyval">abc \t\r\n\f\v \xff \uffff \U000fffff</code> + abc \t\r\n\f\v \xff \uffff \U000fffff >>> color_re(r'\.\^\$\\\*\+\?\{\}\[\]\|\(\)') - <code class="pyval">\.\^\$\\\*\+\?\{\}\[\]\|\(\)</code> + \.\^\$\\\*\+\?\{\}\[\]\|\(\) >>> # Any character & character classes >>> color_re(r".\d\D\s\S\w\W\A^$\b\B\Z") - <code class="pyval">.\d\D\s\S\w\W\A^$\b\B\Z</code> + .\d\D\s\S\w\W\A^$\b\B\Z >>> # Branching >>> color_re(r"foo|bar") - <code class="pyval">foo<code class="re-op">|</code>bar</code> + foo<code class="re-op">|</code>bar >>> # Character classes >>> color_re(r"[abcd]") - <code class="pyval"><code class="re-group">[</code>abcd<code class="re-group">]</code></code> + <code class="re-group">[</code>abcd<code class="re-group">]</code> >>> # Repeats >>> color_re(r"a*b+c{4,}d{,5}e{3,9}f?") - <code class="pyval">a<code class="re-op">*</code>b<code class="re-op">+</code>c<code class="re-op">{4,}</code>d<code class="re-op">{,5}</code>e<code class="re-op">{3,9}</code>f<code class="re-op">?</code></code> + a<code class="re-op">*</code>b<code class="re-op">+</code>c<code class="re-op">{4,}</code>d<code class="re-op">{,5}</code>e<code class="re-op">{3,9}</code>f<code class="re-op">?</code> >>> color_re(r"a*?b+?c{4,}?d{,5}?e{3,9}?f??") - <code class="pyval">a<code class="re-op">*?</code>b<code class="re-op">+?</code>c<code class="re-op">{4,}?</code>d<code class="re-op">{,5}?</code>e<code class="re-op">{3,9}?</code>f<code class="re-op">??</code></code> + a<code class="re-op">*?</code>b<code class="re-op">+?</code>c<code class="re-op">{4,}?</code>d<code class="re-op">{,5}?</code>e<code class="re-op">{3,9}?</code>f<code class="re-op">??</code> >>> # Subpatterns >>> color_re(r"(foo (bar) | (baz))") - <code class="pyval"><code class="re-group">(</code>foo <code class="re-group">(</code>bar<code class="re-group">)</code> <code class="re-op">|</code> <code class="re-group">(</code>baz<code class="re-group">)</code><code class="re-group">)</code></code> + <code class="re-group">(</code>foo <code class="re-group">(</code>bar<code class="re-group">)</code> <code class="re-op">|</code> <code class="re-group">(</code>baz<code class="re-group">)</code><code class="re-group">)</code> >>> color_re(r"(?:foo (?:bar) | (?:baz))") - <code class="pyval"><code class="re-group">(?:</code>foo <code class="re-group">(?:</code>bar<code class="re-group">)</code> <code class="re-op">|</code> <code class="re-group">(?:</code>baz<code class="re-group">)</code><code class="re-group">)</code></code> + <code class="re-group">(?:</code>foo <code class="re-group">(?:</code>bar<code class="re-group">)</code> <code class="re-op">|</code> <code class="re-group">(?:</code>baz<code class="re-group">)</code><code class="re-group">)</code> >>> color_re("(foo (?P<a>bar) | (?P<boop>baz))") - <code class="pyval"><code class="re-group">(</code>foo <code class="re-group">(?P<</code><code class="re-ref">a</code><code class="re-group">></code>bar<code class="re-group">)</code> <code class="re-op">|</code> <code class="re-group">(?P<</code><code class="re-ref">boop</code><code class="re-group">></code>baz<code class="re-group">)</code><code class="re-group">)</code></code> + <code class="re-group">(</code>foo <code class="re-group">(?P<</code><code class="re-ref">a</code><code class="re-group">></code>bar<code class="re-group">)</code> <code class="re-op">|</code> <code class="re-group">(?P<</code><code class="re-ref">boop</code><code class="re-group">></code>baz<code class="re-group">)</code><code class="re-group">)</code> >>> # Group References >>> color_re(r"(...) and (\1)") - <code class="pyval"><code class="re-group">(</code>...<code class="re-group">)</code> and <code class="re-group">(</code><code class="re-ref">\1</code><code class="re-group">)</code></code> + <code class="re-group">(</code>...<code class="re-group">)</code> and <code class="re-group">(</code><code class="re-ref">\1</code><code class="re-group">)</code> >>> # Ranges >>> color_re(r"[a-bp-z]") - <code class="pyval"><code class="re-group">[</code>a<code class="re-op">-</code>bp<code class="re-op">-</code>z<code class="re-group">]</code></code> + <code class="re-group">[</code>a<code class="re-op">-</code>bp<code class="re-op">-</code>z<code class="re-group">]</code> >>> color_re(r"[^a-bp-z]") - <code class="pyval"><code class="re-group">[</code><code class="re-op">^</code>a<code class="re-op">-</code>bp<code class="re-op">-</code>z<code class="re-group">]</code></code> + <code class="re-group">[</code><code class="re-op">^</code>a<code class="re-op">-</code>bp<code class="re-op">-</code>z<code class="re-group">]</code> >>> color_re(r"[^abc]") - <code class="pyval"><code class="re-group">[</code><code class="re-op">^</code>abc<code class="re-group">]</code></code> + <code class="re-group">[</code><code class="re-op">^</code>abc<code class="re-group">]</code> >>> # Lookahead/behinds >>> color_re(r"foo(?=bar)") - <code class="pyval">foo<code class="re-group">(?=</code>bar<code class="re-group">)</code></code> + foo<code class="re-group">(?=</code>bar<code class="re-group">)</code> >>> color_re(r"foo(?!bar)") - <code class="pyval">foo<code class="re-group">(?!</code>bar<code class="re-group">)</code></code> + foo<code class="re-group">(?!</code>bar<code class="re-group">)</code> >>> color_re(r"(?<=bar)foo") - <code class="pyval"><code class="re-group">(?<=</code>bar<code class="re-group">)</code>foo</code> + <code class="re-group">(?<=</code>bar<code class="re-group">)</code>foo >>> color_re(r"(?<!bar)foo") - <code class="pyval"><code class="re-group">(?<!</code>bar<code class="re-group">)</code>foo</code> + <code class="re-group">(?<!</code>bar<code class="re-group">)</code>foo >>> # Flags >>> color_re(r"(?im)^Food") - <code class="pyval"><code class="re-flags">(?im)</code>^Food</code> + <code class="re-flags">(?im)</code>^Food >>> color_re(r"(?Limsx)^Food") - <code class="pyval"><code class="re-flags">(?Limsx)</code>^Food</code> + <code class="re-flags">(?Limsx)</code>^Food >>> color_re(r"(?Limstux)^Food") - <code class="pyval"><code class="re-flags">(?Limstux)</code>^Food</code> + <code class="re-flags">(?Limstux)</code>^Food >>> color_re(r"(?x)This is verbose", False) - <code class="pyval"><code class="re-flags">(?x)</code>Thisisverbose</code> + <code class="re-flags">(?x)</code>Thisisverbose Representation Scores ===================== This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-13 08:17:38
|
Revision: 1466 http://svn.sourceforge.net/epydoc/?rev=1466&view=rev Author: edloper Date: 2007-02-13 00:17:33 -0800 (Tue, 13 Feb 2007) Log Message: ----------- - Modified pyval_repr.py so now it generates a ParsedEpydocDocstring as its output. This should make it possible to change APIDoc.pyval_repr to return a ParsedDocstring instead of a str. This ParsedDocstring would be the result of colorization via pyval_repr, with the parsed repr as a fallback. Modified Paths: -------------- trunk/epydoc/src/epydoc/markup/epytext.py trunk/epydoc/src/epydoc/markup/pyval_repr.py trunk/epydoc/src/epydoc/test/pyval_repr.doctest Modified: trunk/epydoc/src/epydoc/markup/epytext.py =================================================================== --- trunk/epydoc/src/epydoc/markup/epytext.py 2007-02-12 06:54:25 UTC (rev 1465) +++ trunk/epydoc/src/epydoc/markup/epytext.py 2007-02-13 08:17:33 UTC (rev 1466) @@ -67,7 +67,7 @@ <!ELEMENT tag (#PCDATA)> <!ELEMENT arg (#PCDATA)> - <!ELEMENT literalblock (#PCDATA)> + <!ELEMENT literalblock (#PCDATA | %colorized;)*> <!ELEMENT doctestblock (#PCDATA)> <!ELEMENT ulist (li+)> @@ -86,6 +86,7 @@ <!ELEMENT italic (#PCDATA | %colorized;)*> <!ELEMENT bold (#PCDATA | %colorized;)*> <!ELEMENT indexed (#PCDATA | %colorized;)> + <!ATTLIST code style CDATA #IMPLIED> <!ELEMENT symbol (#PCDATA)> @@ -1270,6 +1271,10 @@ return '%s{%s}' % (tag, childstr) raise ValueError('Unknown DOM element %r' % tree.tag) +SYMBOL_TO_PLAINTEXT = { + 'crarr': '\\', + } + def to_plaintext(tree, indent=0, seclevel=0): """ Convert a DOM document encoding epytext to a string representation. @@ -1344,7 +1349,7 @@ # if child.count('\n') > 2: return childstr return childstr.replace('\n\n', '\n')+'\n' elif tree.tag == 'symbol': - return '%s' % childstr + return '%s' % SYMBOL_TO_PLAINTEXT.get(childstr, childstr) elif tree.tag == 'graph': return '<<%s graph: %s>>' % (variables[0], ', '.join(variables[1:])) else: @@ -1606,47 +1611,47 @@ class ParsedEpytextDocstring(ParsedDocstring): SYMBOL_TO_HTML = { # Symbols - '<-': 'larr', '->': 'rarr', '^': 'uarr', 'v': 'darr', + '<-': '←', '->': '→', '^': '↑', 'v': '↓', # Greek letters - 'alpha': 'alpha', 'beta': 'beta', 'gamma': 'gamma', - 'delta': 'delta', 'epsilon': 'epsilon', 'zeta': 'zeta', - 'eta': 'eta', 'theta': 'theta', 'iota': 'iota', - 'kappa': 'kappa', 'lambda': 'lambda', 'mu': 'mu', - 'nu': 'nu', 'xi': 'xi', 'omicron': 'omicron', - 'pi': 'pi', 'rho': 'rho', 'sigma': 'sigma', - 'tau': 'tau', 'upsilon': 'upsilon', 'phi': 'phi', - 'chi': 'chi', 'psi': 'psi', 'omega': 'omega', - 'Alpha': 'Alpha', 'Beta': 'Beta', 'Gamma': 'Gamma', - 'Delta': 'Delta', 'Epsilon': 'Epsilon', 'Zeta': 'Zeta', - 'Eta': 'Eta', 'Theta': 'Theta', 'Iota': 'Iota', - 'Kappa': 'Kappa', 'Lambda': 'Lambda', 'Mu': 'Mu', - 'Nu': 'Nu', 'Xi': 'Xi', 'Omicron': 'Omicron', - 'Pi': 'Pi', 'Rho': 'Rho', 'Sigma': 'Sigma', - 'Tau': 'Tau', 'Upsilon': 'Upsilon', 'Phi': 'Phi', - 'Chi': 'Chi', 'Psi': 'Psi', 'Omega': 'Omega', + 'alpha': 'α', 'beta': 'β', 'gamma': 'γ', + 'delta': 'δ', 'epsilon': 'ε', 'zeta': 'ζ', + 'eta': 'η', 'theta': 'θ', 'iota': 'ι', + 'kappa': 'κ', 'lambda': 'λ', 'mu': 'μ', + 'nu': 'ν', 'xi': 'ξ', 'omicron': 'ο', + 'pi': 'π', 'rho': 'ρ', 'sigma': 'σ', + 'tau': 'τ', 'upsilon': 'υ', 'phi': 'φ', + 'chi': 'χ', 'psi': 'ψ', 'omega': 'ω', + 'Alpha': 'Α', 'Beta': 'Β', 'Gamma': 'Γ', + 'Delta': 'Δ', 'Epsilon': 'Ε', 'Zeta': 'Ζ', + 'Eta': 'Η', 'Theta': 'Θ', 'Iota': 'Ι', + 'Kappa': 'Κ', 'Lambda': 'Λ', 'Mu': 'Μ', + 'Nu': 'Ν', 'Xi': 'Ξ', 'Omicron': 'Ο', + 'Pi': 'Π', 'Rho': 'Ρ', 'Sigma': 'Σ', + 'Tau': 'Τ', 'Upsilon': 'Υ', 'Phi': 'Φ', + 'Chi': 'Χ', 'Psi': 'Ψ', 'Omega': 'Ω', # HTML character entities - 'larr': 'larr', 'rarr': 'rarr', 'uarr': 'uarr', - 'darr': 'darr', 'harr': 'harr', 'crarr': 'crarr', - 'lArr': 'lArr', 'rArr': 'rArr', 'uArr': 'uArr', - 'dArr': 'dArr', 'hArr': 'hArr', - 'copy': 'copy', 'times': 'times', 'forall': 'forall', - 'exist': 'exist', 'part': 'part', - 'empty': 'empty', 'isin': 'isin', 'notin': 'notin', - 'ni': 'ni', 'prod': 'prod', 'sum': 'sum', - 'prop': 'prop', 'infin': 'infin', 'ang': 'ang', - 'and': 'and', 'or': 'or', 'cap': 'cap', 'cup': 'cup', - 'int': 'int', 'there4': 'there4', 'sim': 'sim', - 'cong': 'cong', 'asymp': 'asymp', 'ne': 'ne', - 'equiv': 'equiv', 'le': 'le', 'ge': 'ge', - 'sub': 'sub', 'sup': 'sup', 'nsub': 'nsub', - 'sube': 'sube', 'supe': 'supe', 'oplus': 'oplus', - 'otimes': 'otimes', 'perp': 'perp', + 'larr': '←', 'rarr': '→', 'uarr': '↑', + 'darr': '↓', 'harr': '↔', 'crarr': '↵', + 'lArr': '⇐', 'rArr': '⇒', 'uArr': '⇑', + 'dArr': '⇓', 'hArr': '⇔', + 'copy': '©', 'times': '×', 'forall': '∀', + 'exist': '∃', 'part': '∂', + 'empty': '∅', 'isin': '∈', 'notin': '∉', + 'ni': '∋', 'prod': '∏', 'sum': '∑', + 'prop': '∝', 'infin': '∞', 'ang': '∠', + 'and': '∧', 'or': '∨', 'cap': '∩', 'cup': '∪', + 'int': '∫', 'there4': '∴', 'sim': '∼', + 'cong': '≅', 'asymp': '≈', 'ne': '≠', + 'equiv': '≡', 'le': '≤', 'ge': '≥', + 'sub': '⊂', 'sup': '⊃', 'nsub': '⊄', + 'sube': '⊆', 'supe': '⊇', 'oplus': '⊕', + 'otimes': '⊗', 'perp': '⊥', # Alternate (long) names - 'infinity': 'infin', 'integral': 'int', 'product': 'prod', - '<=': 'le', '>=': 'ge', + 'infinity': '∞', 'integral': '∫', 'product': '∏', + '<=': '≤', '>=': '≥', } SYMBOL_TO_LATEX = { @@ -1709,6 +1714,9 @@ # Caching: self._html = self._latex = self._plaintext = None self._terms = None + + def __str__(self): + return str(self._tree) def to_html(self, docstring_linker, directory=None, docindex=None, context=None, **options): @@ -1776,7 +1784,11 @@ if tree.tag == 'para': return wordwrap('<p>%s</p>' % childstr, indent) elif tree.tag == 'code': - return '<code>%s</code>' % childstr + style = tree.attribs.get('style') + if style: + return '<code class="%s">%s</code>' % (style, childstr) + else: + return '<code>%s</code>' % childstr elif tree.tag == 'uri': return ('<a href="%s" target="_top">%s</a>' % (variables[1], variables[0])) @@ -1815,10 +1827,7 @@ return childstr 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 '[??]' + return self.SYMBOL_TO_HTML.get(symbol, '[%s]' % symbol) elif tree.tag == 'graph': # Generate the graph. graph = self._build_graph(variables[0], variables[1:], linker, @@ -1940,10 +1949,7 @@ ' '*indent + '\\end{itemize}\n\n') 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 '[??]' + return self.SYMBOL_TO_LATEX.get(symbol, '[%s]' % symbol) elif tree.tag == 'graph': return '(GRAPH)' #raise ValueError, 'graph not implemented yet for latex' Modified: trunk/epydoc/src/epydoc/markup/pyval_repr.py =================================================================== --- trunk/epydoc/src/epydoc/markup/pyval_repr.py 2007-02-12 06:54:25 UTC (rev 1465) +++ trunk/epydoc/src/epydoc/markup/pyval_repr.py 2007-02-13 08:17:33 UTC (rev 1466) @@ -20,6 +20,10 @@ number of lines (which should make it faster than pprint for large values). It does I{not} bother to do automatic cycle detection, because maxlines is typically around 5, so it's really not worth it. + +The syntax-highlighted output is encoded using a +L{ParsedEpydocDocstring}, which can then be used to generate output in +a variety of formats. """ # Implementation note: we use exact tests for classes (list, etc) @@ -29,9 +33,12 @@ import types, re import epydoc.apidoc from epydoc.util import decode_with_backslashreplace +from epydoc.util import plaintext_to_html, plaintext_to_latex from epydoc.compat import * import sre_parse, sre_constants +from epydoc.markup.epytext import Element, ParsedEpytextDocstring + def is_re_pattern(pyval): return type(pyval).__name__ == 'SRE_Pattern' @@ -42,19 +49,25 @@ a backup point, and restore back to that backup point. This is used by several colorization methods that first try colorizing their object on a single line (setting linebreakok=False); and - then fall back on a multi-line output if that fails. + then fall back on a multi-line output if that fails. The L{score} + variable is used to keep track of a 'score', reflecting how good + we think this repr is. E.g., unhelpful values like '<Foo instance + at 0x12345>' get low scores. If the score is too low, we'll use + the parse-derived repr instead. """ def __init__(self): self.result = [] self.charpos = 0 self.lineno = 1 self.linebreakok = True + self.score = 0 def mark(self): - return (len(self.result), self.charpos, self.lineno, self.linebreakok) + return (len(self.result), self.charpos, + self.lineno, self.linebreakok, self.score) def restore(self, mark): - n, self.charpos, self.lineno, self.linebreakok = mark + n, self.charpos, self.lineno, self.linebreakok, self.score = mark del self.result[n:] class _Maxlines(Exception): @@ -78,40 +91,6 @@ self.sort = sort #//////////////////////////////////////////////////////////// - # Subclassing Hooks - #//////////////////////////////////////////////////////////// - - PREFIX = None - """A string sequence that should be added to the beginning of all - colorized pyval outputs.""" - - SUFFIX = None - """A string sequence that should be added to the beginning of all - colorized pyval outputs.""" - - NEWLINE = '\n' - """The string sequence that should be generated to encode newlines.""" - - LINEWRAP = None - """The string sequence that should be generated when linewrapping a - string that is too long to fit on a single line. (The - NEWLINE sequence will be added immediately after this sequence)""" - - ELLIPSIS = None - """The string sequence that should be generated when omitting the - rest of the repr because maxlines has been exceeded.""" - - def markup(self, s, tag=None): - """ - Apply syntax highlighting to a single substring from a Python - value representation. C{s} is the substring, and C{tag} is - the tag that should be applied to the substring. C{tag} will - be one of the following strings: - - - (list under construction) - """ - - #//////////////////////////////////////////////////////////// # Colorization Tags #//////////////////////////////////////////////////////////// @@ -128,30 +107,43 @@ RE_REF_TAG = 're-ref' RE_OP_TAG = 're-op' RE_FLAGS_TAG = 're-flags' + + # Should these use symbols instead? + ELLIPSIS = Element('code', '...', style='ellipsis') + LINEWRAP = Element('symbol', 'crarr') #//////////////////////////////////////////////////////////// # Entry Point #//////////////////////////////////////////////////////////// - def colorize(self, pyval): + def colorize(self, pyval, min_score=None): + pds, score = self.colorize_and_score(pyval) + if min_score is None or score >= min_score: + return pds + else: + return None + + def colorize_and_score(self, pyval): + """ + @return: A tuple (parsed_docstring, score). + """ # Create an object to keep track of the colorization. state = _ColorizerState() - # Add the prefix string. - state.result.append(self.PREFIX) # Colorize the value. If we reach maxlines, then add on an # ellipsis marker and call it a day. try: self._colorize(pyval, state) except _Maxlines: state.result.append(self.ELLIPSIS) - # Add on the suffix string. - state.result.append(self.SUFFIX) # Put it all together. - return ''.join(state.result) + tree = Element('epytext', Element('code', style='pyval', + *state.result)) + return ParsedEpytextDocstring(tree), state.score def _colorize(self, pyval, state): pyval_type = type(pyval) - + state.score += 1 + if pyval is None or pyval is True or pyval is False: self._output(str(pyval), self.CONST_TAG, state) elif pyval_type in (int, float, long, types.ComplexType): @@ -179,7 +171,19 @@ elif is_re_pattern(pyval): self._colorize_re(pyval, state) else: - self._output(repr(pyval), None, state) + try: + pyval_repr = repr(pyval) + self._output(pyval_repr, None, state) + if self.GENERIC_OBJECT_RE.match(pyval_repr): + state.score -= 5 + except KeyboardInterrupt: + raise + except: + pyval_repr = '...' + state.score -= 100 + + GENERIC_OBJECT_RE = re.compile(r'^<.* at 0x[0-9a-f]+>$', + re.IGNORECASE) #//////////////////////////////////////////////////////////// # Object Colorization Functions @@ -430,7 +434,7 @@ if i > 0: if not state.linebreakok: raise _Linebreak() - state.result.append(self.NEWLINE) + state.result.append('\n') state.lineno += 1 state.charpos = 0 if state.lineno > self.maxlines: @@ -439,40 +443,21 @@ # If the segment fits on the current line, then just call # markup to tag it, and store the result. if state.charpos + len(segment) <= self.linelen: - state.result.append(self.markup(segment, tag)) state.charpos += len(segment) + if tag: + segment = Element('code', segment, style=tag) + state.result.append(segment) # If the segment doesn't fit on the current line, then # line-wrap it, and insert the remainder of the line into - # the segments list that we're iterating over. + # the segments list that we're iterating over. (We'll go + # the the beginning of the next line at the start of the + # next iteration through the loop.) else: split = self.linelen-state.charpos - state.result += [self.markup(segment[:split], tag), - self.LINEWRAP] segments.insert(i+1, segment[split:]) + segment = segment[:split] + if tag: + segment = Element('code', segment, style=tag) + state.result += [segment, self.LINEWRAP] -class HTMLPyvalColorizer(PyvalColorizer): - NEWLINE = '\n' - PREFIX = SUFFIX = '' - LINEWRAP = (r'<span class="variable-linewrap">' - '<img src="crarr.png" alt="\" /></span>') - ELLIPSIS = r'<span class="variable-ellipsis">...</span>' - def markup(self, s, tag=None): - s = s.replace('&', '&').replace('<', '<').replace('>', '>') - if tag: - return '<span class="variable-%s">%s</span>' % (tag, s) - else: - return s - -class XMLPyvalColorizer(PyvalColorizer): - NEWLINE = '\n' - PREFIX = '<pyval>' - SUFFIX = '</pyval>' - LINEWRAP = '<linewrap />' - ELLIPSIS = '<ellipsis />' - def markup(self, s, tag=None): - s = s.replace('&', '&').replace('<', '<').replace('>', '>') - if tag: - return '<%s>%s</%s>' % (tag, s, tag) - else: - return s Modified: trunk/epydoc/src/epydoc/test/pyval_repr.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/pyval_repr.doctest 2007-02-12 06:54:25 UTC (rev 1465) +++ trunk/epydoc/src/epydoc/test/pyval_repr.doctest 2007-02-13 08:17:33 UTC (rev 1466) @@ -2,32 +2,36 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >>> from epydoc.markup.pyval_repr import * - >>> colorizer = XMLPyvalColorizer(linelen=40) - >>> def color(s): print colorizer.colorize(s) + >>> colorizer = PyvalColorizer(linelen=40) + >>> def color(s): print colorizer.colorize(s).to_html(None).rstrip() - Simple Types ============ Integers, floats, None, and complex numbers get printed using str, with no syntax highlighting: >>> color(10) - <pyval>10</pyval> + <code class="pyval">10</code> >>> color(1./4) - <pyval>0.25</pyval> + <code class="pyval">0.25</code> >>> color(None) - <pyval>None</pyval> + <code class="pyval">None</code> >>> color(100) - <pyval>100</pyval> + <code class="pyval">100</code> Long ints will get wrapped if they're big enough: >>> color(10000000) - <pyval>10000000</pyval> + <code class="pyval">10000000</code> >>> color(10**90) - <pyval>1000000000000000000000000000000000000000<linewrap /> - 0000000000000000000000000000000000000000<linewrap /> - 00000000000</pyval> + <code class="pyval">1000000000000000000000000000000000000000↵ + 0000000000000000000000000000000000000000↵ + 00000000000</code> + >>> print '-'*40+'\n'+colorizer.colorize(10**90).to_plaintext(None) + ---------------------------------------- + 1000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000\ + 00000000000 Strings ======= @@ -35,37 +39,37 @@ escaped using the 'string-escape' encoding. >>> color(''.join(chr(i) for i in range(256))) - <pyval><val-quote>'''</val-quote><val-string>\x00\x01\x02\x03\x04\x05\x06\x07\x08\</val-string><linewrap /> - <val-string>t</val-string> - <val-string>\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x</val-string><linewrap /> - <val-string>15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x</val-string><linewrap /> - <val-string>1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCD</val-string><linewrap /> - <ellipsis /></pyval> + <code class="pyval"><code class="val-quote">'''</code><code class="val-string">\x00\x01\x02\x03\x04\x05\x06\x07\x08\</code>↵ + <code class="val-string">t</code> + <code class="val-string">\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x</code>↵ + <code class="val-string">15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x</code>↵ + <code class="val-string">1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCD</code>↵ + <code class="ellipsis">...</code></code> Currently, the "'" quote is always used, because that's what the 'string-escape' encoding expects. >>> color('Hello') - <pyval><val-quote>'</val-quote><val-string>Hello</val-string><val-quote>'</val-quote></pyval> + <code class="pyval"><code class="val-quote">'</code><code class="val-string">Hello</code><code class="val-quote">'</code></code> >>> color('"Hello"') - <pyval><val-quote>'</val-quote><val-string>"Hello"</val-string><val-quote>'</val-quote></pyval> + <code class="pyval"><code class="val-quote">'</code><code class="val-string">"Hello"</code><code class="val-quote">'</code></code> >>> color("'Hello'") - <pyval><val-quote>'</val-quote><val-string>\'Hello\'</val-string><val-quote>'</val-quote></pyval> + <code class="pyval"><code class="val-quote">'</code><code class="val-string">\'Hello\'</code><code class="val-quote">'</code></code> Strings containing newlines are automatically rendered as multiline strings. >>> color("This\n is a multiline\n string!") - <pyval><val-quote>'''</val-quote><val-string>This</val-string> - <val-string> is a multiline</val-string> - <val-string> string!</val-string><val-quote>'''</val-quote></pyval> + <code class="pyval"><code class="val-quote">'''</code><code class="val-string">This</code> + <code class="val-string"> is a multiline</code> + <code class="val-string"> string!</code><code class="val-quote">'''</code></code> Unicode strings are handled properly. >>> color(u"Hello world") - <pyval><val-quote>u'</val-quote><val-string>Hello world</val-string><val-quote>'</val-quote></pyval> + <code class="pyval"><code class="val-quote">u'</code><code class="val-string">Hello world</code><code class="val-quote">'</code></code> >>> color(u"\uaaaa And \ubbbb") - <pyval><val-quote>u'</val-quote><val-string>\uaaaa And \ubbbb</val-string><val-quote>'</val-quote></pyval> + <code class="pyval"><code class="val-quote">u'</code><code class="val-string">\uaaaa And \ubbbb</code><code class="val-quote">'</code></code> Lists, Tuples, etc. =================== @@ -75,28 +79,28 @@ listed on a separate line, indented by the size of the open-bracket. >>> color(range(10)) - <pyval><val-group>[</val-group>0<val-op>, </val-op>1<val-op>, </val-op>2<val-op>, </val-op>3<val-op>, </val-op>4<val-op>, </val-op>5<val-op>, </val-op>6<val-op>, </val-op>7<val-op>, </val-op>8<val-op>, </val-op>9<val-group>]</val-group></pyval> + <code class="pyval"><code class="val-group">[</code>0<code class="val-op">, </code>1<code class="val-op">, </code>2<code class="val-op">, </code>3<code class="val-op">, </code>4<code class="val-op">, </code>5<code class="val-op">, </code>6<code class="val-op">, </code>7<code class="val-op">, </code>8<code class="val-op">, </code>9<code class="val-group">]</code></code> >>> color(range(100)) - <pyval><val-group>[</val-group>0<val-op>,</val-op> - 1<val-op>,</val-op> - 2<val-op>,</val-op> - 3<val-op>,</val-op> - 4<val-op>,</val-op> - <ellipsis /></pyval> + <code class="pyval"><code class="val-group">[</code>0<code class="val-op">,</code> + 1<code class="val-op">,</code> + 2<code class="val-op">,</code> + 3<code class="val-op">,</code> + 4<code class="val-op">,</code> + <code class="ellipsis">...</code></code> >>> color([1,2,[5,6,[(11,22,33),9],10],11]+[99,98,97,96,95]) - <pyval><val-group>[</val-group>1<val-op>,</val-op> - 2<val-op>,</val-op> - <val-group>[</val-group>5<val-op>, </val-op>6<val-op>, </val-op><val-group>[</val-group><val-group>(</val-group>11<val-op>, </val-op>22<val-op>, </val-op>33<val-group>)</val-group><val-op>, </val-op>9<val-group>]</val-group><val-op>, </val-op>10<val-group>]</val-group><val-op>,</val-op> - 11<val-op>,</val-op> - 99<val-op>,</val-op> - <ellipsis /></pyval> + <code class="pyval"><code class="val-group">[</code>1<code class="val-op">,</code> + 2<code class="val-op">,</code> + <code class="val-group">[</code>5<code class="val-op">, </code>6<code class="val-op">, </code><code class="val-group">[</code><code class="val-group">(</code>11<code class="val-op">, </code>22<code class="val-op">, </code>33<code class="val-group">)</code><code class="val-op">, </code>9<code class="val-group">]</code><code class="val-op">, </code>10<code class="val-group">]</code><code class="val-op">,</code> + 11<code class="val-op">,</code> + 99<code class="val-op">,</code> + <code class="ellipsis">...</code></code> >>> color(set(range(20))) - <pyval><val-group>set([</val-group>0<val-op>,</val-op> - 1<val-op>,</val-op> - 2<val-op>,</val-op> - 3<val-op>,</val-op> - 4<val-op>,</val-op> - <ellipsis /></pyval> + <code class="pyval"><code class="val-group">set([</code>0<code class="val-op">,</code> + 1<code class="val-op">,</code> + 2<code class="val-op">,</code> + 3<code class="val-op">,</code> + 4<code class="val-op">,</code> + <code class="ellipsis">...</code></code> Dictionaries ============ @@ -104,91 +108,137 @@ "op". >>> color({1:33, 2:[1,2,3,{7:'oo'*20}]}) - <pyval><val-group>{</val-group>1<val-op>: </val-op>33<val-op>,</val-op> - 2<val-op>: </val-op><val-group>[</val-group>1<val-op>,</val-op> - 2<val-op>,</val-op> - 3<val-op>,</val-op> - <val-group>{</val-group>7<val-op>: </val-op><val-quote>'</val-quote><val-string>oooooooooooooooooooooooooooooo</val-string><linewrap /> - <ellipsis /></pyval> + <code class="pyval"><code class="val-group">{</code>1<code class="val-op">: </code>33<code class="val-op">,</code> + 2<code class="val-op">: </code><code class="val-group">[</code>1<code class="val-op">,</code> + 2<code class="val-op">,</code> + 3<code class="val-op">,</code> + <code class="val-group">{</code>7<code class="val-op">: </code><code class="val-quote">'</code><code class="val-string">oooooooooooooooooooooooooooooo</code>↵ + <code class="ellipsis">...</code></code> Regular Expressions =================== + >>> def textcontent(elt): + ... if isinstance(elt, basestring): return elt + ... else: return ''.join(textcontent(c) for c in elt.children) + >>> import re >>> def color_re(s, check_roundtrip=True): ... val = colorizer.colorize(re.compile(s)) ... if check_roundtrip: - ... roundtrip_val = re.sub('</?[\w-]+>', '', val) - ... roundtrip_val = roundtrip_val.replace('>', '>') - ... roundtrip_val = roundtrip_val.replace('<', '<') - ... roundtrip_val = roundtrip_val.replace('&', '&') - ... assert roundtrip_val == s, roundtrip_val - ... print val + ... assert textcontent(val._tree) == s, val._tree + ... print val.to_html(None).rstrip() >>> # Literal characters >>> color_re(u'abc \t\r\n\f\v \xff \uffff \U000fffff', False) - <pyval>abc \t\r\n\f\v \xff \uffff \U000fffff</pyval> + <code class="pyval">abc \t\r\n\f\v \xff \uffff \U000fffff</code> >>> color_re(r'\.\^\$\\\*\+\?\{\}\[\]\|\(\)') - <pyval>\.\^\$\\\*\+\?\{\}\[\]\|\(\)</pyval> + <code class="pyval">\.\^\$\\\*\+\?\{\}\[\]\|\(\)</code> >>> # Any character & character classes >>> color_re(r".\d\D\s\S\w\W\A^$\b\B\Z") - <pyval>.\d\D\s\S\w\W\A^$\b\B\Z</pyval> + <code class="pyval">.\d\D\s\S\w\W\A^$\b\B\Z</code> >>> # Branching >>> color_re(r"foo|bar") - <pyval>foo<re-op>|</re-op>bar</pyval> + <code class="pyval">foo<code class="re-op">|</code>bar</code> >>> # Character classes >>> color_re(r"[abcd]") - <pyval><re-group>[</re-group>abcd<re-group>]</re-group></pyval> + <code class="pyval"><code class="re-group">[</code>abcd<code class="re-group">]</code></code> >>> # Repeats >>> color_re(r"a*b+c{4,}d{,5}e{3,9}f?") - <pyval>a<re-op>*</re-op>b<re-op>+</re-op>c<re-op>{4,}</re-op>d<re-op>{,5}</re-op>e<re-op>{3,9}</re-op>f<re-op>?</re-op></pyval> + <code class="pyval">a<code class="re-op">*</code>b<code class="re-op">+</code>c<code class="re-op">{4,}</code>d<code class="re-op">{,5}</code>e<code class="re-op">{3,9}</code>f<code class="re-op">?</code></code> >>> color_re(r"a*?b+?c{4,}?d{,5}?e{3,9}?f??") - <pyval>a<re-op>*?</re-op>b<re-op>+?</re-op>c<re-op>{4,}?</re-op>d<re-op>{,5}?</re-op>e<re-op>{3,9}?</re-op>f<re-op>??</re-op></pyval> + <code class="pyval">a<code class="re-op">*?</code>b<code class="re-op">+?</code>c<code class="re-op">{4,}?</code>d<code class="re-op">{,5}?</code>e<code class="re-op">{3,9}?</code>f<code class="re-op">??</code></code> >>> # Subpatterns >>> color_re(r"(foo (bar) | (baz))") - <pyval><re-group>(</re-group>foo <re-group>(</re-group>bar<re-group>)</re-group> <re-op>|</re-op> <re-group>(</re-group>baz<re-group>)</re-group><re-group>)</re-group></pyval> + <code class="pyval"><code class="re-group">(</code>foo <code class="re-group">(</code>bar<code class="re-group">)</code> <code class="re-op">|</code> <code class="re-group">(</code>baz<code class="re-group">)</code><code class="re-group">)</code></code> >>> color_re(r"(?:foo (?:bar) | (?:baz))") - <pyval><re-group>(?:</re-group>foo <re-group>(?:</re-group>bar<re-group>)</re-group> <re-op>|</re-op> <re-group>(?:</re-group>baz<re-group>)</re-group><re-group>)</re-group></pyval> + <code class="pyval"><code class="re-group">(?:</code>foo <code class="re-group">(?:</code>bar<code class="re-group">)</code> <code class="re-op">|</code> <code class="re-group">(?:</code>baz<code class="re-group">)</code><code class="re-group">)</code></code> >>> color_re("(foo (?P<a>bar) | (?P<boop>baz))") - <pyval><re-group>(</re-group>foo <re-group>(?P<</re-group><re-ref>a</re-ref><re-group>></re-group>bar<re-group>)</re-group> <re-op>|</re-op> <re-group>(?P<</re-group><re-ref>boop</re-ref><re-group>></re-group>baz<re-group>)</re-group><re-group>)</re-group></pyval> + <code class="pyval"><code class="re-group">(</code>foo <code class="re-group">(?P<</code><code class="re-ref">a</code><code class="re-group">></code>bar<code class="re-group">)</code> <code class="re-op">|</code> <code class="re-group">(?P<</code><code class="re-ref">boop</code><code class="re-group">></code>baz<code class="re-group">)</code><code class="re-group">)</code></code> >>> # Group References >>> color_re(r"(...) and (\1)") - <pyval><re-group>(</re-group>...<re-group>)</re-group> and <re-group>(</re-group><re-ref>\1</re-ref><re-group>)</re-group></pyval> + <code class="pyval"><code class="re-group">(</code>...<code class="re-group">)</code> and <code class="re-group">(</code><code class="re-ref">\1</code><code class="re-group">)</code></code> >>> # Ranges >>> color_re(r"[a-bp-z]") - <pyval><re-group>[</re-group>a<re-op>-</re-op>bp<re-op>-</re-op>z<re-group>]</re-group></pyval> + <code class="pyval"><code class="re-group">[</code>a<code class="re-op">-</code>bp<code class="re-op">-</code>z<code class="re-group">]</code></code> >>> color_re(r"[^a-bp-z]") - <pyval><re-group>[</re-group><re-op>^</re-op>a<re-op>-</re-op>bp<re-op>-</re-op>z<re-group>]</re-group></pyval> + <code class="pyval"><code class="re-group">[</code><code class="re-op">^</code>a<code class="re-op">-</code>bp<code class="re-op">-</code>z<code class="re-group">]</code></code> >>> color_re(r"[^abc]") - <pyval><re-group>[</re-group><re-op>^</re-op>abc<re-group>]</re-group></pyval> + <code class="pyval"><code class="re-group">[</code><code class="re-op">^</code>abc<code class="re-group">]</code></code> >>> # Lookahead/behinds >>> color_re(r"foo(?=bar)") - <pyval>foo<re-group>(?=</re-group>bar<re-group>)</re-group></pyval> + <code class="pyval">foo<code class="re-group">(?=</code>bar<code class="re-group">)</code></code> >>> color_re(r"foo(?!bar)") - <pyval>foo<re-group>(?!</re-group>bar<re-group>)</re-group></pyval> + <code class="pyval">foo<code class="re-group">(?!</code>bar<code class="re-group">)</code></code> >>> color_re(r"(?<=bar)foo") - <pyval><re-group>(?<=</re-group>bar<re-group>)</re-group>foo</pyval> + <code class="pyval"><code class="re-group">(?<=</code>bar<code class="re-group">)</code>foo</code> >>> color_re(r"(?<!bar)foo") - <pyval><re-group>(?<!</re-group>bar<re-group>)</re-group>foo</pyval> + <code class="pyval"><code class="re-group">(?<!</code>bar<code class="re-group">)</code>foo</code> >>> # Flags >>> color_re(r"(?im)^Food") - <pyval><re-flags>(?im)</re-flags>^Food</pyval> + <code class="pyval"><code class="re-flags">(?im)</code>^Food</code> >>> color_re(r"(?Limsx)^Food") - <pyval><re-flags>(?Limsx)</re-flags>^Food</pyval> + <code class="pyval"><code class="re-flags">(?Limsx)</code>^Food</code> >>> color_re(r"(?Limstux)^Food") - <pyval><re-flags>(?Limstux)</re-flags>^Food</pyval> + <code class="pyval"><code class="re-flags">(?Limstux)</code>^Food</code> >>> color_re(r"(?x)This is verbose", False) - <pyval><re-flags>(?x)</re-flags>Thisisverbose</pyval> + <code class="pyval"><code class="re-flags">(?x)</code>Thisisverbose</code> +Representation Scores +===================== +When colorized representations are built, a score is computed +evaluating how helpful the repr is. E.g., unhelpful values like `<Foo +instance at 0x12345>` get low scores. Currently, the scoring +algorithm is: +- [+1] for each object colorized. When the colorizer recurses into + a structure, this will add one for each element contained. +- [-5] when repr(obj) looks like <xyz instance at ...>, for any + colorized object (including objects in structures). +- [-100] if repr(obj) raises an exception, for any colorized object + (including objects in structures). +The `min_score` arg to colorize can be used to set a cutoff-point for +scores; if the score is too low, then `colorize` will return `None`. + >>> def color2(v): + ... pds, score = colorizer.colorize_and_score(v) + ... print 'repr: %s' % pds.to_plaintext(None) + ... print 'score: %s (%s)' % (score, score>0 and 'ok' or 'bad') + + >>> class A: pass + + >>> color2('hello') + repr: 'hello' + score: 1 (ok) + + >>> color2(["hello", 123]) + repr: ['hello', 123] + score: 3 (ok) + + >>> color2(A()) + repr: <__builtin__.A instance at ...> + score: -4 (bad) + + >>> color2([A()]) + repr: [<__builtin__.A instance at ...>] + score: -3 (bad) + + >>> color2([A(),1,2,3,4,5,6]) + repr: [<__builtin__.A instance at ...>, + 1, + 2, + 3, + 4, + ... + score: 1 (ok) + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-12 06:54:26
|
Revision: 1465 http://svn.sourceforge.net/epydoc/?rev=1465&view=rev Author: edloper Date: 2007-02-11 22:54:25 -0800 (Sun, 11 Feb 2007) Log Message: ----------- - Added preliminary repr tests Modified Paths: -------------- trunk/epydoc/src/epydoc/test/docbuilder.doctest Modified: trunk/epydoc/src/epydoc/test/docbuilder.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/docbuilder.doctest 2007-02-12 06:53:50 UTC (rev 1464) +++ trunk/epydoc/src/epydoc/test/docbuilder.doctest 2007-02-12 06:54:25 UTC (rev 1465) @@ -290,3 +290,27 @@ +- type_descr = u'date\n\n' +- value = <UNKNOWN> +Value Representation +==================== +Currently, many variable reprs use the introspected form where it +would really be better to use the parsed version. See SF bug +#1653577. We intend to improve on this. This test documents the +current behavior; but should be replaced when we change the behavior. + + >>> from epydoc.test.util import buildvaluedoc + >>> def print_py_reprs(s): + ... value_doc = buildvaluedoc(s) + ... for (name, var_doc) in sorted(value_doc.variables.items()): + ... print "%-5s %r" % (name, var_doc.value.pyval_repr()) + + >>> print_py_reprs(''' + ... class Foo: pass + ... a = Foo() + ... b = [1, 2, 3] + ... c = 3+5 + ... b.append(99) + ... ''') + Foo u'<class epydoc_test.Foo at 0x40484bfc>' + a u'<epydoc_test.Foo instance at 0x4069ca4c>' + b u'[1, 2, 3, 99]' + c u'8' This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-12 06:53:52
|
Revision: 1464 http://svn.sourceforge.net/epydoc/?rev=1464&view=rev Author: edloper Date: 2007-02-11 22:53:50 -0800 (Sun, 11 Feb 2007) Log Message: ----------- - Refactored some test functions Modified Paths: -------------- trunk/epydoc/src/epydoc/test/util.py Modified: trunk/epydoc/src/epydoc/test/util.py =================================================================== --- trunk/epydoc/src/epydoc/test/util.py 2007-02-12 05:26:28 UTC (rev 1463) +++ trunk/epydoc/src/epydoc/test/util.py 2007-02-12 06:53:50 UTC (rev 1464) @@ -23,6 +23,18 @@ #{ Test Functions ###################################################################### +def buildvaluedoc(s): + """ + This test function takes a string containing the contents of a + module. It writes the string contents to a file, imports the file + as a module, and uses build_doc to build documentation, and + returns it as a C{ValueDoc} object. + """ + tmp_dir = write_pystring_to_tmp_dir(s) + val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py')) + cleanup_tmp_dir(tmp_dir) + return val_doc + def runbuilder(s, attribs='', build=None, exclude=''): """ This test function takes a string containing the contents of a @@ -35,10 +47,7 @@ the whole module. """ # Write it to a temp file. - tmp_dir = tempfile.mkdtemp() - out = open(os.path.join(tmp_dir, 'epydoc_test.py'), 'w') - out.write(textwrap.dedent(s)) - out.close() + tmp_dir = write_pystring_to_tmp_dir(s) # Build it. val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py')) if build: val_doc = val_doc.variables[build].value @@ -54,11 +63,7 @@ s = re.sub(r"(<\w+ object at )0x\w+>", r"\1...>", s) print s # Clean up. - os.unlink(os.path.join(tmp_dir, 'epydoc_test.py')) - try: os.unlink(os.path.join(tmp_dir, 'epydoc_test.pyc')) - except OSError: pass - os.rmdir(tmp_dir) - del sys.modules['epydoc_test'] + cleanup_tmp_dir(tmp_dir) def runparser(s, attribs='', show=None, exclude=''): """ @@ -72,10 +77,7 @@ display). """ # Write it to a temp file. - tmp_dir = tempfile.mkdtemp() - out = open(os.path.join(tmp_dir, 'test.py'), 'w') - out.write(textwrap.dedent(s)) - out.close() + tmp_dir = write_pystring_to_tmp_dir(s) # Parse it. val_doc = parse_docs(out.name) if show is not None: @@ -89,8 +91,7 @@ s = re.sub(r"filename = .*", "filename = ...", s) print s # Clean up. - os.unlink(os.path.join(tmp_dir, 'test.py')) - os.rmdir(tmp_dir) + cleanup_tmp_dir(tmp_dir) def runintrospecter(s, attribs='', introspect=None, exclude=''): """ @@ -104,10 +105,7 @@ introspecting the whole module. """ # Write it to a temp file. - tmp_dir = tempfile.mkdtemp() - out = open(os.path.join(tmp_dir, 'epydoc_test.py'), 'w') - out.write(textwrap.dedent(s)) - out.close() + tmp_dir = write_pystring_to_tmp_dir(s) # Import it. sys.path.insert(0, tmp_dir) if introspect is None: @@ -125,11 +123,7 @@ s = re.sub(r"(<\w+ object at )0x\w+>", r"\1...>", s) print s # Clean up. - os.unlink(os.path.join(tmp_dir, 'epydoc_test.py')) - try: os.unlink(os.path.join(tmp_dir, 'epydoc_test.pyc')) - except OSError: pass - os.rmdir(tmp_dir) - del sys.modules['epydoc_test'] + cleanup_tmp_dir(tmp_dir) def print_warnings(): """ @@ -176,6 +170,20 @@ #{ Helper Functions ###################################################################### +def write_pystring_to_tmp_dir(s): + tmp_dir = tempfile.mkdtemp() + out = open(os.path.join(tmp_dir, 'epydoc_test.py'), 'w') + out.write(textwrap.dedent(s)) + out.close() + return tmp_dir + +def cleanup_tmp_dir(tmp_dir): + os.unlink(os.path.join(tmp_dir, 'epydoc_test.py')) + try: os.unlink(os.path.join(tmp_dir, 'epydoc_test.pyc')) + except OSError: pass + os.rmdir(tmp_dir) + del sys.modules['epydoc_test'] + def to_plain(docstring): """Conver a parsed docstring into plain text""" if isinstance(docstring, ParsedDocstring): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ed...@us...> - 2007-02-12 05:26:30
|
Revision: 1463 http://svn.sourceforge.net/epydoc/?rev=1463&view=rev Author: edloper Date: 2007-02-11 21:26:28 -0800 (Sun, 11 Feb 2007) Log Message: ----------- - Added a new module for colorizing python values. This abstracts away from the code that's currently in the html writer, and should make it easier to use the same colorization code for other docwriters. The new code should do a better job of pretty-printing values than the current html writer code. I also fixed a couple minor bugs in the regexp colorizer along the way. Note, though, that this code hasn't been plugged into epydoc in any way yet. I.e., docwriter/html.py still needs to be modified to actually *use* this new code. Added Paths: ----------- trunk/epydoc/src/epydoc/markup/pyval_repr.py trunk/epydoc/src/epydoc/test/pyval_repr.doctest Added: trunk/epydoc/src/epydoc/markup/pyval_repr.py =================================================================== --- trunk/epydoc/src/epydoc/markup/pyval_repr.py (rev 0) +++ trunk/epydoc/src/epydoc/markup/pyval_repr.py 2007-02-12 05:26:28 UTC (rev 1463) @@ -0,0 +1,478 @@ +# epydoc -- Marked-up Representations for Python Values +# +# Copyright (C) 2005 Edward Loper +# Author: Edward Loper <ed...@lo...> +# URL: <http://epydoc.sf.net> +# +# $Id: apidoc.py 1448 2007-02-11 00:05:34Z dvarrazzo $ + +""" +Syntax highlighter for Python values. Currently provides special +colorization support for: + + - lists, tuples, sets, frozensets, dicts + - numbers + - strings + - compiled regexps + +The highlighter also takes care of line-wrapping, and automatically +stops generating repr output as soon as it has exceeded the specified +number of lines (which should make it faster than pprint for large +values). It does I{not} bother to do automatic cycle detection, +because maxlines is typically around 5, so it's really not worth it. +""" + +# Implementation note: we use exact tests for classes (list, etc) +# rather than using isinstance, because subclasses might override +# __repr__. + +import types, re +import epydoc.apidoc +from epydoc.util import decode_with_backslashreplace +from epydoc.compat import * +import sre_parse, sre_constants + +def is_re_pattern(pyval): + return type(pyval).__name__ == 'SRE_Pattern' + +class _ColorizerState: + """ + An object uesd to keep track of the current state of the pyval + colorizer. The L{mark()}/L{restore()} methods can be used to set + a backup point, and restore back to that backup point. This is + used by several colorization methods that first try colorizing + their object on a single line (setting linebreakok=False); and + then fall back on a multi-line output if that fails. + """ + def __init__(self): + self.result = [] + self.charpos = 0 + self.lineno = 1 + self.linebreakok = True + + def mark(self): + return (len(self.result), self.charpos, self.lineno, self.linebreakok) + + def restore(self, mark): + n, self.charpos, self.lineno, self.linebreakok = mark + del self.result[n:] + +class _Maxlines(Exception): + """A control-flow exception that is raised when PyvalColorizer + exeeds the maximum number of allowed lines.""" + +class _Linebreak(Exception): + """A control-flow exception that is raised when PyvalColorizer + generates a string containing a newline, but the state object's + linebreakok variable is False.""" + + +class PyvalColorizer: + """ + Syntax highlighter for Python values. + """ + + def __init__(self, linelen=75, maxlines=5, sort=True): + self.linelen = linelen + self.maxlines = maxlines + self.sort = sort + + #//////////////////////////////////////////////////////////// + # Subclassing Hooks + #//////////////////////////////////////////////////////////// + + PREFIX = None + """A string sequence that should be added to the beginning of all + colorized pyval outputs.""" + + SUFFIX = None + """A string sequence that should be added to the beginning of all + colorized pyval outputs.""" + + NEWLINE = '\n' + """The string sequence that should be generated to encode newlines.""" + + LINEWRAP = None + """The string sequence that should be generated when linewrapping a + string that is too long to fit on a single line. (The + NEWLINE sequence will be added immediately after this sequence)""" + + ELLIPSIS = None + """The string sequence that should be generated when omitting the + rest of the repr because maxlines has been exceeded.""" + + def markup(self, s, tag=None): + """ + Apply syntax highlighting to a single substring from a Python + value representation. C{s} is the substring, and C{tag} is + the tag that should be applied to the substring. C{tag} will + be one of the following strings: + + - (list under construction) + """ + + #//////////////////////////////////////////////////////////// + # Colorization Tags + #//////////////////////////////////////////////////////////// + + GROUP_TAG = 'val-group' # e.g., "[" and "]" + COMMA_TAG = 'val-op' # The "," that separates elements + COLON_TAG = 'val-op' # The ":" in dictionaries + CONST_TAG = None # None, True, False + NUMBER_TAG = None # ints, floats, etc + QUOTE_TAG = 'val-quote' # Quotes around strings. + STRING_TAG = 'val-string' # Body of string literals + + RE_CHAR_TAG = None + RE_GROUP_TAG = 're-group' + RE_REF_TAG = 're-ref' + RE_OP_TAG = 're-op' + RE_FLAGS_TAG = 're-flags' + + #//////////////////////////////////////////////////////////// + # Entry Point + #//////////////////////////////////////////////////////////// + + def colorize(self, pyval): + # Create an object to keep track of the colorization. + state = _ColorizerState() + # Add the prefix string. + state.result.append(self.PREFIX) + # Colorize the value. If we reach maxlines, then add on an + # ellipsis marker and call it a day. + try: + self._colorize(pyval, state) + except _Maxlines: + state.result.append(self.ELLIPSIS) + # Add on the suffix string. + state.result.append(self.SUFFIX) + # Put it all together. + return ''.join(state.result) + + def _colorize(self, pyval, state): + pyval_type = type(pyval) + + if pyval is None or pyval is True or pyval is False: + self._output(str(pyval), self.CONST_TAG, state) + elif pyval_type in (int, float, long, types.ComplexType): + self._output(str(pyval), self.NUMBER_TAG, state) + elif pyval_type is str: + self._colorize_str(pyval, state, '', 'string-escape') + elif pyval_type is unicode: + self._colorize_str(pyval, state, 'u', 'unicode-escape') + elif pyval_type is list: + self._multiline(self._colorize_iter, pyval, state, '[', ']') + elif pyval_type is tuple: + self._multiline(self._colorize_iter, pyval, state, '(', ')') + elif pyval_type is set: + if self.sort: pyval = sorted(pyval) + self._multiline(self._colorize_iter, pyval, state, + 'set([', '])') + elif pyval_type is frozenset: + if self.sort: pyval = sorted(pyval) + self._multiline(self._colorize_iter, pyval, state, + 'frozenset([', '])') + elif pyval_type is dict: + items = pyval.items() + if self.sort: items = sorted(items) + self._multiline(self._colorize_dict, items, state, '{', '}') + elif is_re_pattern(pyval): + self._colorize_re(pyval, state) + else: + self._output(repr(pyval), None, state) + + #//////////////////////////////////////////////////////////// + # Object Colorization Functions + #//////////////////////////////////////////////////////////// + + def _multiline(self, func, pyval, state, *args): + """ + Helper for container-type colorizers. First, try calling + C{func(pyval, state, *args)} with linebreakok set to false; + and if that fails, then try again with it set to true. + """ + linebreakok = state.linebreakok + mark = state.mark() + + try: + state.linebreakok = False + func(pyval, state, *args) + state.linebreakok = linebreakok + + except _Linebreak: + if not linebreakok: + raise + state.restore(mark) + func(pyval, state, *args) + + def _colorize_iter(self, pyval, state, prefix, suffix): + self._output(prefix, self.GROUP_TAG, state) + indent = state.charpos + for i, elt in enumerate(pyval): + if i>=1: + if state.linebreakok: + self._output(',', self.COMMA_TAG, state) + self._output('\n'+' '*indent, None, state) + else: + self._output(', ', self.COMMA_TAG, state) + self._colorize(elt, state) + self._output(suffix, self.GROUP_TAG, state) + + def _colorize_dict(self, items, state, prefix, suffix): + self._output(prefix, self.GROUP_TAG, state) + indent = state.charpos + for i, (key, val) in enumerate(items): + if i>=1: + if state.linebreakok: + self._output(',', self.COMMA_TAG, state) + self._output('\n'+' '*indent, None, state) + else: + self._output(', ', self.COMMA_TAG, state) + self._colorize(key, state) + self._output(': ', self.COLON_TAG, state) + self._colorize(val, state) + self._output(suffix, self.GROUP_TAG, state) + + def _colorize_str(self, pyval, state, prefix, encoding): + # Decide which quote to use. + if '\n' in pyval: quote = "'''" + else: quote = "'" + # Open quote. + self._output(prefix+quote, self.QUOTE_TAG, state) + # Body + for i, line in enumerate(pyval.split('\n')): + if i>0: self._output('\n', None, state) + self._output(line.encode(encoding), self.STRING_TAG, state) + # Close quote. + self._output(quote, self.QUOTE_TAG, state) + + def _colorize_re(self, pyval, state): + # Extract the flag & pattern from the regexp. + pat, flags = pyval.pattern, pyval.flags + # If the pattern is a string, decode it to unicode. + if isinstance(pat, str): + pat = decode_with_backslashreplace(pat) + # Parse the regexp pattern. + tree = sre_parse.parse(pat, flags) + groups = dict([(num,name) for (name,num) in + tree.pattern.groupdict.items()]) + # Colorize it! + self._colorize_re_flags(tree.pattern.flags, state) + self._colorize_re_tree(tree, state, True, groups) + + def _colorize_re_flags(self, flags, state): + if flags: + flags = [c for (c,n) in sorted(sre_parse.FLAGS.items()) + if (n&flags)] + flags = '(?%s)' % ''.join(flags) + self._output(flags, self.RE_FLAGS_TAG, state) + + def _colorize_re_tree(self, tree, state, noparen, groups): + assert noparen in (True, False) + if len(tree) > 1 and not noparen: + self._output('(', self.RE_GROUP_TAG, state) + for elt in tree: + op = elt[0] + args = elt[1] + + if op == sre_constants.LITERAL: + c = unichr(args) + # Add any appropriate escaping. + if c in '.^$\\*+?{}[]|()': c = '\\'+c + elif c == '\t': c = '\\t' + elif c == '\r': c = '\\r' + elif c == '\n': c = '\\n' + elif c == '\f': c = '\\f' + elif c == '\v': c = '\\v' + elif ord(c) > 0xffff: c = r'\U%08x' % ord(c) + elif ord(c) > 0xff: c = r'\u%04x' % ord(c) + elif ord(c)<32 or ord(c)>=127: c = r'\x%02x' % ord(c) + self._output(c, self.RE_CHAR_TAG, state) + + elif op == sre_constants.ANY: + self._output('.', self.RE_CHAR_TAG, state) + + elif op == sre_constants.BRANCH: + if args[0] is not None: + raise ValueError('Branch expected None arg but got %s' + % args[0]) + for i, item in enumerate(args[1]): + if i > 0: + self._output('|', self.RE_OP_TAG, state) + self._colorize_re_tree(item, state, True, groups) + + elif op == sre_constants.IN: + if (len(args) == 1 and args[0][0] == sre_constants.CATEGORY): + self._colorize_re_tree(args, state, False, groups) + else: + self._output('[', self.RE_GROUP_TAG, state) + self._colorize_re_tree(args, state, True, groups) + self._output(']', self.RE_GROUP_TAG, state) + + elif op == sre_constants.CATEGORY: + if args == sre_constants.CATEGORY_DIGIT: val = r'\d' + elif args == sre_constants.CATEGORY_NOT_DIGIT: val = r'\D' + elif args == sre_constants.CATEGORY_SPACE: val = r'\s' + elif args == sre_constants.CATEGORY_NOT_SPACE: val = r'\S' + elif args == sre_constants.CATEGORY_WORD: val = r'\w' + elif args == sre_constants.CATEGORY_NOT_WORD: val = r'\W' + else: raise ValueError('Unknown category %s' % args) + self._output(val, self.RE_CHAR_TAG, state) + + elif op == sre_constants.AT: + if args == sre_constants.AT_BEGINNING_STRING: val = r'\A' + elif args == sre_constants.AT_BEGINNING: val = r'^' + elif args == sre_constants.AT_END: val = r'$' + elif args == sre_constants.AT_BOUNDARY: val = r'\b' + elif args == sre_constants.AT_NON_BOUNDARY: val = r'\B' + elif args == sre_constants.AT_END_STRING: val = r'\Z' + else: raise ValueError('Unknown position %s' % args) + self._output(val, self.RE_CHAR_TAG, state) + + elif op in (sre_constants.MAX_REPEAT, sre_constants.MIN_REPEAT): + minrpt = args[0] + maxrpt = args[1] + if maxrpt == sre_constants.MAXREPEAT: + if minrpt == 0: val = '*' + elif minrpt == 1: val = '+' + else: val = '{%d,}' % (minrpt) + elif minrpt == 0: + if maxrpt == 1: val = '?' + else: val = '{,%d}' % (maxrpt) + elif minrpt == maxrpt: + val = '{%d}' % (maxrpt) + else: + val = '{%d,%d}' % (minrpt, maxrpt) + if op == sre_constants.MIN_REPEAT: + val += '?' + + self._colorize_re_tree(args[2], state, False, groups) + self._output(val, self.RE_OP_TAG, state) + + elif op == sre_constants.SUBPATTERN: + if args[0] is None: + self._output('(?:', self.RE_GROUP_TAG, state) + elif args[0] in groups: + self._output('(?P<', self.RE_GROUP_TAG, state) + self._output(groups[args[0]], self.RE_REF_TAG, state) + self._output('>', self.RE_GROUP_TAG, state) + elif isinstance(args[0], (int, long)): + # This is cheating: + self._output('(', self.RE_GROUP_TAG, state) + else: + self._output('(?P<', self.RE_GROUP_TAG, state) + self._output(args[0], self.RE_REF_TAG, state) + self._output('>', self.RE_GROUP_TAG, state) + self._colorize_re_tree(args[1], state, True, groups) + self._output(')', self.RE_GROUP_TAG, state) + + elif op == sre_constants.GROUPREF: + self._output('\\%d' % args, self.RE_REF_TAG, state) + + elif op == sre_constants.RANGE: + self._colorize_re_tree( ((sre_constants.LITERAL, args[0]),), + state, False, groups ) + self._output('-', self.RE_OP_TAG, state) + self._colorize_re_tree( ((sre_constants.LITERAL, args[1]),), + state, False, groups ) + + elif op == sre_constants.NEGATE: + self._output('^', self.RE_OP_TAG, state) + + elif op == sre_constants.ASSERT: + if args[0] > 0: + self._output('(?=', self.RE_GROUP_TAG, state) + else: + self._output('(?<=', self.RE_GROUP_TAG, state) + self._colorize_re_tree(args[1], state, True, groups) + self._output(')', self.RE_GROUP_TAG, state) + + elif op == sre_constants.ASSERT_NOT: + if args[0] > 0: + self._output('(?!', self.RE_GROUP_TAG, state) + else: + self._output('(?<!', self.RE_GROUP_TAG, state) + self._colorize_re_tree(args[1], state, True, groups) + self._output(')', self.RE_GROUP_TAG, state) + + elif op == sre_constants.NOT_LITERAL: + self._output('[^', self.RE_GROUP_TAG, state) + self._colorize_re_tree( ((sre_constants.LITERAL, args),), + state, False, groups ) + self._output(']', self.RE_GROUP_TAG, state) + else: + log.error("Error colorizing regexp: unknown elt %r" % elt) + if len(tree) > 1 and not noparen: + self._output(')', self.RE_GROUP_TAG, state) + + #//////////////////////////////////////////////////////////// + # Output function + #//////////////////////////////////////////////////////////// + + def _output(self, s, tag, state): + """ + Add the string `s` to the result list, tagging its contents + with tag `tag`. Any lines that go beyond `self.linelen` will + be line-wrapped. If the total number of lines exceeds + `self.maxlines`, then raise a `_Maxlines` exception. + """ + if '\n' in s and not state.linebreakok: + raise _Linebreak() + + # Split the string into segments. The first segment is the + # content to add to the current line, and the remaining + # segments are new lines. + segments = s.split('\n') + + for i, segment in enumerate(segments): + # If this isn't the first segment, then add a newline to + # split it from the previous segment. + if i > 0: + if not state.linebreakok: + raise _Linebreak() + state.result.append(self.NEWLINE) + state.lineno += 1 + state.charpos = 0 + if state.lineno > self.maxlines: + raise _Maxlines() + + # If the segment fits on the current line, then just call + # markup to tag it, and store the result. + if state.charpos + len(segment) <= self.linelen: + state.result.append(self.markup(segment, tag)) + state.charpos += len(segment) + + # If the segment doesn't fit on the current line, then + # line-wrap it, and insert the remainder of the line into + # the segments list that we're iterating over. + else: + split = self.linelen-state.charpos + state.result += [self.markup(segment[:split], tag), + self.LINEWRAP] + segments.insert(i+1, segment[split:]) + +class HTMLPyvalColorizer(PyvalColorizer): + NEWLINE = '\n' + PREFIX = SUFFIX = '' + LINEWRAP = (r'<span class="variable-linewrap">' + '<img src="crarr.png" alt="\" /></span>') + ELLIPSIS = r'<span class="variable-ellipsis">...</span>' + def markup(self, s, tag=None): + s = s.replace('&', '&').replace('<', '<').replace('>', '>') + if tag: + return '<span class="variable-%s">%s</span>' % (tag, s) + else: + return s + +class XMLPyvalColorizer(PyvalColorizer): + NEWLINE = '\n' + PREFIX = '<pyval>' + SUFFIX = '</pyval>' + LINEWRAP = '<linewrap />' + ELLIPSIS = '<ellipsis />' + def markup(self, s, tag=None): + s = s.replace('&', '&').replace('<', '<').replace('>', '>') + if tag: + return '<%s>%s</%s>' % (tag, s, tag) + else: + return s Added: trunk/epydoc/src/epydoc/test/pyval_repr.doctest =================================================================== --- trunk/epydoc/src/epydoc/test/pyval_repr.doctest (rev 0) +++ trunk/epydoc/src/epydoc/test/pyval_repr.doctest 2007-02-12 05:26:28 UTC (rev 1463) @@ -0,0 +1,194 @@ +Regression Testing for epydoc.markup.pyval_repr +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + >>> from epydoc.markup.pyval_repr import * + >>> colorizer = XMLPyvalColorizer(linelen=40) + >>> def color(s): print colorizer.colorize(s) + + +Simple Types +============ +Integers, floats, None, and complex numbers get printed using str, +with no syntax highlighting: + + >>> color(10) + <pyval>10</pyval> + >>> color(1./4) + <pyval>0.25</pyval> + >>> color(None) + <pyval>None</pyval> + >>> color(100) + <pyval>100</pyval> + +Long ints will get wrapped if they're big enough: + + >>> color(10000000) + <pyval>10000000</pyval> + >>> color(10**90) + <pyval>1000000000000000000000000000000000000000<linewrap /> + 0000000000000000000000000000000000000000<linewrap /> + 00000000000</pyval> + +Strings +======= +Strings have their quotation marks tagged as 'quote'. Characters are +escaped using the 'string-escape' encoding. + + >>> color(''.join(chr(i) for i in range(256))) + <pyval><val-quote>'''</val-quote><val-string>\x00\x01\x02\x03\x04\x05\x06\x07\x08\</val-string><linewrap /> + <val-string>t</val-string> + <val-string>\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x</val-string><linewrap /> + <val-string>15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x</val-string><linewrap /> + <val-string>1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCD</val-string><linewrap /> + <ellipsis /></pyval> + +Currently, the "'" quote is always used, because that's what the +'string-escape' encoding expects. + + >>> color('Hello') + <pyval><val-quote>'</val-quote><val-string>Hello</val-string><val-quote>'</val-quote></pyval> + >>> color('"Hello"') + <pyval><val-quote>'</val-quote><val-string>"Hello"</val-string><val-quote>'</val-quote></pyval> + >>> color("'Hello'") + <pyval><val-quote>'</val-quote><val-string>\'Hello\'</val-string><val-quote>'</val-quote></pyval> + +Strings containing newlines are automatically rendered as multiline +strings. + + >>> color("This\n is a multiline\n string!") + <pyval><val-quote>'''</val-quote><val-string>This</val-string> + <val-string> is a multiline</val-string> + <val-string> string!</val-string><val-quote>'''</val-quote></pyval> + +Unicode strings are handled properly. + + >>> color(u"Hello world") + <pyval><val-quote>u'</val-quote><val-string>Hello world</val-string><val-quote>'</val-quote></pyval> + >>> color(u"\uaaaa And \ubbbb") + <pyval><val-quote>u'</val-quote><val-string>\uaaaa And \ubbbb</val-string><val-quote>'</val-quote></pyval> + +Lists, Tuples, etc. +=================== +Lists, tuples, and sets are all colorized using the same method. The +braces and commas are tagged with "op". If the value can fit on the +current line, it is displayed on one line. Otherwise, each value is +listed on a separate line, indented by the size of the open-bracket. + + >>> color(range(10)) + <pyval><val-group>[</val-group>0<val-op>, </val-op>1<val-op>, </val-op>2<val-op>, </val-op>3<val-op>, </val-op>4<val-op>, </val-op>5<val-op>, </val-op>6<val-op>, </val-op>7<val-op>, </val-op>8<val-op>, </val-op>9<val-group>]</val-group></pyval> + >>> color(range(100)) + <pyval><val-group>[</val-group>0<val-op>,</val-op> + 1<val-op>,</val-op> + 2<val-op>,</val-op> + 3<val-op>,</val-op> + 4<val-op>,</val-op> + <ellipsis /></pyval> + >>> color([1,2,[5,6,[(11,22,33),9],10],11]+[99,98,97,96,95]) + <pyval><val-group>[</val-group>1<val-op>,</val-op> + 2<val-op>,</val-op> + <val-group>[</val-group>5<val-op>, </val-op>6<val-op>, </val-op><val-group>[</val-group><val-group>(</val-group>11<val-op>, </val-op>22<val-op>, </val-op>33<val-group>)</val-group><val-op>, </val-op>9<val-group>]</val-group><val-op>, </val-op>10<val-group>]</val-group><val-op>,</val-op> + 11<val-op>,</val-op> + 99<val-op>,</val-op> + <ellipsis /></pyval> + >>> color(set(range(20))) + <pyval><val-group>set([</val-group>0<val-op>,</val-op> + 1<val-op>,</val-op> + 2<val-op>,</val-op> + 3<val-op>,</val-op> + 4<val-op>,</val-op> + <ellipsis /></pyval> + +Dictionaries +============ +Dicts are treated just like lists, except that the ":" is also tagged as +"op". + + >>> color({1:33, 2:[1,2,3,{7:'oo'*20}]}) + <pyval><val-group>{</val-group>1<val-op>: </val-op>33<val-op>,</val-op> + 2<val-op>: </val-op><val-group>[</val-group>1<val-op>,</val-op> + 2<val-op>,</val-op> + 3<val-op>,</val-op> + <val-group>{</val-group>7<val-op>: </val-op><val-quote>'</val-quote><val-string>oooooooooooooooooooooooooooooo</val-string><linewrap /> + <ellipsis /></pyval> + +Regular Expressions +=================== + + >>> import re + >>> def color_re(s, check_roundtrip=True): + ... val = colorizer.colorize(re.compile(s)) + ... if check_roundtrip: + ... roundtrip_val = re.sub('</?[\w-]+>', '', val) + ... roundtrip_val = roundtrip_val.replace('>', '>') + ... roundtrip_val = roundtrip_val.replace('<', '<') + ... roundtrip_val = roundtrip_val.replace('&', '&') + ... assert roundtrip_val == s, roundtrip_val + ... print val + + >>> # Literal characters + >>> color_re(u'abc \t\r\n\f\v \xff \uffff \U000fffff', False) + <pyval>abc \t\r\n\f\v \xff \uffff \U000fffff</pyval> + >>> color_re(r'\.\^\$\\\*\+\?\{\}\[\]\|\(\)') + <pyval>\.\^\$\\\*\+\?\{\}\[\]\|\(\)</pyval> + + >>> # Any character & character classes + >>> color_re(r".\d\D\s\S\w\W\A^$\b\B\Z") + <pyval>.\d\D\s\S\w\W\A^$\b\B\Z</pyval> + + >>> # Branching + >>> color_re(r"foo|bar") + <pyval>foo<re-op>|</re-op>bar</pyval> + + >>> # Character classes + >>> color_re(r"[abcd]") + <pyval><re-group>[</re-group>abcd<re-group>]</re-group></pyval> + + >>> # Repeats + >>> color_re(r"a*b+c{4,}d{,5}e{3,9}f?") + <pyval>a<re-op>*</re-op>b<re-op>+</re-op>c<re-op>{4,}</re-op>d<re-op>{,5}</re-op>e<re-op>{3,9}</re-op>f<re-op>?</re-op></pyval> + >>> color_re(r"a*?b+?c{4,}?d{,5}?e{3,9}?f??") + <pyval>a<re-op>*?</re-op>b<re-op>+?</re-op>c<re-op>{4,}?</re-op>d<re-op>{,5}?</re-op>e<re-op>{3,9}?</re-op>f<re-op>??</re-op></pyval> + + >>> # Subpatterns + >>> color_re(r"(foo (bar) | (baz))") + <pyval><re-group>(</re-group>foo <re-group>(</re-group>bar<re-group>)</re-group> <re-op>|</re-op> <re-group>(</re-group>baz<re-group>)</re-group><re-group>)</re-group></pyval> + >>> color_re(r"(?:foo (?:bar) | (?:baz))") + <pyval><re-group>(?:</re-group>foo <re-group>(?:</re-group>bar<re-group>)</re-group> <re-op>|</re-op> <re-group>(?:</re-group>baz<re-group>)</re-group><re-group>)</re-group></pyval> + >>> color_re("(foo (?P<a>bar) | (?P<boop>baz))") + <pyval><re-group>(</re-group>foo <re-group>(?P<</re-group><re-ref>a</re-ref><re-group>></re-group>bar<re-group>)</re-group> <re-op>|</re-op> <re-group>(?P<</re-group><re-ref>boop</re-ref><re-group>></re-group>baz<re-group>)</re-group><re-group>)</re-group></pyval> + + >>> # Group References + >>> color_re(r"(...) and (\1)") + <pyval><re-group>(</re-group>...<re-group>)</re-group> and <re-group>(</re-group><re-ref>\1</re-ref><re-group>)</re-group></pyval> + + >>> # Ranges + >>> color_re(r"[a-bp-z]") + <pyval><re-group>[</re-group>a<re-op>-</re-op>bp<re-op>-</re-op>z<re-group>]</re-group></pyval> + >>> color_re(r"[^a-bp-z]") + <pyval><re-group>[</re-group><re-op>^</re-op>a<re-op>-</re-op>bp<re-op>-</re-op>z<re-group>]</re-group></pyval> + >>> color_re(r"[^abc]") + <pyval><re-group>[</re-group><re-op>^</re-op>abc<re-group>]</re-group></pyval> + + >>> # Lookahead/behinds + >>> color_re(r"foo(?=bar)") + <pyval>foo<re-group>(?=</re-group>bar<re-group>)</re-group></pyval> + >>> color_re(r"foo(?!bar)") + <pyval>foo<re-group>(?!</re-group>bar<re-group>)</re-group></pyval> + >>> color_re(r"(?<=bar)foo") + <pyval><re-group>(?<=</re-group>bar<re-group>)</re-group>foo</pyval> + >>> color_re(r"(?<!bar)foo") + <pyval><re-group>(?<!</re-group>bar<re-group>)</re-group>foo</pyval> + + >>> # Flags + >>> color_re(r"(?im)^Food") + <pyval><re-flags>(?im)</re-flags>^Food</pyval> + >>> color_re(r"(?Limsx)^Food") + <pyval><re-flags>(?Limsx)</re-flags>^Food</pyval> + >>> color_re(r"(?Limstux)^Food") + <pyval><re-flags>(?Limstux)</re-flags>^Food</pyval> + >>> color_re(r"(?x)This is verbose", False) + <pyval><re-flags>(?x)</re-flags>Thisisverbose</pyval> + + + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |