Skip to content

Commit 92e29db

Browse files
committed
Improve --fail-on-template-vars: use origin if available
This will be there with Django 1.9+ always, and in case of `settings.TEMPLATE_DEBUG` before. It stops going up to the Template, but uses the nearest location (which is required when extending templates). Using `django.template.base.Origin` also gives the benefit of having the full/absolute path.
1 parent d4f42ea commit 92e29db

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

pytest_django/plugin.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -483,10 +483,24 @@ def __contains__(self, key):
483483
"""There is a test for '%s' in TEMPLATE_STRING_IF_INVALID."""
484484
return key == '%s'
485485

486-
def _get_template(self):
486+
def _get_origin(self):
487+
stack = inspect.stack()
488+
489+
# Try to use topmost `self.origin` first (Django 1.9+, and with
490+
# TEMPLATE_DEBUG)..
491+
for f in stack[2:]:
492+
func = f[3]
493+
if func == 'render':
494+
frame = f[0]
495+
try:
496+
origin = frame.f_locals['self'].origin
497+
except (AttributeError, KeyError):
498+
continue
499+
if origin is not None:
500+
return origin
501+
487502
from django.template import Template
488503

489-
stack = inspect.stack()
490504
# finding the ``render`` needle in the stack
491505
frame = reduce(
492506
lambda x, y: y[3] == 'render' and 'base.py' in y[1] and y or x,
@@ -502,14 +516,14 @@ def _get_template(self):
502516
# ``django.template.base.Template``
503517
template = f_locals['self']
504518
if isinstance(template, Template):
505-
return template
519+
return template.name
506520

507521
def __mod__(self, var):
508522
"""Handle TEMPLATE_STRING_IF_INVALID % var."""
509-
template = self._get_template()
510-
if template:
523+
origin = self._get_origin()
524+
if origin:
511525
msg = "Undefined template variable '%s' in '%s'" % (
512-
var, template.name)
526+
var, origin)
513527
else:
514528
msg = "Undefined template variable '%s'" % var
515529
if self.fail:

tests/test_environment.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ def invalid_template(request):
7373
""", 'views.py')
7474
django_testdir.create_app_file(
7575
"<div>{{ invalid_var }}</div>",
76+
'templates/invalid_template_base.html'
77+
)
78+
django_testdir.create_app_file(
79+
"{% extends 'invalid_template_base.html' %}",
7680
'templates/invalid_template.html'
7781
)
7882
django_testdir.create_test_module('''
@@ -86,9 +90,14 @@ def test_ignore(client):
8690
client.get('/invalid_template/')
8791
''')
8892
result = django_testdir.runpytest_subprocess('-s', '--fail-on-template-vars')
93+
94+
if get_django_version() >= (1, 9):
95+
origin = "'*/tpkg/app/templates/invalid_template_base.html'"
96+
else:
97+
origin = "'invalid_template.html'"
8998
result.stdout.fnmatch_lines_random([
9099
"tpkg/test_the_test.py F.",
91-
"Undefined template variable 'invalid_var' in 'invalid_template.html'",
100+
"Undefined template variable 'invalid_var' in {}".format(origin)
92101
])
93102

94103

0 commit comments

Comments
 (0)