Skip to content

Commit

Permalink
Undefineds now support attribute errors for special attributes. This f…
Browse files Browse the repository at this point in the history
…ixes #6
  • Loading branch information
mitsuhiko committed Nov 19, 2010
1 parent ab014bd commit 6a3e95d
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGES
Expand Up @@ -5,6 +5,10 @@ Version 2.6
-----------
(codename to be selected, release date to be announced)

- internal attributes now raise an internal attribute error now instead
of returning an undefined. This fixes problems when passing undefined
objects to Python semantics expecting APIs.

Version 2.5.5
-------------
(re-release of 2.5.4 with built documentation removed for filesize.
Expand Down
10 changes: 8 additions & 2 deletions jinja2/runtime.py
Expand Up @@ -458,11 +458,17 @@ def _fail_with_undefined_error(self, *args, **kwargs):
hint = self._undefined_hint
raise self._undefined_exception(hint)

@internalcode
def __getattr__(self, name):
if name[:2] == '__':
raise AttributeError(name)
return self._fail_with_undefined_error()

__add__ = __radd__ = __mul__ = __rmul__ = __div__ = __rdiv__ = \
__truediv__ = __rtruediv__ = __floordiv__ = __rfloordiv__ = \
__mod__ = __rmod__ = __pos__ = __neg__ = __call__ = \
__getattr__ = __getitem__ = __lt__ = __le__ = __gt__ = __ge__ = \
__int__ = __float__ = __complex__ = __pow__ = __rpow__ = \
__getitem__ = __lt__ = __le__ = __gt__ = __ge__ = __int__ = \
__float__ = __complex__ = __pow__ = __rpow__ = \
_fail_with_undefined_error

def __str__(self):
Expand Down
8 changes: 8 additions & 0 deletions jinja2/testsuite/api.py
Expand Up @@ -180,6 +180,14 @@ def test():
t = Template('A{{ test().missingattribute }}B')
self.assert_raises(UndefinedError, t.render, test=test)

def test_undefined_and_special_attributes(self):
try:
Undefined('Foo').__dict__
except AttributeError:
pass
else:
assert False, "Expected actual attribute error"

def test_default_undefined(self):
env = Environment(undefined=Undefined)
self.assert_equal(env.from_string('{{ missing }}').render(), u'')
Expand Down
7 changes: 3 additions & 4 deletions jinja2/testsuite/security.py
Expand Up @@ -56,6 +56,7 @@ def test_unsafe(self):
self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()), '23')
self.assert_equal(env.from_string("{{ foo.__class__ }}").render(foo=42), '')
self.assert_equal(env.from_string("{{ foo.func_code }}").render(foo=lambda:None), '')
# security error comes from __class__ already.
self.assert_raises(SecurityError, env.from_string(
"{{ foo.__class__.__subclasses__() }}").render, foo=42)

Expand Down Expand Up @@ -108,7 +109,6 @@ def __unicode__(self):
assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
assert Markup("&lt;test&gt;").unescape() == "<test>"


def test_template_data(self):
env = Environment(autoescape=True)
t = env.from_string('{% macro say_hello(name) %}'
Expand All @@ -121,11 +121,10 @@ def test_template_data(self):
assert t.module.say_hello('<blink>foo</blink>') == escaped_out
assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out


def test_attr_filter(self):
env = SandboxedEnvironment()
tmpl = env.from_string('{{ 42|attr("__class__")|attr("__subclasses__")() }}')
self.assert_raises(SecurityError, tmpl.render)
tmpl = env.from_string('{{ cls|attr("__subclasses__")() }}')
self.assert_raises(SecurityError, tmpl.render, cls=int)


def suite():
Expand Down

0 comments on commit 6a3e95d

Please sign in to comment.