1 #
2 # This module was written by Ka-Ping Yee, <ping@lfw.org>.
3 #
4 # $Id: cgitb.py,v 1.3 2002-09-06 07:23:29 richard Exp $
6 __doc__ = """
7 Extended CGI traceback handler by Ka-Ping Yee, <ping@lfw.org>.
8 """
10 import sys, os, types, string, keyword, linecache, tokenize, inspect, pydoc
12 from roundup.i18n import _
14 def breaker():
15 return ('<body bgcolor="white">' +
16 '<font color="white" size="-5"> > </font> ' +
17 '</table>' * 5)
19 def niceDict(indent, dict):
20 l = []
21 for k,v in dict.items():
22 l.append('%s%s: %r'%(indent,k,v))
23 return '\n'.join(l)
25 def pt_html(context=5):
26 import cgi
27 etype, evalue = sys.exc_type, sys.exc_value
28 if type(etype) is types.ClassType:
29 etype = etype.__name__
30 pyver = 'Python ' + string.split(sys.version)[0] + '<br>' + sys.executable
31 head = pydoc.html.heading(
32 '<font size=+1><strong>%s</strong>: %s</font>'%(etype, evalue),
33 '#ffffff', '#777777', pyver)
35 head = head + _('<p>A problem occurred in your template</p><pre>')
37 l = []
38 for frame, file, lnum, func, lines, index in inspect.trace(context):
39 args, varargs, varkw, locals = inspect.getargvalues(frame)
40 if locals.has_key('__traceback_info__'):
41 ti = locals['__traceback_info__']
42 l.append(str(ti))
43 if locals.has_key('__traceback_supplement__'):
44 ts = locals['__traceback_supplement__']
45 if len(ts) == 2:
46 supp, context = ts
47 l.append('in template %r'%context.id)
48 elif len(ts) == 3:
49 supp, context, info = ts
50 l.append('in expression %r\n current variables:\n%s\n%s\n'%(info,
51 niceDict(' ', context.global_vars),
52 niceDict(' ', context.local_vars)))
53 # context._scope_stack))
54 return head + cgi.escape('\n'.join(l)) + '</pre><p> </p>'
56 def html(context=5):
57 etype, evalue = sys.exc_type, sys.exc_value
58 if type(etype) is types.ClassType:
59 etype = etype.__name__
60 pyver = 'Python ' + string.split(sys.version)[0] + '<br>' + sys.executable
61 head = pydoc.html.heading(
62 '<font size=+1><strong>%s</strong>: %s</font>'%(etype, evalue),
63 '#ffffff', '#777777', pyver)
65 head = head + (_('<p>A problem occurred while running a Python script. '
66 'Here is the sequence of function calls leading up to '
67 'the error, with the most recent (innermost) call first. '
68 'The exception attributes are:'))
70 indent = '<tt><small>%s</small> </tt>' % (' ' * 5)
71 traceback = []
72 for frame, file, lnum, func, lines, index in inspect.trace(context):
73 if file is None:
74 link = '''<file is None - probably inside <tt>eval</tt> or
75 <tt>exec</tt>>'''
76 else:
77 file = os.path.abspath(file)
78 link = '<a href="file:%s">%s</a>' % (file, pydoc.html.escape(file))
79 args, varargs, varkw, locals = inspect.getargvalues(frame)
80 if func == '?':
81 call = ''
82 else:
83 call = 'in <strong>%s</strong>' % func + inspect.formatargvalues(
84 args, varargs, varkw, locals,
85 formatvalue=lambda value: '=' + pydoc.html.repr(value))
87 level = '''
88 <table width="100%%" bgcolor="#dddddd" cellspacing=0 cellpadding=2 border=0>
89 <tr><td>%s %s</td></tr></table>''' % (link, call)
91 if index is None or file is None:
92 traceback.append('<p>' + level)
93 continue
95 # do a file inspection
96 names = []
97 def tokeneater(type, token, start, end, line, names=names):
98 if type == tokenize.NAME and token not in keyword.kwlist:
99 if token not in names:
100 names.append(token)
101 if type == tokenize.NEWLINE: raise IndexError
102 def linereader(file=file, lnum=[lnum]):
103 line = linecache.getline(file, lnum[0])
104 lnum[0] = lnum[0] + 1
105 return line
107 try:
108 tokenize.tokenize(linereader, tokeneater)
109 except IndexError:
110 pass
111 lvals = []
112 for name in names:
113 if name in frame.f_code.co_varnames:
114 if locals.has_key(name):
115 value = pydoc.html.repr(locals[name])
116 else:
117 value = _('<em>undefined</em>')
118 name = '<strong>%s</strong>' % name
119 else:
120 if frame.f_globals.has_key(name):
121 value = pydoc.html.repr(frame.f_globals[name])
122 else:
123 value = _('<em>undefined</em>')
124 name = '<em>global</em> <strong>%s</strong>' % name
125 lvals.append('%s = %s'%(name, value))
126 if lvals:
127 lvals = string.join(lvals, ', ')
128 lvals = indent + '<small><font color="#909090">%s'\
129 '</font></small><br>'%lvals
130 else:
131 lvals = ''
133 excerpt = []
134 i = lnum - index
135 for line in lines:
136 number = ' ' * (5-len(str(i))) + str(i)
137 number = '<small><font color="#909090">%s</font></small>' % number
138 line = '<tt>%s %s</tt>' % (number, pydoc.html.preformat(line))
139 if i == lnum:
140 line = '''
141 <table width="100%%" bgcolor="#white" cellspacing=0 cellpadding=0 border=0>
142 <tr><td>%s</td></tr></table>''' % line
143 excerpt.append('\n' + line)
144 if i == lnum:
145 excerpt.append(lvals)
146 i = i + 1
147 traceback.append('<p>' + level + string.join(excerpt, '\n'))
149 traceback.reverse()
151 exception = '<p><strong>%s</strong>: %s' % (str(etype), str(evalue))
152 attribs = []
153 if type(evalue) is types.InstanceType:
154 for name in dir(evalue):
155 value = pydoc.html.repr(getattr(evalue, name))
156 attribs.append('<br>%s%s = %s' % (indent, name, value))
158 return head + string.join(attribs) + string.join(traceback) + '<p> </p>'
160 def handler():
161 print breaker()
162 print html()
164 #
165 # $Log: not supported by cvs2svn $
166 # Revision 1.2 2002/09/06 07:21:31 richard
167 # much nicer error messages when there's a templating error
168 #
169 # Revision 1.1 2002/08/30 08:28:44 richard
170 # New CGI interface support
171 #
172 # Revision 1.10 2002/01/16 04:49:45 richard
173 # Handle a special case that the CGI interface tickles. I need to check if
174 # this needs fixing in python's core.
175 #
176 # Revision 1.9 2002/01/08 11:56:24 richard
177 # missed an import _
178 #
179 # Revision 1.8 2002/01/05 02:22:32 richard
180 # i18n'ification
181 #
182 # Revision 1.7 2001/11/22 15:46:42 jhermann
183 # Added module docstrings to all modules.
184 #
185 # Revision 1.6 2001/09/29 13:27:00 richard
186 # CGI interfaces now spit up a top-level index of all the instances they can
187 # serve.
188 #
189 # Revision 1.5 2001/08/07 00:24:42 richard
190 # stupid typo
191 #
192 # Revision 1.4 2001/08/07 00:15:51 richard
193 # Added the copyright/license notice to (nearly) all files at request of
194 # Bizar Software.
195 #
196 # Revision 1.3 2001/07/29 07:01:39 richard
197 # Added vim command to all source so that we don't get no steenkin' tabs :)
198 #
199 # Revision 1.2 2001/07/22 12:09:32 richard
200 # Final commit of Grande Splite
201 #
202 # Revision 1.1 2001/07/22 11:58:35 richard
203 # More Grande Splite
204 #
205 #
206 # vim: set filetype=python ts=4 sw=4 et si