Skip to content

Commit

Permalink
Further fixes to unicode handling of .py files with the
Browse files Browse the repository at this point in the history
html_error_template. fixes #88
  • Loading branch information
pjenvey committed Jan 22, 2010
1 parent 2adc041 commit cd7fdd8
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
- Support the <%namespacename:defname> syntax in
the babel extractor. [ticket:118]

- Further fixes to unicode handling of .py files with the
html_error_template. [ticket:88]

0.2.5
- Added a "decorator" kw argument to <%def>,
allows custom decoration functions to wrap
Expand Down
32 changes: 30 additions & 2 deletions lib/mako/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class RichTraceback(object):
Properties:
error - the exception instance.
message - the exception error message as unicode
source - source code of the file where the error occured. if the error occured within a compiled template,
this is the template source.
lineno - line number where the error occured. if the error occured within a compiled template, the line number
Expand All @@ -78,6 +79,22 @@ def __init__(self, traceback=None):
self._has_source = True
self.reverse_records = [r for r in self.records]
self.reverse_records.reverse()
self.init_message()

def init_message(self):
"""Find a unicode representation of self.error"""
try:
self.message = unicode(self.error)
except UnicodeError:
try:
self.message = str(self.error)
except UnicodeEncodeError:
# Fallback to args as neither unicode nor
# str(Exception(u'\xe6')) work in Python < 2.6
self.message = self.error.args[0]
if not isinstance(self.message, unicode):
self.message = unicode(self.message, 'ascii', 'replace')

def _get_reformatted_records(self, records):
for rec in records:
if rec[6] is not None:
Expand Down Expand Up @@ -112,6 +129,17 @@ def _init(self, trcback):
template_source = info.source
template_filename = info.template_filename or filename
except KeyError:
# A normal .py file (not a Template)
try:
fp = open(filename)
encoding = util.parse_encoding(fp)
fp.close()
except IOError:
encoding = None
if encoding:
line = line.decode(encoding)
else:
line = line.decode('ascii', 'replace')
new_trcback.append((filename, lineno, function, line, None, None, None, None))
continue

Expand Down Expand Up @@ -174,7 +202,7 @@ def text_error_template(lookup=None):
File "${filename}", line ${lineno}, in ${function or '?'}
${line | unicode.strip}
% endfor
${str(tback.error.__class__.__name__)}: ${str(tback.error)}
${str(tback.error.__class__.__name__)}: ${tback.message}
""")

def html_error_template():
Expand Down Expand Up @@ -225,7 +253,7 @@ def html_error_template():
else:
lines = None
%>
<h3>${str(tback.error.__class__.__name__)}: ${str(tback.error)}</h3>
<h3>${str(tback.error.__class__.__name__)}: ${tback.message}</h3>
% if lines:
<div class="sample">
Expand Down
9 changes: 9 additions & 0 deletions test/exceptions_.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ def test_py_utf8_html_error_template(self):
assert 'RuntimeError: test' in html_error
assert "foo = u'&#x65E5;&#x672C;'" in html_error


def test_py_unicode_error_html_error_template(self):
try:
raise RuntimeError(u'日本')
except:
html_error = exceptions.html_error_template().render()
assert 'RuntimeError: &#x65E5;&#x672C;' in html_error
assert "RuntimeError(u'&#x65E5;&#x672C;')" in html_error

def test_format_exceptions(self):
l = TemplateLookup(format_exceptions=True)

Expand Down

0 comments on commit cd7fdd8

Please sign in to comment.