Skip to content
Snippets Groups Projects
Commit 04a09d48 authored by Philip Jenvey's avatar Philip Jenvey
Browse files

fix the html_error_template not handling tracebacks from normal .py files with

a magic encoding comment
parent 4559801f
No related branches found
No related tags found
No related merge requests found
0.2.3
- fixed the html_error_template not handling tracebacks from
normal .py files with a magic encoding comment [ticket:88]
0.2.2
- cached blocks now use the current context when rendering
an expired section, instead of the original context
......
......@@ -7,6 +7,7 @@
"""exception classes"""
import traceback, sys, re
from mako import util
class MakoException(Exception):
pass
......@@ -139,7 +140,14 @@ class RichTraceback(object):
break
else:
try:
self.source = file(new_trcback[-1][0]).read()
# A normal .py file (not a Template)
fp = open(new_trcback[-1][0])
encoding = util.parse_encoding(fp)
fp.seek(0)
self.source = fp.read()
fp.close()
if encoding:
self.source = self.source.decode(encoding)
except IOError:
self.source = ''
self.lineno = new_trcback[-1][1]
......
......@@ -16,7 +16,7 @@ try:
except:
from StringIO import StringIO
import weakref, os, time
import codecs, re, weakref, os, time
try:
import threading
......@@ -130,6 +130,56 @@ class LRUCache(dict):
# on us. loop around and try again
break
# Regexp to match python magic encoding line
_PYTHON_MAGIC_COMMENT_re = re.compile(
r'[ \t\f]* \# .* coding[=:][ \t]*([-\w.]+)',
re.VERBOSE)
def parse_encoding(fp):
"""Deduce the encoding of a source file from magic comment.
It does this in the same way as the `Python interpreter`__
.. __: http://docs.python.org/ref/encodings.html
The ``fp`` argument should be a seekable file object.
"""
pos = fp.tell()
fp.seek(0)
try:
line1 = fp.readline()
has_bom = line1.startswith(codecs.BOM_UTF8)
if has_bom:
line1 = line1[len(codecs.BOM_UTF8):]
m = _PYTHON_MAGIC_COMMENT_re.match(line1)
if not m:
try:
import parser
parser.suite(line1)
except (ImportError, SyntaxError):
# Either it's a real syntax error, in which case the source
# is not valid python source, or line2 is a continuation of
# line1, in which case we don't want to scan line2 for a magic
# comment.
pass
else:
line2 = fp.readline()
m = _PYTHON_MAGIC_COMMENT_re.match(line2)
if has_bom:
if m:
raise SyntaxError, \
"python refuses to compile code with both a UTF8" \
" byte-order-mark and a magic encoding comment"
return 'utf_8'
elif m:
return m.group(1)
else:
return None
finally:
fp.seek(pos)
def restore__ast(_ast):
"""Attempt to restore the required classes to the _ast module if it
appears to be missing them
......
......@@ -60,6 +60,15 @@ ${u'привет'}
assert False, ("This function should trigger a CompileException, "
"but didn't")
def test_py_utf8_html_error_template(self):
try:
foo = u'日本'
raise RuntimeError('test')
except:
html_error = exceptions.html_error_template().render()
assert 'RuntimeError: test' in html_error
assert "foo = u'日本'" in html_error
def test_format_exceptions(self):
l = TemplateLookup(format_exceptions=True)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment