From f15f5f7fd77d93bf46b5db91e4f9820f25b7dd8d Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 26 May 2008 12:21:45 +0200 Subject: [PATCH] items have a higher priority than attributes now. That's compatible with Jinja1 and Django --HG-- branch : trunk --- jinja2/environment.py | 20 ++++++++++---------- jinja2/sandbox.py | 39 ++++++++++++++++++--------------------- tests/test_various.py | 10 ++++++++++ 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/jinja2/environment.py b/jinja2/environment.py index dc8bc25..acb5c02 100644 --- a/jinja2/environment.py +++ b/jinja2/environment.py @@ -288,19 +288,19 @@ class Environment(object): def subscribe(self, obj, argument): """Get an item or attribute of an object.""" - if isinstance(argument, basestring): - try: - attr = str(argument) - except: - pass - else: - try: - return getattr(obj, attr) - except AttributeError: - pass try: return obj[argument] except (TypeError, LookupError): + if isinstance(argument, basestring): + try: + attr = str(argument) + except: + pass + else: + try: + return getattr(obj, attr) + except AttributeError: + pass return self.undefined(obj=obj, name=argument) def parse(self, source, name=None, filename=None): diff --git a/jinja2/sandbox.py b/jinja2/sandbox.py index b0de8e7..ce3369b 100644 --- a/jinja2/sandbox.py +++ b/jinja2/sandbox.py @@ -164,30 +164,27 @@ class SandboxedEnvironment(Environment): def subscribe(self, obj, argument): """Subscribe an object from sandboxed code.""" - is_unsafe = False - if isinstance(argument, basestring): - try: - attr = str(argument) - except: - pass - else: - try: - value = getattr(obj, attr) - except AttributeError: - pass - else: - if self.is_safe_attribute(obj, argument, value): - return value - is_unsafe = True try: return obj[argument] except (TypeError, LookupError): - if is_unsafe: - return self.undefined('access to attribute %r of %r object is' - ' unsafe.' % ( - argument, - obj.__class__.__name__ - ), name=argument, exc=SecurityError) + if isinstance(argument, basestring): + try: + attr = str(argument) + except: + pass + else: + try: + value = getattr(obj, attr) + except AttributeError: + pass + else: + if self.is_safe_attribute(obj, argument, value): + return value + return self.undefined('access to attribute %r of %r ' + 'object is unsafe.' % ( + argument, + obj.__class__.__name__ + ), name=argument, exc=SecurityError) return self.undefined(obj=obj, name=argument) def call(__self, __context, __obj, *args, **kwargs): diff --git a/tests/test_various.py b/tests/test_various.py index 147f459..7a3882e 100644 --- a/tests/test_various.py +++ b/tests/test_various.py @@ -58,3 +58,13 @@ def test_markup_leaks(): escape(u"") counts.add(len(gc.get_objects())) assert len(counts) == 1, 'ouch, c extension seems to leak objects' + + +def test_item_before_attribute(): + from jinja2 import Environment + from jinja2.sandbox import SandboxedEnvironment + + for env in Environment(), SandboxedEnvironment(): + tmpl = env.from_string('{{ foo.items() }}') + assert tmpl.render(foo={'items': lambda: 42}) == '42' + assert tmpl.render(foo={}) == '[]' -- 2.26.2