blob: c9640e61ec18e57b1e626d40034da30e4a48b3e4 [file]
# exceptions.py
# Copyright (C) 2006 Michael Bayer mike_mp@zzzcomputing.com
#
# This module is part of Mako and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
"""exception classes"""
import traceback, sys, re
class MakoException(Exception):
pass
class RuntimeException(MakoException):
pass
def _format_filepos(lineno, pos, filename):
if filename is None:
return " at line: %d char: %d" % (lineno, pos)
else:
return " in file '%s' at line: %d char: %d" % (filename, lineno, pos)
class CompileException(MakoException):
def __init__(self, message, lineno, pos, filename):
MakoException.__init__(self, message + _format_filepos(lineno, pos, filename))
self.lineno =lineno
self.pos = pos
self.filename = filename
class SyntaxException(MakoException):
def __init__(self, message, lineno, pos, filename):
MakoException.__init__(self, message + _format_filepos(lineno, pos, filename))
self.lineno =lineno
self.pos = pos
self.filename = filename
class TemplateLookupException(MakoException):
pass
def rich_traceback():
"""format a traceback from sys.exc_info() into 7-item tuples, containing
the regular four traceback tuple items, plus the original template
filename, the line number adjusted relative to the template source, and
code line from that line number of the template."""
import mako.template
mods = {}
(type, value, trcback) = sys.exc_info()
rawrecords = traceback.extract_tb(trcback)
# this line extends the stack all the way back....shouldnt be needed...
# rawrecords = traceback.extract_stack() + rawrecords
new_trcback = []
for filename, lineno, function, line in rawrecords:
try:
(line_map, template_lines) = mods[filename]
except KeyError:
try:
info = mako.template._get_module_info(filename)
module_source = info.code
template_source = info.source
template_filename = info.template_filename
except KeyError:
new_trcback.append((filename, lineno, function, line, None, None, None))
continue
template_ln = module_ln = 1
line_map = {}
for line in module_source.split("\n"):
match = re.match(r'\s*# SOURCE LINE (\d+)', line)
if match:
template_ln = int(match.group(1))
else:
template_ln += 1
module_ln += 1
line_map[module_ln] = template_ln
template_lines = [line for line in template_source.split("\n")]
mods[filename] = (line_map, template_lines)
template_ln = line_map[lineno]
template_line = template_lines[template_ln - 1]
new_trcback.append((filename, lineno, function, line, template_filename, template_ln, template_line))
return (type, value, new_trcback)
# TODO: this is scratch, make a module for exception reporting templates
def get_error_template():
import mako.template
return mako.template.Template("""
<%!
from mako.exceptions import rich_traceback
%>
<html>
<body>
Error !
<%
(type, value, trcback) = rich_traceback()
%>
${str(type)} - ${value}
% for (filename, lineno, function, line, template_filename, template_ln, template_line) in trcback:
% if template_line:
${template_filename} ${template_ln} ${template_line} <br/>
% endif
% endfor
</body>
</html>
""")