Skip to content

Infinite recursion when using with Django SimpleLazyObject #1177

Closed

Description

@rkashapov

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.

Actual Behavior

Template rendering falls into infinite recursion.

Minimal Code To Reproduce

from django.utils.functional import SimpleLazyObject
import jinja2

def raises_attribute_error():
      raise AttributeError()

template = jinja2.Template('{{ obj.hello.recursion }}')
template.render(obj=SimpleLazyObject(lambda: raises_attribute_error()))

Full Traceback

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 render
    self.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 reraise
    raise 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 getattr
    return getattr(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_repr
    if obj.__class__.__module__ in ("__builtin__", "builtins"):
  File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/django/utils/functional.py", line 224, in inner
    self._setup()
  File "/Users/rkashapov/Library/Python/3.7/lib/python/site-packages/django/utils/functional.py", line 360, in _setup
    self._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_error
    raise AttributeError()
RecursionError: maximum recursion depth exceeded while calling a Python object

Your Environment

  • Python version: 3.7.3
  • Jinja version: 2.11.1

Activity

  1. davidism commented on Mar 27, 2020

    @davidism
    Member

    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.

  2. added this to the 2.11.2 milestone on Mar 27, 2020
  3. rkashapov commented on Mar 27, 2020

    @rkashapov
    Author

    Thanks

  4. locked as resolved and limited conversation to collaborators on Nov 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions