diff options
author | David Lord <davidism@gmail.com> | 2020-03-27 10:05:12 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-27 10:05:12 -0700 |
commit | 41ed50c805ac04252cdc094db216977d70e7c0da (patch) | |
tree | e907b26980341a927e2ba1233ea68d0a00eb2205 | |
parent | e1b5e50ca33f4b10d033c96de007d18b510ecab9 (diff) | |
parent | f15452f130b82090ca1e1f650b5b7662496633db (diff) | |
download | jinja-41ed50c805ac04252cdc094db216977d70e7c0da.tar.gz |
Merge pull request #1179 from pallets/undefined-recursion
AttributeError in undefined message doesn't cause RuntimeError
-rw-r--r-- | CHANGES.rst | 3 | ||||
-rw-r--r-- | src/jinja2/utils.py | 10 | ||||
-rw-r--r-- | tests/test_api.py | 15 |
3 files changed, 25 insertions, 3 deletions
diff --git a/CHANGES.rst b/CHANGES.rst index aee6ad3a..0902830b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,6 +12,9 @@ Unreleased by wrapping the input in :func:`soft_unicode`. :pr:`1160` - Fix a hang when displaying tracebacks on Python 32-bit. :issue:`1162` +- Showing an undefined error for an object that raises + ``AttributeError`` on access doesn't cause a recursion error. + :issue:`1177` Version 2.11.1 diff --git a/src/jinja2/utils.py b/src/jinja2/utils.py index e3285e8e..94581ca8 100644 --- a/src/jinja2/utils.py +++ b/src/jinja2/utils.py @@ -165,11 +165,15 @@ def object_type_repr(obj): return "None" elif obj is Ellipsis: return "Ellipsis" + + cls = type(obj) + # __builtin__ in 2.x, builtins in 3.x - if obj.__class__.__module__ in ("__builtin__", "builtins"): - name = obj.__class__.__name__ + if cls.__module__ in ("__builtin__", "builtins"): + name = cls.__name__ else: - name = obj.__class__.__module__ + "." + obj.__class__.__name__ + name = cls.__module__ + "." + cls.__name__ + return "%s object" % name diff --git a/tests/test_api.py b/tests/test_api.py index 058ec56c..7a1cae86 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -269,6 +269,21 @@ class TestUndefined(object): with pytest.raises(AttributeError): Undefined("Foo").__dict__ + def test_undefined_attribute_error(self): + # Django's LazyObject turns the __class__ attribute into a + # property that resolves the wrapped function. If that wrapped + # function raises an AttributeError, printing the repr of the + # object in the undefined message would cause a RecursionError. + class Error(object): + @property + def __class__(self): + raise AttributeError() + + u = Undefined(obj=Error(), name="hello") + + with pytest.raises(UndefinedError): + getattr(u, "recursion", None) + def test_logging_undefined(self): _messages = [] |