You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Infinite recursion when using with Django SimpleLazyObject #1177
Hi,
I use an object of type django.utils.functional.SimpleLazyObject as a template variable.
When an AttributeError happens in the inner of a lazy object the template rendering falls into infinite recursion.
Expected Behavior
A traceback about the attribute error is displayed.
Traceback (most recent call last):
File "main.py", line 10, in <module>
template.render(obj=SimpleLazyObject(lambda: raises_attribute_error()))
File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/jinja2/environment.py", line 1090, in renderself.environment.handle_exception()
File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/jinja2/environment.py", line 832, in handle_exception
reraise(*rewrite_traceback_stack(source=source))
File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/jinja2/_compat.py", line 28, in reraiseraise value.with_traceback(tb)
File "<template>", line 1, in top-level template code
File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/jinja2/environment.py", line 471, in getattrreturngetattr(obj, attribute)
File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/jinja2/runtime.py", line 738, in _undefined_message
object_type_repr(self._undefined_obj),
File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/jinja2/utils.py", line 169, in object_type_reprif obj.__class__.__module__in ("__builtin__", "builtins"):
File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/django/utils/functional.py", line 224, in innerself._setup()
File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/django/utils/functional.py", line 360, in _setupself._wrapped =self._setupfunc()
File "main.py", line 10, in <lambda>
template.render(obj=SimpleLazyObject(lambda: raises_attribute_error()))
File "main.py", line 6, in raises_attribute_errorraiseAttributeError()
RecursionError: maximum recursion depth exceeded while calling a Python object
This is due to the way that Jinja variable lookup and undefined handling works. First it tries to get the attribute hello, which raises an attribute error. Then it tries to treat the variable as a dict key, which also raises an attribute error, so it returns an undefined object. Then it tries to look up the attrribute recursion on the undefined object, which raises an undefined error, which tries to print out some information about the object (obj.__class__.__name__), which raises an attribute error again.
In this case, it's possible to fix this by changing the undefined code to use type(obj) instead.
In general, the code you've shown indicates a bad design. Avoid code that could potentially raise an AttributeError in every situation it's used, as that's a recipe for disaster, especially when looking up attributes.
Activity
davidism commentedon Mar 27, 2020
This is due to the way that Jinja variable lookup and undefined handling works. First it tries to get the attribute
hello, which raises an attribute error. Then it tries to treat the variable as a dict key, which also raises an attribute error, so it returns an undefined object. Then it tries to look up the attrributerecursionon the undefined object, which raises an undefined error, which tries to print out some information about the object (obj.__class__.__name__), which raises an attribute error again.In this case, it's possible to fix this by changing the undefined code to use
type(obj)instead.In general, the code you've shown indicates a bad design. Avoid code that could potentially raise an
AttributeErrorin every situation it's used, as that's a recipe for disaster, especially when looking up attributes.rkashapov commentedon Mar 27, 2020
Thanks