Skip to content

Commit

Permalink
fix the html_error_template not handling tracebacks from normal .py f…
Browse files Browse the repository at this point in the history
…iles with

a magic encoding comment
  • Loading branch information
pjenvey committed Jul 8, 2008
1 parent 4559801 commit 04a09d4
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
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
Expand Down
10 changes: 9 additions & 1 deletion lib/mako/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"""exception classes"""

import traceback, sys, re
from mako import util

class MakoException(Exception):
pass
Expand Down Expand Up @@ -139,7 +140,14 @@ def _init(self):
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]
Expand Down
52 changes: 51 additions & 1 deletion lib/mako/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
except:
from StringIO import StringIO

import weakref, os, time
import codecs, re, weakref, os, time

try:
import threading
Expand Down Expand Up @@ -130,6 +130,56 @@ def _manage_size(self):
# 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
Expand Down
9 changes: 9 additions & 0 deletions test/exceptions_.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ def test_utf8_html_error_template(self):
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)

Expand Down

0 comments on commit 04a09d4

Please sign in to comment.