"""
Build error messages
"""
import traceback, sys, cgi, urllib
def truncate (msg, limit) :
"""
Truncate the given message to <limit> chars
"""
if len(msg) > limit :
return msg[:limit-3] + '...'
else :
return msg
def build_link (title, url) :
return '<a href="%s">%s</a>' % (cgi.escape(url, True), cgi.escape(title))
def build_error (exc_info=None, env=None) :
"""
Dumps out a raw traceback of the given/current exception to stdout.
If request_env, it should be a environment dict, like under WSGI, and will be used to display additional info
about the request.
Returns a (status, content-type, body) tuple, with all components being non-unicode strs.
"""
# default for exc_info is current exception
if not exc_info :
exc_info = sys.exc_info()
# request URL?
if env :
try :
from qmsk.web.http import request_url
url = request_url(env)
except :
# ignore
url = None
else :
url = None
# working copy path?
try :
from config import HG_WC_PATH, HGWEB_URL
wc_path = HG_WC_PATH
hgweb_url = HGWEB_URL
except :
# a good guess
wc_path = '.'
hgweb_url = None
# version?
try :
from version import version_string, version_link_hg
version = version_string(wc_path)
if hgweb_url :
version_href = version_link_hg(hgweb_url, wc_path)
else :
version_href = None
except :
version = None
version_href = None
# the exception type
exception_str = traceback.format_exception_only(*exc_info[:2])[-1]
# the exception traceback
traceback_lines = traceback.format_exception(*exc_info)
# XXX: make this configureable
trac_url = "http://projects.qmsk.net/irclogs2/trac"
# ticket list
trac_query = build_link("All tickets", "%s/query" % trac_url)
# submit ticket
submit_args = dict(type='defect')
# handle optional components
if url :
submit_args['url'] = url
trac_query_url = build_link("Same URL", "%s/query?url=%s" % (trac_url, urllib.quote(url)))
else :
trac_query_url = ""
if version :
submit_args['revision'] = version
trac_query_version = build_link("Same version", "%s/query?revision=%s" % (trac_url, urllib.quote(version)))
else :
trac_query_version = ""
if exception_str :
submit_args['summary'] = truncate(exception_str, 140)
trac_query_err = build_link("Same error", "%s/query?summary=%s" % (trac_url, urllib.quote(exception_str.rstrip())))
else :
trac_query_err = ""
if traceback_lines :
# this is big
submit_args['description'] = """\
[Insert any additional information here]
= Traceback =
{{{
%s
}}}""" % ''.join(traceback_lines)
# the trac newticket URL
submit_url = "%s/newticket?%s" % (trac_url, '&'.join('%s=%s' % (urllib.quote(k), urllib.quote(v)) for k, v in submit_args.iteritems()))
# return
return ('500 Internal Server Error', 'text/html; charset=UTF-8', ("""\
<html><head><title>500 Internal Server Error</title></head><body>
<h1>Oops!</h1>
<p>
An error occured, which was not logged, and was not reported to anybody. It might be your fault, or it might be mine.
</p>
<p>
You can try:
<ol style="list-style-type: lower-alpha">
<li><strong>Poking</strong> the administrator of this site to see if they respond</li>
<li><strong>Looking</strong> for similar issue tickets with:
<ul>
<li>%(trac_query)s</li>
<li>%(trac_query_url)s</li>
<li>%(trac_query_version)s</li>
<li>%(trac_query_err)s</li>
</ul>
</li>
<li><strong>Submitting</strong> a new ticket using the following link (quick & easy):</li>
</ol>
</p>
<pre>
<a href="%(submit_url)s">%(submit_url_short)s</a>
</pre>
<h2>Details:</h2>
<p>The page you tried to request was:</p>
<pre>
%(url)s
</pre>
<p>The software version is:</p>
<pre>
%(version_link)s
</pre>
<p>The error was:</p>
<pre>
%(exception)s
</pre>
<p>The traceback was:</p>
<pre>%(traceback)s</pre>
</body></html>""" % dict(
url = url if url else 'Unknown',
version_link = version_href if version_href else 'Unknown',
exception = truncate(exception_str, 512),
traceback = cgi.escape(''.join(' ' + line for line in traceback_lines)),
trac_query = trac_query,
trac_query_url = trac_query_url,
trac_query_version = trac_query_version,
trac_query_err = trac_query_err,
submit_url = submit_url,
submit_url_short = truncate(submit_url, 120)
)).encode('utf-8'))