# Set SECRET to write tracebacks to files instead of showing them to users.
SECRET = 0

def reset():
    """Attempt to reset the CGI and browser to a known state."""
    return '''<!--: spam
Content-Type: text/html

<body bgcolor="#f0f0ff"><font color="#f0f0ff" size="-5"> -->
<body bgcolor="#f0f0ff"><font color="#f0f0ff" size="-5"> --> -->
</font> </font> </font> </script> </object> </blockquote> </pre>
</table> </table> </table> </table> </table> </font> </font> </font>'''

def html(etype, evalue, etb, context=5):
    """Return a nice HTML document describing the traceback."""
    import sys, os, types, string, time, traceback
    import keyword, tokenize, linecache, inspect, pydoc

    if type(etype) is types.ClassType:
        etype = etype.__name__
    pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
    date = time.ctime(time.time())
    head = '<body bgcolor="#f0f0ff">' + pydoc.html.heading(
        '<big><big><strong>%s</strong></big></big>' % str(etype),
        '#ffffff', '#aa55cc', pyver + '<br>' + date) + '''
<p>A problem occurred in a Python script.
Here is the sequence of function calls leading up to
the error, with the most recent (innermost) call last.'''

    indent = '<tt><small>%s</small>&nbsp;</tt>' % ('&nbsp;' * 5)
    frames = []
    records = inspect.getinnerframes(etb, context)
    for frame, file, lnum, func, lines, index in records:
        file = file and os.path.abspath(file) or '?'
        link = '<a href="file:%s">%s</a>' % (file, pydoc.html.escape(file))
        args, varargs, varkw, locals = inspect.getargvalues(frame)
        if func == '?':
            call = ''
        else:
	    def eqrepr(value, repr=pydoc.html.repr): return '=' + repr(value)
            call = 'in <strong>%s</strong>' % func + inspect.formatargvalues(
                    args, varargs, varkw, locals, formatvalue=eqrepr)

        names = []
        def tokeneater(type, token, start, end, line,
                       names=names, kwlist=keyword.kwlist,
		       NAME=tokenize.NAME, NEWLINE=tokenize.NEWLINE):
            if type == NAME and token not in kwlist:
                if token not in names: names.append(token)
            if type == NEWLINE: raise IndexError
        def linereader(file=file, lnum=[lnum], getline=linecache.getline):
            line = getline(file, lnum[0])
            lnum[0] = lnum[0] + 1
            return line

        try:
            tokenize.tokenize(linereader, tokeneater)
        except IndexError: pass
        lvals = []
        for name in names:
            if name in frame.f_code.co_varnames:
                if locals.has_key(name):
                    value = pydoc.html.repr(locals[name])
                else:
                    value = '<em>undefined</em>'
                name = '<strong>%s</strong>' % name
            else:
                if frame.f_globals.has_key(name):
                    value = pydoc.html.repr(frame.f_globals[name])
                else:
                    value = '<em>undefined</em>'
                name = '<em>global</em> <strong>%s</strong>' % name
            lvals.append('%s&nbsp;= %s' % (name, value))
        if lvals:
            lvals = string.join(lvals, ', ')
            lvals = indent + '''
<small><font color="#909090">%s</font></small><br>''' % lvals
        else:
            lvals = ''

        level = '''
<table width="100%%" bgcolor="#d8bbff" cellspacing=0 cellpadding=2 border=0>
<tr><td>%s %s</td></tr></table>\n''' % (link, call)
        excerpt = []
        if index is not None:
            i = lnum - index
            for line in lines:
                num = '<small><font color="#909090">%s</font></small>' % (
                    '&nbsp;' * (5-len(str(i))) + str(i))
                line = '<tt>%s&nbsp;%s</tt>' % (num, pydoc.html.preformat(line))
                if i == lnum:
                    line = '''
<table width="100%%" bgcolor="#ffccee" cellspacing=0 cellpadding=0 border=0>
<tr><td>%s</td></tr></table>\n''' % line
                excerpt.append('\n' + line)
                if i == lnum:
                    excerpt.append(lvals)
                i = i + 1
        frames.append('<p>' + level + string.join(excerpt, '\n'))

    exception = ['<p><strong>%s</strong>: %s' % (str(etype), str(evalue))]
    if type(evalue) is types.InstanceType:
        for name in dir(evalue):
            value = pydoc.html.repr(getattr(evalue, name))
            exception.append('\n<br>%s%s&nbsp;=\n%s' % (indent, name, value))
        
    import traceback
    plaintrace = string.join(traceback.format_exception(etype, evalue, etb))

    return head + string.join(frames) + string.join(exception) + '''


<!-- The above is a description of an error that occurred in a Python program.
     It is formatted for display in a Web browser because it appears that
     we are running in a CGI environment.  In case you are viewing this
     message outside of a Web browser, here is the original error traceback:

%s
-->
''' % plaintrace

def handler(info=None):
    import sys
    (etype, evalue, etb) = info or sys.exc_info()
    print reset()

    if SECRET:
        print '<p>A problem occurred in a Python script.'
        print '<p>Details of the problem have been withheld.'

        import string, tempfile
        try:
            doc = html(etype, evalue, etb)
            filename = tempfile.mktemp() + '.html'
        except:
            doc = string.join(traceback.format_exception(etype, evalue, etb))
            filename = tempfile.mktemp()
        try:
            file = open(filename, 'w')
            file.write(doc)
            file.close()
            print 'A description was written to the file: %s' % filename
        except:
            print 'Tried to write a description to %s, but failed.' % filename

    else:
        # Just in case something goes wrong in html(), send errors to stdout.
        sys.stderr = sys.stdout
        sys.stderr.write('<pre>')

        doc = html(etype, evalue, etb)
        print '</pre>', doc

def excepthook(etype, evalue, etb):
    """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
    handler((etype, evalue, etb))
