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