Skip to content

Instantly share code, notes, and snippets.

@laundmo
Last active November 28, 2020 05:15
Show Gist options
  • Save laundmo/acb9e26345c1454dd6029391e895f844 to your computer and use it in GitHub Desktop.
Save laundmo/acb9e26345c1454dd6029391e895f844 to your computer and use it in GitHub Desktop.
Jinja 2 will sometimes hide exceptions thrown in properties behind "Class has no attribute property_name" due to the way the jinja2.Undefined works. This is a way to forcibly throw the underlying exceptions.
class JinjaPropertyErrorReporting():
def __getattribute__(self, name):
if isinstance(getattr(type(self), name, None), property): # TODO: could be done using hasattr?
try:
return super().__getattribute__(name)
except Exception as e:
raise Exception(f"Jinja would have accidentally hidden this error: {type(e).__name__}: {str(e)}") from e
else:
return super().__getattribute__(name)
#########################
# EXAMPLE CODE
from jinja2 import Environment
from jinja2.runtime import StrictUndefined
# Class without mixin to show bad jinja2 behaviour
class MyClass():
@property
def faulty_property(self):
return self.doesntexist
# Class with mixin to show the workaround works.
class MyClassWithMixin(JinjaPropertyErrorReporting):
@property
def faulty_property(self):
return self.doesntexist
# otherwise it will ignore any errors, the Mixin still works with the base Undefined.
env = Environment(undefined=StrictUndefined)
t = env.from_string("{{ obj.faulty_property }}")
# instances
without = MyClass()
with_ = MyClassWithMixin()
# printing just the error message
try:
print(t.render(obj=without))
except Exception as e:
print(e)
try:
print(t.render(obj=with_))
except Exception as e:
print(e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment