From cd7fdd8c918f1ccccd62910f2bb1837b7265e19d Mon Sep 17 00:00:00 2001 From: Philip Jenvey <pjenvey@underboss.org> Date: Fri, 22 Jan 2010 01:54:38 +0000 Subject: [PATCH] Further fixes to unicode handling of .py files with the html_error_template. fixes #88 --- CHANGES | 3 +++ lib/mako/exceptions.py | 32 ++++++++++++++++++++++++++++++-- test/exceptions_.py | 9 +++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index b9de2ad..46aa4da 100644 --- a/CHANGES +++ b/CHANGES @@ -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 diff --git a/lib/mako/exceptions.py b/lib/mako/exceptions.py index 444f004..aa529d7 100644 --- a/lib/mako/exceptions.py +++ b/lib/mako/exceptions.py @@ -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 @@ -78,6 +79,22 @@ class RichTraceback(object): 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: @@ -112,6 +129,17 @@ class RichTraceback(object): 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 @@ -174,7 +202,7 @@ Traceback (most recent call last): 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(): @@ -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"> diff --git a/test/exceptions_.py b/test/exceptions_.py index 43059f5..2cb5d1d 100644 --- a/test/exceptions_.py +++ b/test/exceptions_.py @@ -69,6 +69,15 @@ ${u'привет'} assert 'RuntimeError: test' in html_error assert "foo = u'日本'" 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: 日本' in html_error + assert "RuntimeError(u'日本')" in html_error + def test_format_exceptions(self): l = TemplateLookup(format_exceptions=True) -- GitLab