Code

Fixed CGI client change messages so they actually include the properties
[roundup.git] / roundup / cgitb.py
1 #
2 # Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/)
3 # This module is free software, and you may redistribute it and/or modify
4 # under the same terms as Python, so long as this copyright message and
5 # disclaimer are retained in their original form.
6 #
7 # IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR
8 # DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
9 # OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE
10 # POSSIBILITY OF SUCH DAMAGE.
11 #
12 # BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 # FOR A PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS"
15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
17
18 # $Id: cgitb.py,v 1.5 2001-08-07 00:24:42 richard Exp $
20 import sys, os, types, string, keyword, linecache, tokenize, inspect, pydoc
22 def breaker():
23     return ('<body bgcolor="#f0f0ff">' +
24             '<font color="#f0f0ff" size="-5"> > </font> ' +
25             '</table>' * 5)
27 def html(context=5):
28     etype, evalue = sys.exc_type, sys.exc_value
29     if type(etype) is types.ClassType:
30         etype = etype.__name__
31     pyver = 'Python ' + string.split(sys.version)[0] + '<br>' + sys.executable
32     head = pydoc.html.heading(
33         '<font size=+1><strong>%s</strong>: %s</font>'%(str(etype), str(evalue)),
34         '#ffffff', '#aa55cc', pyver)
36     head = head + ('<p>A problem occurred while running a Python script. '
37                    'Here is the sequence of function calls leading up to '
38                    'the error, with the most recent (innermost) call first. '
39                    'The exception attributes are:')
41     indent = '<tt><small>%s</small>&nbsp;</tt>' % ('&nbsp;' * 5)
42     traceback = []
43     for frame, file, lnum, func, lines, index in inspect.trace(context):
44         if file is None:
45             link = '&lt;file is None - probably inside <tt>eval</tt> or <tt>exec</tt>&gt;'
46         else:
47             file = os.path.abspath(file)
48             link = '<a href="file:%s">%s</a>' % (file, pydoc.html.escape(file))
49         args, varargs, varkw, locals = inspect.getargvalues(frame)
50         if func == '?':
51             call = ''
52         else:
53             call = 'in <strong>%s</strong>' % func + inspect.formatargvalues(
54                     args, varargs, varkw, locals,
55                     formatvalue=lambda value: '=' + pydoc.html.repr(value))
57         level = '''
58 <table width="100%%" bgcolor="#d8bbff" cellspacing=0 cellpadding=2 border=0>
59 <tr><td>%s %s</td></tr></table>''' % (link, call)
61         if file is None:
62             traceback.append('<p>' + level)
63             continue
65         # do a fil inspection
66         names = []
67         def tokeneater(type, token, start, end, line, names=names):
68             if type == tokenize.NAME and token not in keyword.kwlist:
69                 if token not in names:
70                     names.append(token)
71             if type == tokenize.NEWLINE: raise IndexError
72         def linereader(file=file, lnum=[lnum]):
73             line = linecache.getline(file, lnum[0])
74             lnum[0] = lnum[0] + 1
75             return line
77         try:
78             tokenize.tokenize(linereader, tokeneater)
79         except IndexError: pass
80         lvals = []
81         for name in names:
82             if name in frame.f_code.co_varnames:
83                 if locals.has_key(name):
84                     value = pydoc.html.repr(locals[name])
85                 else:
86                     value = '<em>undefined</em>'
87                 name = '<strong>%s</strong>' % name
88             else:
89                 if frame.f_globals.has_key(name):
90                     value = pydoc.html.repr(frame.f_globals[name])
91                 else:
92                     value = '<em>undefined</em>'
93                 name = '<em>global</em> <strong>%s</strong>' % name
94             lvals.append('%s&nbsp;= %s' % (name, value))
95         if lvals:
96             lvals = string.join(lvals, ', ')
97             lvals = indent + '''
98 <small><font color="#909090">%s</font></small><br>''' % lvals
99         else:
100             lvals = ''
102         excerpt = []
103         i = lnum - index
104         for line in lines:
105             number = '&nbsp;' * (5-len(str(i))) + str(i)
106             number = '<small><font color="#909090">%s</font></small>' % number
107             line = '<tt>%s&nbsp;%s</tt>' % (number, pydoc.html.preformat(line))
108             if i == lnum:
109                 line = '''
110 <table width="100%%" bgcolor="#ffccee" cellspacing=0 cellpadding=0 border=0>
111 <tr><td>%s</td></tr></table>''' % line
112             excerpt.append('\n' + line)
113             if i == lnum:
114                 excerpt.append(lvals)
115             i = i + 1
116         traceback.append('<p>' + level + string.join(excerpt, '\n'))
118     traceback.reverse()
120     exception = '<p><strong>%s</strong>: %s' % (str(etype), str(evalue))
121     attribs = []
122     if type(evalue) is types.InstanceType:
123         for name in dir(evalue):
124             value = pydoc.html.repr(getattr(evalue, name))
125             attribs.append('<br>%s%s&nbsp;= %s' % (indent, name, value))
127     return head + string.join(attribs) + string.join(traceback) + '<p>&nbsp;</p>'
129 def handler():
130     print breaker()
131     print html()
134 # $Log: not supported by cvs2svn $
135 # Revision 1.4  2001/08/07 00:15:51  richard
136 # Added the copyright/license notice to (nearly) all files at request of
137 # Bizar Software.
139 # Revision 1.3  2001/07/29 07:01:39  richard
140 # Added vim command to all source so that we don't get no steenkin' tabs :)
142 # Revision 1.2  2001/07/22 12:09:32  richard
143 # Final commit of Grande Splite
145 # Revision 1.1  2001/07/22 11:58:35  richard
146 # More Grande Splite
149 # vim: set filetype=python ts=4 sw=4 et si