Commits

jayven committed 72f6a11

go on add pretty_tb

  • Participants
  • Parent commits 1b787fa
  • Branches add_traceback_html

Comments (0)

Files changed (3)

     linecache.checkcache(filename)
     lines = linecache.getlines(filename, g)
     line = linecache.getline(filename, lineno, g)
-    if not line or not lines:
-        return '', []
+    if not lines:
+        return [(lineno, line)]
 
     b, e = lineno - lines_around - 1, lineno + lines_around
     if b < 0:
     if e > len(lines):
         e = len(lines)
 
-    return line, [(ln, l) for ln, l in izip(
+    return [(ln, l) for ln, l in izip(
         xrange(b + 1, e + 1), islice(lines, b, e))]
 
 
 def iter_tracback(tb, lines_around=7):
     depth = 1
 
+    # skip the first
+    tb = tb.tb_next
+
     while tb is not None:
         f = tb.tb_frame
         co = f.f_code
         filename = co.co_filename
         lineno = tb.tb_lineno
         where = co.co_name
-        line, lines = get_file_part(filename, lineno, lines_around,
-                f.f_globals)
-        yield depth, filename, where, lineno, line, lines, f.f_locals
+        lines = get_file_part(filename, lineno, lines_around, f.f_globals)
+        yield depth, filename, where, lineno, lines, f.f_locals
 
         tb = tb.tb_next
         depth += 1
 
         # now add tracebacks
         lines_around = context.get('lines_around', 5)
-        tb = last_traceback.tb_next # skip the first one
 
-        for depth, filename, where, lineno, line, lines, local in \
+        for depth, filename, where, lineno, lines, local in \
                 codebase.iter_tracback(tb, lines_around):
 
+            line = dict(lines)[lineno]
+
             if lines:
                 w = len(str(lines[-1][0]))
                 lines = ''.join(("%*d. %s" % (w, ln) for ln, l in lines))
 # -*- coding: utf-8 -*-
 # vim: set ai et si ts=4 sts=4 sw=4:
 
+import cgi
 import codebase
 
 
+_id_gen = None
+
+
+def gen_id():
+    global _id_gen
+    if _id_gen is None:
+        def _id_generator(start=1):
+            while True:
+                yield 'id%.10d' % start
+                start += 1
+        _id_gen = _id_generator()
+    return _id_gen.next()
+
+
+def html_encode(x):
+    return cgi.escape(str(x))
+
+
 def pretty_tb(exc_type, exc_value, exc_tb):
     res = []
-    res.append('<h1>%s</h1>' % exc_type)
-    res.append('<h2>%s</h2>' % exc_value)
-    res.append('<h2>Tracebacks</h2>')
-    res.append('<ul class="traceback">')
+    def _(template, *args):
+        res.append(template % tuple(map(html_encode, args)))
 
-    tb = exc_tb.tb_next # skip the first one
+    _('''
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <title>%s</title>
+    <style type="text/css">
+    ol.precode {
+        cursor: pointer;
+        display: none;
+    }
+    ol.midcode {
+        cursor: pointer;
+    }
+    ol.postcode {
+        cursor: pointer;
+        display: none;
+    }
+    </style>
+    <script type="text/javascript">
+    //<!--
+    function toggle() {
+        for (var i=0; i < arguments.length; i++) {
+            var e = document.getElementById(arguments[i]);
+            if (e) {
+                e.style.display = e.style.display != 'none' ? 'none' : 'block';
+            }
+        }
+    }
+    //-->
+    </script>
+</head>
+<body>
+    ''', exc_type)
     
-    for depth, filename, where, lineno, line, lines, local in \
-            codebase.iter_tracback(tb, 7):
-        res.append('<li class="tb">')
-        res.append('<code>%s</code> in <code>%s</code>' % (filename, where))
-        if lines:
-            res.append('<ol start="%d">' % lines[0][0])
-            for l in lines:
-                res.append('<li><code>%s</code></li>' % l[1])
-        else:
-            pass
+    _('<h1>%s</h1>', exc_type)
+    _('<h2>%s</h2>', exc_value)
+    _('<h2>Tracebacks</h2>')
+    _('<ul>')
 
-        res.append('</li>')
+    tobe_hide = []
 
-    res.append('</ul>')
+    for depth, filename, where, lineno, lines, local in \
+            codebase.iter_tracback(exc_tb, 7):
+        _('<li>')
+            
+        # code
+        pre_id, mid_id, post_id = gen_id(), gen_id(), gen_id()
+        tobe_hide.append(pre_id)
+        tobe_hide.append(post_id)
+
+        _('<div>')
+        _('<code>%s</code> in <code>%s</code>', filename, where)
+
+        start_lineno = lines[0][0]
+        _('<ol start="%s" id="%s" class="precode">', start_lineno, pre_id)
+        for ln, line in lines[:lineno - start_lineno]:
+            _('<li><code onclick="toggle(\'%s\',\'%s\')">%s</code></li>',
+                    pre_id, post_id, line)
+        _('</ol>')
+
+        _('<ol start="%s" id="%s" class="midcode">', lineno, mid_id)
+        _('<li><code onclick="toggle(\'%s\',\'%s\')">%s</code></li>',
+                pre_id, post_id, lines[lineno - start_lineno][1])
+        _('</ol>')
+        
+        _('<ol start="%s" id="%s" class="postcode">', lineno + 1, post_id)
+        for ln, line in lines[lineno - start_lineno + 1:]:
+            _('<li><code onclick="toggle(\'%s\',\'%s\')">%s</code></li>',
+                    pre_id, post_id, line)
+        _('</ol>')
+
+        _('</div>')
+
+        # local
+        _('<div>')
+        _('<a href="#"><span>&#x25b6;</span> Local Vars</a>')
+        _('<table class="vars" style="display:none">')
+        _('<thead><tr><th>Name</th><th>Value</th></tr></thead>')
+        for name, value in local.iteritems():
+            _('<tr><td><code>%s</code></td><td><code>%s</code></td></tr>',
+                    name, value)
+        _('</table>')
+        _('</div>')
+
+        _('</li>')
+
+    _('</ul>')
+    _('</body>')
+
     return '\n'.join(res)