root/galaxy-central/eggs/Mako-0.2.5-py2.6.egg/mako/exceptions.py @ 3

リビジョン 3, 9.4 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1# exceptions.py
2# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
3#
4# This module is part of Mako and is released under
5# the MIT License: http://www.opensource.org/licenses/mit-license.php
6
7"""exception classes"""
8
9import traceback, sys, re
10from mako import util
11
12class MakoException(Exception):
13    pass
14
15class RuntimeException(MakoException):
16    pass
17
18def _format_filepos(lineno, pos, filename):
19    if filename is None:
20        return " at line: %d char: %d" % (lineno, pos)
21    else:
22        return " in file '%s' at line: %d char: %d" % (filename, lineno, pos)     
23class CompileException(MakoException):
24    def __init__(self, message, source, lineno, pos, filename):
25        MakoException.__init__(self, message + _format_filepos(lineno, pos, filename))
26        self.lineno =lineno
27        self.pos = pos
28        self.filename = filename
29        self.source = source
30                   
31class SyntaxException(MakoException):
32    def __init__(self, message, source, lineno, pos, filename):
33        MakoException.__init__(self, message + _format_filepos(lineno, pos, filename))
34        self.lineno =lineno
35        self.pos = pos
36        self.filename = filename
37        self.source = source
38       
39class TemplateLookupException(MakoException):
40    pass
41
42class TopLevelLookupException(TemplateLookupException):
43    pass
44   
45class RichTraceback(object):
46    """pulls the current exception from the sys traceback and extracts Mako-specific
47    template information.
48   
49    Usage:
50   
51    RichTraceback()
52   
53    Properties:
54   
55    error - the exception instance. 
56    source - source code of the file where the error occured.  if the error occured within a compiled template,
57    this is the template source.
58    lineno - line number where the error occured.  if the error occured within a compiled template, the line number
59    is adjusted to that of the template source
60    records - a list of 8-tuples containing the original python traceback elements, plus the
61    filename, line number, source line, and full template source for the traceline mapped back to its originating source
62    template, if any for that traceline (else the fields are None).
63    reverse_records - the list of records in reverse
64    traceback - a list of 4-tuples, in the same format as a regular python traceback, with template-corresponding
65    traceback records replacing the originals
66    reverse_traceback - the traceback list in reverse
67   
68    """
69    def __init__(self, traceback=None):
70        (self.source, self.lineno) = ("", 0)
71        (t, self.error, self.records) = self._init(traceback)
72        if self.error is None:
73            self.error = t
74        if isinstance(self.error, CompileException) or isinstance(self.error, SyntaxException):
75            import mako.template
76            self.source = self.error.source
77            self.lineno = self.error.lineno
78            self._has_source = True
79        self.reverse_records = [r for r in self.records]
80        self.reverse_records.reverse()
81    def _get_reformatted_records(self, records):
82        for rec in records:
83            if rec[6] is not None:
84                yield (rec[4], rec[5], rec[2], rec[6])
85            else:
86                yield tuple(rec[0:4])
87    traceback = property(lambda self:self._get_reformatted_records(self.records), doc="""
88        return a list of 4-tuple traceback records (i.e. normal python format)
89        with template-corresponding lines remapped to the originating template
90    """)
91    reverse_traceback = property(lambda self:self._get_reformatted_records(self.reverse_records), doc="""
92        return the same data as traceback, except in reverse order
93    """)
94    def _init(self, trcback):
95        """format a traceback from sys.exc_info() into 7-item tuples, containing
96        the regular four traceback tuple items, plus the original template
97        filename, the line number adjusted relative to the template source, and
98        code line from that line number of the template."""
99        import mako.template
100        mods = {}
101        if not trcback:
102            (type, value, trcback) = sys.exc_info()
103        rawrecords = traceback.extract_tb(trcback)
104        new_trcback = []
105        for filename, lineno, function, line in rawrecords:
106            try:
107                (line_map, template_lines) = mods[filename]
108            except KeyError:
109                try:
110                    info = mako.template._get_module_info(filename)
111                    module_source = info.code
112                    template_source = info.source
113                    template_filename = info.template_filename or filename
114                except KeyError:
115                    new_trcback.append((filename, lineno, function, line, None, None, None, None))
116                    continue
117
118                template_ln = module_ln = 1
119                line_map = {}
120                for line in module_source.split("\n"):
121                    match = re.match(r'\s*# SOURCE LINE (\d+)', line)
122                    if match:
123                        template_ln = int(match.group(1))
124                    else:
125                        template_ln += 1
126                    module_ln += 1
127                    line_map[module_ln] = template_ln
128                template_lines = [line for line in template_source.split("\n")]
129                mods[filename] = (line_map, template_lines)
130
131            template_ln = line_map[lineno]
132            if template_ln <= len(template_lines):
133                template_line = template_lines[template_ln - 1]
134            else:
135                template_line = None
136            new_trcback.append((filename, lineno, function, line, template_filename, template_ln, template_line, template_source))
137        if not self.source:
138            for l in range(len(new_trcback)-1, 0, -1):
139                if new_trcback[l][5]:
140                    self.source = new_trcback[l][7]
141                    self.lineno = new_trcback[l][5]
142                    break
143            else:
144                try:
145                    # A normal .py file (not a Template)
146                    fp = open(new_trcback[-1][0])
147                    encoding = util.parse_encoding(fp)
148                    fp.seek(0)
149                    self.source = fp.read()
150                    fp.close()
151                    if encoding:
152                        self.source = self.source.decode(encoding)
153                except IOError:
154                    self.source = ''
155                self.lineno = new_trcback[-1][1]
156        return (type, value, new_trcback)
157
158               
159def text_error_template(lookup=None):
160    """provides a template that renders a stack trace in a similar format to the Python interpreter,
161    substituting source template filenames, line numbers and code for that of the originating
162    source template, as applicable."""
163    import mako.template
164    return mako.template.Template(r"""
165<%page args="traceback=None"/>
166<%!
167    from mako.exceptions import RichTraceback
168%>\
169<%
170    tback = RichTraceback(traceback=traceback)
171%>\
172Traceback (most recent call last):
173% for (filename, lineno, function, line) in tback.traceback:
174  File "${filename}", line ${lineno}, in ${function or '?'}
175    ${line | unicode.strip}
176% endfor
177${str(tback.error.__class__.__name__)}: ${str(tback.error)}
178""")
179
180def html_error_template():
181    """provides a template that renders a stack trace in an HTML format, providing an excerpt of
182    code as well as substituting source template filenames, line numbers and code
183    for that of the originating source template, as applicable.
184
185    the template's default encoding_errors value is 'htmlentityreplace'. the template has
186    two options:
187
188    with the full option disabled, only a section of an HTML document is returned.
189    with the css option disabled, the default stylesheet won't be included."""
190    import mako.template
191    return mako.template.Template(r"""
192<%!
193    from mako.exceptions import RichTraceback
194%>
195<%page args="full=True, css=True, traceback=None"/>
196% if full:
197<html>
198<head>
199    <title>Mako Runtime Error</title>
200% endif
201% if css:
202    <style>
203        body { font-family:verdana; margin:10px 30px 10px 30px;}
204        .stacktrace { margin:5px 5px 5px 5px; }
205        .highlight { padding:0px 10px 0px 10px; background-color:#9F9FDF; }
206        .nonhighlight { padding:0px; background-color:#DFDFDF; }
207        .sample { padding:10px; margin:10px 10px 10px 10px; font-family:monospace; }
208        .sampleline { padding:0px 10px 0px 10px; }
209        .sourceline { margin:5px 5px 10px 5px; font-family:monospace;}
210        .location { font-size:80%; }
211    </style>
212% endif
213% if full:
214</head>
215<body>
216% endif
217
218<h2>Error !</h2>
219<%
220    tback = RichTraceback(traceback=traceback)
221    src = tback.source
222    line = tback.lineno
223    if src:
224        lines = src.split('\n')
225    else:
226        lines = None
227%>
228<h3>${str(tback.error.__class__.__name__)}: ${str(tback.error)}</h3>
229
230% if lines:
231    <div class="sample">
232    <div class="nonhighlight">
233% for index in range(max(0, line-4),min(len(lines), line+5)):
234    % if index + 1 == line:
235<div class="highlight">${index + 1} ${lines[index] | h}</div>
236    % else:
237<div class="sampleline">${index + 1} ${lines[index] | h}</div>
238    % endif
239% endfor
240    </div>
241    </div>
242% endif
243
244<div class="stacktrace">
245% for (filename, lineno, function, line) in tback.reverse_traceback:
246    <div class="location">${filename}, line ${lineno}:</div>
247    <div class="sourceline">${line | h}</div>
248% endfor
249</div>
250
251% if full:
252</body>
253</html>
254% endif
255""", output_encoding=sys.getdefaultencoding(), encoding_errors='htmlentityreplace')
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。