[Epydoc-commits] SF.net SVN: epydoc: [1466] trunk/epydoc/src/epydoc
Brought to you by:
edloper
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. |