Skip to content

Commit 79d14f4

Browse files
committed
Fix exception causes in lookup.py
Mako now performs exception chaining using ``raise from``, correctly identifying underlying exception conditions when it raises its own exceptions. Pull request courtesy Ram Rachum. Additionally includes cleanup of the test suite to include better exception fixtures. Closes: #319 Pull-request: sqlalchemy/mako#319 Pull-request-sha: d06526ac3f80ca9d24cd8143d8afde254f80b094 Additionally: Fixes: #348 Change-Id: Ibb2864de822bf4b63adf22a6bb32cf0758d296bd
1 parent 29d10a9 commit 79d14f4

34 files changed

+554
-302
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.. change::
2+
:tags: bug, py3k
3+
4+
Mako now performs exception chaining using ``raise from``, correctly
5+
identifying underlying exception conditions when it raises its own
6+
exceptions. Pull request courtesy Ram Rachum.

mako/lookup.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ def get_template(self, uri):
241241
return self._check(uri, self._collection[uri])
242242
else:
243243
return self._collection[uri]
244-
except KeyError:
244+
except KeyError as e:
245245
u = re.sub(r"^\/+", "", uri)
246246
for dir_ in self.directories:
247247
# make sure the path seperators are posix - os.altsep is empty
@@ -252,8 +252,8 @@ def get_template(self, uri):
252252
return self._load(srcfile, uri)
253253
else:
254254
raise exceptions.TopLevelLookupException(
255-
"Cant locate template for uri %r" % uri
256-
)
255+
"Can't locate template for uri %r" % uri
256+
) from e
257257

258258
def adjust_uri(self, uri, relativeto):
259259
"""Adjust the given ``uri`` based on the given relative URI."""
@@ -337,11 +337,11 @@ def _check(self, uri, template):
337337
return template
338338
self._collection.pop(uri, None)
339339
return self._load(template.filename, uri)
340-
except OSError:
340+
except OSError as e:
341341
self._collection.pop(uri, None)
342342
raise exceptions.TemplateLookupException(
343-
"Cant locate template for uri %r" % uri
344-
)
343+
"Can't locate template for uri %r" % uri
344+
) from e
345345

346346
def put_string(self, uri, text):
347347
"""Place a new :class:`.Template` object into this

mako/pyparser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def parse(code, mode="exec", **exception_kwargs):
3434

3535
try:
3636
return _ast_util.parse(code, "<unknown>", mode)
37-
except Exception:
37+
except Exception as e:
3838
raise exceptions.SyntaxException(
3939
"(%s) %s (%r)"
4040
% (
@@ -43,7 +43,7 @@ def parse(code, mode="exec", **exception_kwargs):
4343
code[0:50],
4444
),
4545
**exception_kwargs,
46-
)
46+
) from e
4747

4848

4949
class FindIdentifiers(_ast_util.NodeVisitor):

mako/runtime.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,10 @@ def _lookup_template(context, uri, relativeto):
835835
uri = lookup.adjust_uri(uri, relativeto)
836836
try:
837837
return lookup.get_template(uri)
838-
except exceptions.TopLevelLookupException:
839-
raise exceptions.TemplateLookupException(str(compat.exception_as()))
838+
except exceptions.TopLevelLookupException as e:
839+
raise exceptions.TemplateLookupException(
840+
str(compat.exception_as())
841+
) from e
840842

841843

842844
def _populate_self_namespace(context, template, self_ns=None):

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ exclude =
4444
[options.extras_require]
4545
babel =
4646
Babel
47-
lingua =
47+
lingua =
4848
lingua
4949

5050
[options.entry_points]

test/__init__.py

Lines changed: 0 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -1,195 +0,0 @@
1-
import contextlib
2-
import os
3-
import re
4-
import unittest
5-
from unittest import mock # noqa
6-
7-
from mako.cache import CacheImpl
8-
from mako.cache import register_plugin
9-
from mako.template import Template
10-
from mako.util import update_wrapper
11-
12-
template_base = os.path.join(os.path.dirname(__file__), "templates")
13-
module_base = os.path.join(template_base, "modules")
14-
15-
16-
class TemplateTest(unittest.TestCase):
17-
def _file_template(self, filename, **kw):
18-
filepath = self._file_path(filename)
19-
return Template(
20-
uri=filename, filename=filepath, module_directory=module_base, **kw
21-
)
22-
23-
def _file_path(self, filename):
24-
name, ext = os.path.splitext(filename)
25-
py3k_path = os.path.join(template_base, name + "_py3k" + ext)
26-
if os.path.exists(py3k_path):
27-
return py3k_path
28-
29-
return os.path.join(template_base, filename)
30-
31-
def _do_file_test(
32-
self,
33-
filename,
34-
expected,
35-
filters=None,
36-
unicode_=True,
37-
template_args=None,
38-
**kw,
39-
):
40-
t1 = self._file_template(filename, **kw)
41-
self._do_test(
42-
t1,
43-
expected,
44-
filters=filters,
45-
unicode_=unicode_,
46-
template_args=template_args,
47-
)
48-
49-
def _do_memory_test(
50-
self,
51-
source,
52-
expected,
53-
filters=None,
54-
unicode_=True,
55-
template_args=None,
56-
**kw,
57-
):
58-
t1 = Template(text=source, **kw)
59-
self._do_test(
60-
t1,
61-
expected,
62-
filters=filters,
63-
unicode_=unicode_,
64-
template_args=template_args,
65-
)
66-
67-
def _do_test(
68-
self,
69-
template,
70-
expected,
71-
filters=None,
72-
template_args=None,
73-
unicode_=True,
74-
):
75-
if template_args is None:
76-
template_args = {}
77-
if unicode_:
78-
output = template.render_unicode(**template_args)
79-
else:
80-
output = template.render(**template_args)
81-
82-
if filters:
83-
output = filters(output)
84-
eq_(output, expected)
85-
86-
87-
def eq_(a, b, msg=None):
88-
"""Assert a == b, with repr messaging on failure."""
89-
assert a == b, msg or "%r != %r" % (a, b)
90-
91-
92-
def teardown():
93-
import shutil
94-
95-
shutil.rmtree(module_base, True)
96-
97-
98-
@contextlib.contextmanager
99-
def raises(except_cls, message=None):
100-
try:
101-
yield
102-
success = False
103-
except except_cls as e:
104-
if message:
105-
assert re.search(message, str(e), re.UNICODE), "%r !~ %s" % (
106-
message,
107-
e,
108-
)
109-
print(str(e).encode("utf-8"))
110-
success = True
111-
112-
# assert outside the block so it works for AssertionError too !
113-
assert success, "Callable did not raise an exception"
114-
115-
116-
def assert_raises(except_cls, callable_, *args, **kw):
117-
with raises(except_cls):
118-
return callable_(*args, **kw)
119-
120-
121-
def assert_raises_message(except_cls, msg, callable_, *args, **kwargs):
122-
with raises(except_cls, msg):
123-
return callable_(*args, **kwargs)
124-
125-
126-
def skip_if(predicate, reason=None):
127-
"""Skip a test if predicate is true."""
128-
reason = reason or predicate.__name__
129-
130-
def decorate(fn):
131-
fn_name = fn.__name__
132-
133-
def maybe(*args, **kw):
134-
if predicate():
135-
msg = "'%s' skipped: %s" % (fn_name, reason)
136-
raise unittest.SkipTest(msg)
137-
else:
138-
return fn(*args, **kw)
139-
140-
return update_wrapper(maybe, fn)
141-
142-
return decorate
143-
144-
145-
def requires_pygments_14(fn):
146-
try:
147-
import pygments
148-
149-
version = pygments.__version__
150-
except:
151-
version = "0"
152-
return skip_if(
153-
lambda: version < "1.4", "Requires pygments 1.4 or greater"
154-
)(fn)
155-
156-
157-
def requires_no_pygments_exceptions(fn):
158-
def go(*arg, **kw):
159-
from mako import exceptions
160-
161-
exceptions._install_fallback()
162-
try:
163-
return fn(*arg, **kw)
164-
finally:
165-
exceptions._install_highlighting()
166-
167-
return update_wrapper(go, fn)
168-
169-
170-
class PlainCacheImpl(CacheImpl):
171-
"""Simple memory cache impl so that tests which
172-
use caching can run without beaker."""
173-
174-
def __init__(self, cache):
175-
self.cache = cache
176-
self.data = {}
177-
178-
def get_or_create(self, key, creation_function, **kw):
179-
if key in self.data:
180-
return self.data[key]
181-
else:
182-
self.data[key] = data = creation_function(**kw)
183-
return data
184-
185-
def put(self, key, value, **kw):
186-
self.data[key] = value
187-
188-
def get(self, key, **kw):
189-
return self.data[key]
190-
191-
def invalidate(self, key, **kw):
192-
del self.data[key]
193-
194-
195-
register_plugin("plain", __name__, "PlainCacheImpl")

test/ext/test_babelplugin.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import os
33
import unittest
44

5-
from .. import skip_if
6-
from .. import template_base
7-
from .. import TemplateTest
5+
from ..util.exclusions import skip_if
6+
from ..util.fixtures import template_base
7+
from ..util.fixtures import TemplateTest
88

99
try:
1010
import babel.messages.extract as babel

test/ext/test_linguaplugin.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import os
22

3-
from .. import skip_if
4-
from .. import template_base
5-
from .. import TemplateTest
3+
from ..util.exclusions import skip_if
4+
from ..util.fixtures import template_base
5+
from ..util.fixtures import TemplateTest
66

77
try:
88
import lingua

test/test_ast.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from mako import ast
44
from mako import exceptions
55
from mako import pyparser
6-
from test import eq_
6+
from .util.assertions import eq_
77

88
exception_kwargs = {"source": "", "lineno": 0, "pos": 0, "filename": ""}
99

test/test_block.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from mako import exceptions
22
from mako.lookup import TemplateLookup
33
from mako.template import Template
4-
from test import assert_raises_message
5-
from test import TemplateTest
6-
from test.util import result_lines
4+
from .util.assertions import assert_raises_message
5+
from .util.fixtures import TemplateTest
6+
from .util.helpers import result_lines
77

88

99
class BlockTest(TemplateTest):

0 commit comments

Comments
 (0)