1c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley# mako/exceptions.py 2c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file> 3c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley# 4c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley# This module is part of Mako and is released under 5c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley# the MIT License: http://www.opensource.org/licenses/mit-license.php 6c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 7c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley"""exception classes""" 8c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 9c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyimport traceback 10c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyimport sys 11c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyfrom mako import util, compat 12c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 13c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass MakoException(Exception): 14c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pass 15c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 16c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass RuntimeException(MakoException): 17c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pass 18c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 19c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleydef _format_filepos(lineno, pos, filename): 20c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if filename is None: 21c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return " at line: %d char: %d" % (lineno, pos) 22c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley else: 23c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return " in file '%s' at line: %d char: %d" % (filename, lineno, pos) 24c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 25c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 26c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass CompileException(MakoException): 27c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def __init__(self, message, source, lineno, pos, filename): 28c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley MakoException.__init__(self, 29c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley message + _format_filepos(lineno, pos, filename)) 30c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.lineno = lineno 31c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.pos = pos 32c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.filename = filename 33c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.source = source 34c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 35c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass SyntaxException(MakoException): 36c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def __init__(self, message, source, lineno, pos, filename): 37c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley MakoException.__init__(self, 38c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley message + _format_filepos(lineno, pos, filename)) 39c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.lineno = lineno 40c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.pos = pos 41c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.filename = filename 42c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.source = source 43c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 44c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass UnsupportedError(MakoException): 45c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """raised when a retired feature is used.""" 46c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 47c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass NameConflictError(MakoException): 48c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """raised when a reserved word is used inappropriately""" 49c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 50c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass TemplateLookupException(MakoException): 51c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pass 52c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 53c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass TopLevelLookupException(TemplateLookupException): 54c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pass 55c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 56c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleyclass RichTraceback(object): 57c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """Pull the current exception from the ``sys`` traceback and extracts 58c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley Mako-specific template information. 59c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 60c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley See the usage examples in :ref:`handling_exceptions`. 61c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 62c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """ 63c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def __init__(self, error=None, traceback=None): 64c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.source, self.lineno = "", 0 65c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 66c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if error is None or traceback is None: 67c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley t, value, tback = sys.exc_info() 68c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 69c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if error is None: 70c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley error = value or t 71c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 72c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if traceback is None: 73c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley traceback = tback 74c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 75c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.error = error 76c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.records = self._init(traceback) 77c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 78c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if isinstance(self.error, (CompileException, SyntaxException)): 79c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.source = self.error.source 80c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.lineno = self.error.lineno 81c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self._has_source = True 82c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 83c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self._init_message() 84c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 85c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley @property 86c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def errorname(self): 87c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return compat.exception_name(self.error) 88c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 89c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def _init_message(self): 90c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """Find a unicode representation of self.error""" 91c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley try: 92c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.message = compat.text_type(self.error) 93c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley except UnicodeError: 94c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley try: 95c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.message = str(self.error) 96c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley except UnicodeEncodeError: 97c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley # Fallback to args as neither unicode nor 98c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley # str(Exception(u'\xe6')) work in Python < 2.6 99c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.message = self.error.args[0] 100c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if not isinstance(self.message, compat.text_type): 101c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.message = compat.text_type(self.message, 'ascii', 'replace') 102c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 103c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def _get_reformatted_records(self, records): 104c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley for rec in records: 105c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if rec[6] is not None: 106c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley yield (rec[4], rec[5], rec[2], rec[6]) 107c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley else: 108c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley yield tuple(rec[0:4]) 109c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 110c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley @property 111c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def traceback(self): 112c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """Return a list of 4-tuple traceback records (i.e. normal python 113c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley format) with template-corresponding lines remapped to the originating 114c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template. 115c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 116c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """ 117c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return list(self._get_reformatted_records(self.records)) 118c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 119c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley @property 120c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def reverse_records(self): 121c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return reversed(self.records) 122c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 123c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley @property 124c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def reverse_traceback(self): 125c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """Return the same data as traceback, except in reverse order. 126c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """ 127c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 128c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return list(self._get_reformatted_records(self.reverse_records)) 129c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 130c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def _init(self, trcback): 131c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """format a traceback from sys.exc_info() into 7-item tuples, 132c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley containing the regular four traceback tuple items, plus the original 133c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template filename, the line number adjusted relative to the template 134c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley source, and code line from that line number of the template.""" 135c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 136c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley import mako.template 137c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley mods = {} 138c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley rawrecords = traceback.extract_tb(trcback) 139c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley new_trcback = [] 140c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley for filename, lineno, function, line in rawrecords: 141c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if not line: 142c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley line = '' 143c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley try: 144c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley (line_map, template_lines) = mods[filename] 145c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley except KeyError: 146c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley try: 147c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley info = mako.template._get_module_info(filename) 148c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley module_source = info.code 149c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template_source = info.source 150c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template_filename = info.template_filename or filename 151c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley except KeyError: 152c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley # A normal .py file (not a Template) 153c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if not compat.py3k: 154c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley try: 155c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley fp = open(filename, 'rb') 156c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley encoding = util.parse_encoding(fp) 157c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley fp.close() 158c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley except IOError: 159c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley encoding = None 160c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if encoding: 161c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley line = line.decode(encoding) 162c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley else: 163c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley line = line.decode('ascii', 'replace') 164c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley new_trcback.append((filename, lineno, function, line, 165c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley None, None, None, None)) 166c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley continue 167c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 168c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template_ln = 1 169c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 170c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley source_map = mako.template.ModuleInfo.\ 171c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley get_module_source_metadata( 172c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley module_source, full_line_map=True) 173c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley line_map = source_map['full_line_map'] 174c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 175c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template_lines = [line for line in 176c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template_source.split("\n")] 177c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley mods[filename] = (line_map, template_lines) 178c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 179c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template_ln = line_map[lineno - 1] 180c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 181c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if template_ln <= len(template_lines): 182c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template_line = template_lines[template_ln - 1] 183c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley else: 184c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template_line = None 185c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley new_trcback.append((filename, lineno, function, 186c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley line, template_filename, template_ln, 187c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template_line, template_source)) 188c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if not self.source: 189c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley for l in range(len(new_trcback) - 1, 0, -1): 190c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if new_trcback[l][5]: 191c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.source = new_trcback[l][7] 192c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.lineno = new_trcback[l][5] 193c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley break 194c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley else: 195c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if new_trcback: 196c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley try: 197c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley # A normal .py file (not a Template) 198c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley fp = open(new_trcback[-1][0], 'rb') 199c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley encoding = util.parse_encoding(fp) 200c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley fp.seek(0) 201c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.source = fp.read() 202c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley fp.close() 203c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if encoding: 204c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.source = self.source.decode(encoding) 205c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley except IOError: 206c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.source = '' 207c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley self.lineno = new_trcback[-1][1] 208c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return new_trcback 209c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 210c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 211c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleydef text_error_template(lookup=None): 212c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """Provides a template that renders a stack trace in a similar format to 213c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley the Python interpreter, substituting source template filenames, line 214c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley numbers and code for that of the originating source template, as 215c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley applicable. 216c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 217c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """ 218c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley import mako.template 219c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return mako.template.Template(r""" 220c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<%page args="error=None, traceback=None"/> 221c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<%! 222c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley from mako.exceptions import RichTraceback 223c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley%>\ 224c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<% 225c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley tback = RichTraceback(error=error, traceback=traceback) 226c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley%>\ 227c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim RowleyTraceback (most recent call last): 228c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% for (filename, lineno, function, line) in tback.traceback: 229c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley File "${filename}", line ${lineno}, in ${function or '?'} 230c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley ${line | trim} 231c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% endfor 232c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley${tback.errorname}: ${tback.message} 233c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley""") 234c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 235c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 236c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleydef _install_pygments(): 237c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley global syntax_highlight, pygments_html_formatter 238c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley from mako.ext.pygmentplugin import syntax_highlight,\ 239c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pygments_html_formatter 240c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 241c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleydef _install_fallback(): 242c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley global syntax_highlight, pygments_html_formatter 243c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley from mako.filters import html_escape 244c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pygments_html_formatter = None 245c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley def syntax_highlight(filename='', language=None): 246c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return html_escape 247c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 248c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleydef _install_highlighting(): 249c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley try: 250c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley _install_pygments() 251c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley except ImportError: 252c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley _install_fallback() 253c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley_install_highlighting() 254c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 255c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowleydef html_error_template(): 256c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """Provides a template that renders a stack trace in an HTML format, 257c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley providing an excerpt of code as well as substituting source template 258c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley filenames, line numbers and code for that of the originating source 259c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley template, as applicable. 260c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 261c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley The template's default ``encoding_errors`` value is 262c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley ``'htmlentityreplace'``. The template has two options. With the 263c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley ``full`` option disabled, only a section of an HTML document is 264c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley returned. With the ``css`` option disabled, the default stylesheet 265c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley won't be included. 266c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 267c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley """ 268c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley import mako.template 269c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley return mako.template.Template(r""" 270c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<%! 271c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley from mako.exceptions import RichTraceback, syntax_highlight,\ 272c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pygments_html_formatter 273c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley%> 274c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<%page args="full=True, css=True, error=None, traceback=None"/> 275c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% if full: 276c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<html> 277c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<head> 278c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <title>Mako Runtime Error</title> 279c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% endif 280c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% if css: 281c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <style> 282c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley body { font-family:verdana; margin:10px 30px 10px 30px;} 283c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .stacktrace { margin:5px 5px 5px 5px; } 284c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .highlight { padding:0px 10px 0px 10px; background-color:#9F9FDF; } 285c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .nonhighlight { padding:0px; background-color:#DFDFDF; } 286c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .sample { padding:10px; margin:10px 10px 10px 10px; 287c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley font-family:monospace; } 288c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .sampleline { padding:0px 10px 0px 10px; } 289c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .sourceline { margin:5px 5px 10px 5px; font-family:monospace;} 290c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .location { font-size:80%; } 291c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .highlight { white-space:pre; } 292c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .sampleline { white-space:pre; } 293c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 294c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley % if pygments_html_formatter: 295c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley ${pygments_html_formatter.get_style_defs()} 296c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .linenos { min-width: 2.5em; text-align: right; } 297c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pre { margin: 0; } 298c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .syntax-highlighted { padding: 0 10px; } 299c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .syntax-highlightedtable { border-spacing: 1px; } 300c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .nonhighlight { border-top: 1px solid #DFDFDF; 301c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley border-bottom: 1px solid #DFDFDF; } 302c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .stacktrace .nonhighlight { margin: 5px 15px 10px; } 303c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .sourceline { margin: 0 0; font-family:monospace; } 304c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .code { background-color: #F8F8F8; width: 100%; } 305c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .error .code { background-color: #FFBDBD; } 306c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley .error .syntax-highlighted { background-color: #FFBDBD; } 307c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley % endif 308c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 309c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley </style> 310c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% endif 311c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% if full: 312c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley</head> 313c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<body> 314c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% endif 315c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 316c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<h2>Error !</h2> 317c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<% 318c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley tback = RichTraceback(error=error, traceback=traceback) 319c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley src = tback.source 320c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley line = tback.lineno 321c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if src: 322c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley lines = src.split('\n') 323c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley else: 324c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley lines = None 325c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley%> 326c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<h3>${tback.errorname}: ${tback.message|h}</h3> 327c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 328c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% if lines: 329c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <div class="sample"> 330c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <div class="nonhighlight"> 331c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% for index in range(max(0, line-4),min(len(lines), line+5)): 332c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <% 333c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if pygments_html_formatter: 334c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pygments_html_formatter.linenostart = index + 1 335c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley %> 336c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley % if index + 1 == line: 337c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <% 338c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if pygments_html_formatter: 339c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley old_cssclass = pygments_html_formatter.cssclass 340c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pygments_html_formatter.cssclass = 'error ' + old_cssclass 341c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley %> 342c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley ${lines[index] | syntax_highlight(language='mako')} 343c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <% 344c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if pygments_html_formatter: 345c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pygments_html_formatter.cssclass = old_cssclass 346c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley %> 347c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley % else: 348c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley ${lines[index] | syntax_highlight(language='mako')} 349c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley % endif 350c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% endfor 351c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley </div> 352c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley </div> 353c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% endif 354c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 355c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley<div class="stacktrace"> 356c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% for (filename, lineno, function, line) in tback.reverse_traceback: 357c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <div class="location">${filename}, line ${lineno}:</div> 358c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <div class="nonhighlight"> 359c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <% 360c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley if pygments_html_formatter: 361c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley pygments_html_formatter.linenostart = lineno 362c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley %> 363c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley <div class="sourceline">${line | syntax_highlight(filename)}</div> 364c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley </div> 365c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% endfor 366c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley</div> 367c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley 368c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% if full: 369c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley</body> 370c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley</html> 371c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley% endif 372c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley""", output_encoding=sys.getdefaultencoding(), 373c6e67f5a9373e916a8d2333585cb5787aa5f7bb7Tim Rowley encoding_errors='htmlentityreplace') 374