mirror of
https://github.com/django/django.git
synced 2024-12-01 15:42:04 +01:00
Fixed #7153 -- _resolve_lookup now does a better job of resolving callables and correctly catches all silent_variable_exceptions
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14992 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
6fc7d829dc
commit
df6ad35c56
@ -674,12 +674,22 @@ class Variable(object):
|
|||||||
instead.
|
instead.
|
||||||
"""
|
"""
|
||||||
current = context
|
current = context
|
||||||
|
try: # catch-all for silent variable failures
|
||||||
for bit in self.lookups:
|
for bit in self.lookups:
|
||||||
try: # dictionary lookup
|
try: # dictionary lookup
|
||||||
current = current[bit]
|
current = current[bit]
|
||||||
except (TypeError, AttributeError, KeyError):
|
except (TypeError, AttributeError, KeyError):
|
||||||
try: # attribute lookup
|
try: # attribute lookup
|
||||||
current = getattr(current, bit)
|
current = getattr(current, bit)
|
||||||
|
except (TypeError, AttributeError):
|
||||||
|
try: # list-index lookup
|
||||||
|
current = current[int(bit)]
|
||||||
|
except (IndexError, # list index out of range
|
||||||
|
ValueError, # invalid literal for int()
|
||||||
|
KeyError, # current is a dict without `int(bit)` key
|
||||||
|
TypeError, # unsubscriptable object
|
||||||
|
):
|
||||||
|
raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bit, current)) # missing attribute
|
||||||
if callable(current):
|
if callable(current):
|
||||||
if getattr(current, 'alters_data', False):
|
if getattr(current, 'alters_data', False):
|
||||||
current = settings.TEMPLATE_STRING_IF_INVALID
|
current = settings.TEMPLATE_STRING_IF_INVALID
|
||||||
@ -695,25 +705,6 @@ class Variable(object):
|
|||||||
current = settings.TEMPLATE_STRING_IF_INVALID
|
current = settings.TEMPLATE_STRING_IF_INVALID
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
except (TypeError, AttributeError):
|
|
||||||
try: # list-index lookup
|
|
||||||
current = current[int(bit)]
|
|
||||||
except (IndexError, # list index out of range
|
|
||||||
ValueError, # invalid literal for int()
|
|
||||||
KeyError, # current is a dict without `int(bit)` key
|
|
||||||
TypeError, # unsubscriptable object
|
|
||||||
):
|
|
||||||
raise VariableDoesNotExist("Failed lookup for key [%s] in %r", (bit, current)) # missing attribute
|
|
||||||
except Exception, e:
|
|
||||||
if getattr(e, 'silent_variable_failure', False):
|
|
||||||
current = settings.TEMPLATE_STRING_IF_INVALID
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
except Exception, e:
|
|
||||||
if getattr(e, 'silent_variable_failure', False):
|
|
||||||
current = settings.TEMPLATE_STRING_IF_INVALID
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
|
|
||||||
return current
|
return current
|
||||||
|
|
||||||
|
@ -91,6 +91,21 @@ class SomeClass:
|
|||||||
def method4(self):
|
def method4(self):
|
||||||
raise SomeOtherException
|
raise SomeOtherException
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
if key == 'silent_fail_key':
|
||||||
|
raise SomeException
|
||||||
|
elif key == 'noisy_fail_key':
|
||||||
|
raise SomeOtherException
|
||||||
|
raise KeyError
|
||||||
|
|
||||||
|
def silent_fail_attribute(self):
|
||||||
|
raise SomeException
|
||||||
|
silent_fail_attribute = property(silent_fail_attribute)
|
||||||
|
|
||||||
|
def noisy_fail_attribute(self):
|
||||||
|
raise SomeOtherException
|
||||||
|
noisy_fail_attribute = property(noisy_fail_attribute)
|
||||||
|
|
||||||
class OtherClass:
|
class OtherClass:
|
||||||
def method(self):
|
def method(self):
|
||||||
return "OtherClass.method"
|
return "OtherClass.method"
|
||||||
@ -529,6 +544,12 @@ class Templates(unittest.TestCase):
|
|||||||
'basic-syntax35': ("{{ 1 }}", {"1": "abc"}, "1"),
|
'basic-syntax35': ("{{ 1 }}", {"1": "abc"}, "1"),
|
||||||
'basic-syntax36': ("{{ 1.2 }}", {"1": "abc"}, "1.2"),
|
'basic-syntax36': ("{{ 1.2 }}", {"1": "abc"}, "1.2"),
|
||||||
|
|
||||||
|
# Call methods in the top level of the context
|
||||||
|
'basic-syntax37': ('{{ callable }}', {"callable": lambda: "foo bar"}, "foo bar"),
|
||||||
|
|
||||||
|
# Call methods returned from dictionary lookups
|
||||||
|
'basic-syntax38': ('{{ var.callable }}', {"var": {"callable": lambda: "foo bar"}}, "foo bar"),
|
||||||
|
|
||||||
# List-index syntax allows a template to access a certain item of a subscriptable object.
|
# List-index syntax allows a template to access a certain item of a subscriptable object.
|
||||||
'list-index01': ("{{ var.1 }}", {"var": ["first item", "second item"]}, "second item"),
|
'list-index01': ("{{ var.1 }}", {"var": ["first item", "second item"]}, "second item"),
|
||||||
|
|
||||||
@ -616,6 +637,17 @@ class Templates(unittest.TestCase):
|
|||||||
#filters should accept empty string constants
|
#filters should accept empty string constants
|
||||||
'filter-syntax20': ('{{ ""|default_if_none:"was none" }}', {}, ""),
|
'filter-syntax20': ('{{ ""|default_if_none:"was none" }}', {}, ""),
|
||||||
|
|
||||||
|
# Fail silently for non-callable attribute and dict lookups which
|
||||||
|
# raise an exception with a "silent_variable_failure" attribute
|
||||||
|
'filter-syntax21': (r'1{{ var.silent_fail_key }}2', {"var": SomeClass()}, ("12", "1INVALID2")),
|
||||||
|
'filter-syntax22': (r'1{{ var.silent_fail_attribute }}2', {"var": SomeClass()}, ("12", "1INVALID2")),
|
||||||
|
|
||||||
|
# In attribute and dict lookups that raise an unexpected exception
|
||||||
|
# without a "silent_variable_attribute" set to True, the exception
|
||||||
|
# propagates
|
||||||
|
'filter-syntax23': (r'1{{ var.noisy_fail_key }}2', {"var": SomeClass()}, SomeOtherException),
|
||||||
|
'filter-syntax24': (r'1{{ var.noisy_fail_attribute }}2', {"var": SomeClass()}, SomeOtherException),
|
||||||
|
|
||||||
### COMMENT SYNTAX ########################################################
|
### COMMENT SYNTAX ########################################################
|
||||||
'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),
|
'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),
|
||||||
'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"),
|
'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"),
|
||||||
|
Loading…
Reference in New Issue
Block a user