Skip to content

Commit 3485599

Browse files
FarhanAliRazajacobtylerwalls
authored andcommitted
Refs #36559 -- Ran template partial source tests in debug mode only.
Added a warning for accessing PartialTemplate.source when debugging is disabled. Thanks Sarah Boyce for the idea.
1 parent f0c05a4 commit 3485599

3 files changed

Lines changed: 153 additions & 65 deletions

File tree

django/template/base.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import inspect
5454
import logging
5555
import re
56+
import warnings
5657
from enum import Enum
5758

5859
from django.template.context import BaseContext
@@ -329,6 +330,13 @@ def find_partial_source(self, full_source, partial_name):
329330
@property
330331
def source(self):
331332
template = self.origin.loader.get_template(self.origin.template_name)
333+
if not template.engine.debug:
334+
warnings.warn(
335+
"PartialTemplate.source is only available when template "
336+
"debugging is enabled.",
337+
RuntimeWarning,
338+
stacklevel=2,
339+
)
332340
return self.find_partial_source(template.source, self.name)
333341

334342
def _render(self, context):

tests/template_tests/test_partials.py

Lines changed: 141 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
from django.http import HttpResponse
55
from django.template import (
66
Context,
7+
NodeList,
78
Origin,
9+
PartialTemplate,
810
Template,
911
TemplateDoesNotExist,
1012
TemplateSyntaxError,
@@ -15,6 +17,8 @@
1517
from django.test import TestCase, override_settings
1618
from django.urls import path, reverse
1719

20+
from .utils import setup
21+
1822
engine = engines["django"]
1923

2024

@@ -30,18 +34,30 @@ def test_invalid_template_name_raises_template_does_not_exist(self):
3034

3135
def test_template_source_is_correct(self):
3236
partial = engine.get_template("partial_examples.html#test-partial")
33-
self.assertEqual(
34-
partial.template.source,
35-
"{% partialdef test-partial %}\nTEST-PARTIAL-CONTENT\n{% endpartialdef %}",
37+
msg = (
38+
"PartialTemplate.source is only available when "
39+
"template debugging is enabled."
3640
)
41+
with self.assertRaisesMessage(RuntimeWarning, msg):
42+
self.assertEqual(
43+
partial.template.source,
44+
"{% partialdef test-partial %}\n"
45+
"TEST-PARTIAL-CONTENT\n"
46+
"{% endpartialdef %}",
47+
)
3748

3849
def test_template_source_inline_is_correct(self):
3950
partial = engine.get_template("partial_examples.html#inline-partial")
40-
self.assertEqual(
41-
partial.template.source,
42-
"{% partialdef inline-partial inline %}\nINLINE-CONTENT\n"
43-
"{% endpartialdef %}",
51+
msg = (
52+
"PartialTemplate.source is only available when "
53+
"template debugging is enabled."
4454
)
55+
with self.assertRaisesMessage(RuntimeWarning, msg):
56+
self.assertEqual(
57+
partial.template.source,
58+
"{% partialdef inline-partial inline %}\nINLINE-CONTENT\n"
59+
"{% endpartialdef %}",
60+
)
4561

4662
def test_full_template_from_loader(self):
4763
template = engine.get_template("partial_examples.html")
@@ -149,6 +165,20 @@ def test_partial_engine_assignment_with_real_template(self):
149165
rendered_content = template_with_partial.render({})
150166
self.assertEqual("TEST-PARTIAL-CONTENT", rendered_content.strip())
151167

168+
def test_template_source_warning(self):
169+
partial = engine.get_template("partial_examples.html#test-partial")
170+
with self.assertWarnsMessage(
171+
RuntimeWarning,
172+
"PartialTemplate.source is only available when template "
173+
"debugging is enabled.",
174+
):
175+
self.assertEqual(
176+
partial.template.source,
177+
"{% partialdef test-partial %}\n"
178+
"TEST-PARTIAL-CONTENT\n"
179+
"{% endpartialdef %}",
180+
)
181+
152182

153183
class RobustPartialHandlingTests(TestCase):
154184

@@ -219,56 +249,76 @@ def test_nested_partials_rendering_with_context(self):
219249

220250
class FindPartialSourceTests(TestCase):
221251

252+
@setup(
253+
{
254+
"partial_source_success_template": (
255+
"{% partialdef test-partial %}\n"
256+
"TEST-PARTIAL-CONTENT\n"
257+
"{% endpartialdef %}\n"
258+
),
259+
},
260+
debug_only=True,
261+
)
222262
def test_find_partial_source_success(self):
223-
template = engine.get_template("partial_examples.html").template
263+
template = self.engine.get_template("partial_source_success_template")
224264
partial_proxy = template.extra_data["partials"]["test-partial"]
225265

226266
expected = """{% partialdef test-partial %}
227267
TEST-PARTIAL-CONTENT
228268
{% endpartialdef %}"""
229269
self.assertEqual(partial_proxy.source.strip(), expected.strip())
230270

271+
@setup(
272+
{
273+
"partial_source_with_inline_template": (
274+
"{% partialdef inline-partial inline %}\n"
275+
"INLINE-CONTENT\n"
276+
"{% endpartialdef %}\n"
277+
),
278+
},
279+
debug_only=True,
280+
)
231281
def test_find_partial_source_with_inline(self):
232-
template = engine.get_template("partial_examples.html").template
282+
template = self.engine.get_template("partial_source_with_inline_template")
233283
partial_proxy = template.extra_data["partials"]["inline-partial"]
234284

235285
expected = """{% partialdef inline-partial inline %}
236286
INLINE-CONTENT
237287
{% endpartialdef %}"""
238288
self.assertEqual(partial_proxy.source.strip(), expected.strip())
239289

240-
def test_find_partial_source_nonexistent_partial(self):
241-
template = engine.get_template("partial_examples.html").template
242-
partial_proxy = template.extra_data["partials"]["test-partial"]
243-
244-
result = partial_proxy.find_partial_source(
245-
template.source, "nonexistent-partial"
246-
)
247-
self.assertEqual(result, "")
248-
290+
@setup(
291+
{
292+
"empty_partial_template": ("{% partialdef empty %}{% endpartialdef %}"),
293+
},
294+
debug_only=True,
295+
)
249296
def test_find_partial_source_empty_partial(self):
250-
template_source = "{% partialdef empty %}{% endpartialdef %}"
251-
template = Template(template_source)
297+
template = self.engine.get_template("empty_partial_template")
252298
partial_proxy = template.extra_data["partials"]["empty"]
253299

254-
result = partial_proxy.find_partial_source(template_source, "empty")
300+
result = partial_proxy.find_partial_source(template.source, "empty")
255301
self.assertEqual(result, "{% partialdef empty %}{% endpartialdef %}")
256302

303+
@setup(
304+
{
305+
"consecutive_partials_template": (
306+
"{% partialdef empty %}{% endpartialdef %}"
307+
"{% partialdef other %}...{% endpartialdef %}"
308+
),
309+
},
310+
debug_only=True,
311+
)
257312
def test_find_partial_source_multiple_consecutive_partials(self):
258-
259-
template_source = (
260-
"{% partialdef empty %}{% endpartialdef %}"
261-
"{% partialdef other %}...{% endpartialdef %}"
262-
)
263-
template = Template(template_source)
313+
template = self.engine.get_template("consecutive_partials_template")
264314

265315
empty_proxy = template.extra_data["partials"]["empty"]
266316
other_proxy = template.extra_data["partials"]["other"]
267317

268-
empty_result = empty_proxy.find_partial_source(template_source, "empty")
318+
empty_result = empty_proxy.find_partial_source(template.source, "empty")
269319
self.assertEqual(empty_result, "{% partialdef empty %}{% endpartialdef %}")
270320

271-
other_result = other_proxy.find_partial_source(template_source, "other")
321+
other_result = other_proxy.find_partial_source(template.source, "other")
272322
self.assertEqual(other_result, "{% partialdef other %}...{% endpartialdef %}")
273323

274324
def test_partials_with_duplicate_names(self):
@@ -306,28 +356,40 @@ def test_partials_with_duplicate_names(self):
306356
):
307357
Template(template_source, origin=Origin(name="template.html"))
308358

359+
@setup(
360+
{
361+
"named_end_tag_template": (
362+
"{% partialdef thing %}CONTENT{% endpartialdef thing %}"
363+
),
364+
},
365+
debug_only=True,
366+
)
309367
def test_find_partial_source_supports_named_end_tag(self):
310-
template_source = "{% partialdef thing %}CONTENT{% endpartialdef thing %}"
311-
template = Template(template_source)
368+
template = self.engine.get_template("named_end_tag_template")
312369
partial_proxy = template.extra_data["partials"]["thing"]
313370

314-
result = partial_proxy.find_partial_source(template_source, "thing")
371+
result = partial_proxy.find_partial_source(template.source, "thing")
315372
self.assertEqual(
316373
result, "{% partialdef thing %}CONTENT{% endpartialdef thing %}"
317374
)
318375

376+
@setup(
377+
{
378+
"nested_partials_basic_template": (
379+
"{% partialdef outer %}"
380+
"{% partialdef inner %}...{% endpartialdef %}"
381+
"{% endpartialdef %}"
382+
),
383+
},
384+
debug_only=True,
385+
)
319386
def test_find_partial_source_supports_nested_partials(self):
320-
template_source = (
321-
"{% partialdef outer %}"
322-
"{% partialdef inner %}...{% endpartialdef %}"
323-
"{% endpartialdef %}"
324-
)
325-
template = Template(template_source)
387+
template = self.engine.get_template("nested_partials_basic_template")
326388

327389
empty_proxy = template.extra_data["partials"]["outer"]
328390
other_proxy = template.extra_data["partials"]["inner"]
329391

330-
outer_result = empty_proxy.find_partial_source(template_source, "outer")
392+
outer_result = empty_proxy.find_partial_source(template.source, "outer")
331393
self.assertEqual(
332394
outer_result,
333395
(
@@ -336,21 +398,26 @@ def test_find_partial_source_supports_nested_partials(self):
336398
),
337399
)
338400

339-
inner_result = other_proxy.find_partial_source(template_source, "inner")
401+
inner_result = other_proxy.find_partial_source(template.source, "inner")
340402
self.assertEqual(inner_result, "{% partialdef inner %}...{% endpartialdef %}")
341403

404+
@setup(
405+
{
406+
"nested_partials_named_end_template": (
407+
"{% partialdef outer %}"
408+
"{% partialdef inner %}...{% endpartialdef inner %}"
409+
"{% endpartialdef outer %}"
410+
),
411+
},
412+
debug_only=True,
413+
)
342414
def test_find_partial_source_supports_nested_partials_and_named_end_tags(self):
343-
template_source = (
344-
"{% partialdef outer %}"
345-
"{% partialdef inner %}...{% endpartialdef inner %}"
346-
"{% endpartialdef outer %}"
347-
)
348-
template = Template(template_source)
415+
template = self.engine.get_template("nested_partials_named_end_template")
349416

350417
empty_proxy = template.extra_data["partials"]["outer"]
351418
other_proxy = template.extra_data["partials"]["inner"]
352419

353-
outer_result = empty_proxy.find_partial_source(template_source, "outer")
420+
outer_result = empty_proxy.find_partial_source(template.source, "outer")
354421
self.assertEqual(
355422
outer_result,
356423
(
@@ -359,23 +426,28 @@ def test_find_partial_source_supports_nested_partials_and_named_end_tags(self):
359426
),
360427
)
361428

362-
inner_result = other_proxy.find_partial_source(template_source, "inner")
429+
inner_result = other_proxy.find_partial_source(template.source, "inner")
363430
self.assertEqual(
364431
inner_result, "{% partialdef inner %}...{% endpartialdef inner %}"
365432
)
366433

434+
@setup(
435+
{
436+
"nested_partials_mixed_end_1_template": (
437+
"{% partialdef outer %}"
438+
"{% partialdef inner %}...{% endpartialdef %}"
439+
"{% endpartialdef outer %}"
440+
),
441+
},
442+
debug_only=True,
443+
)
367444
def test_find_partial_source_supports_nested_partials_and_mixed_end_tags_1(self):
368-
template_source = (
369-
"{% partialdef outer %}"
370-
"{% partialdef inner %}...{% endpartialdef %}"
371-
"{% endpartialdef outer %}"
372-
)
373-
template = Template(template_source)
445+
template = self.engine.get_template("nested_partials_mixed_end_1_template")
374446

375447
empty_proxy = template.extra_data["partials"]["outer"]
376448
other_proxy = template.extra_data["partials"]["inner"]
377449

378-
outer_result = empty_proxy.find_partial_source(template_source, "outer")
450+
outer_result = empty_proxy.find_partial_source(template.source, "outer")
379451
self.assertEqual(
380452
outer_result,
381453
(
@@ -384,21 +456,26 @@ def test_find_partial_source_supports_nested_partials_and_mixed_end_tags_1(self)
384456
),
385457
)
386458

387-
inner_result = other_proxy.find_partial_source(template_source, "inner")
459+
inner_result = other_proxy.find_partial_source(template.source, "inner")
388460
self.assertEqual(inner_result, "{% partialdef inner %}...{% endpartialdef %}")
389461

462+
@setup(
463+
{
464+
"nested_partials_mixed_end_2_template": (
465+
"{% partialdef outer %}"
466+
"{% partialdef inner %}...{% endpartialdef inner %}"
467+
"{% endpartialdef %}"
468+
),
469+
},
470+
debug_only=True,
471+
)
390472
def test_find_partial_source_supports_nested_partials_and_mixed_end_tags_2(self):
391-
template_source = (
392-
"{% partialdef outer %}"
393-
"{% partialdef inner %}...{% endpartialdef inner %}"
394-
"{% endpartialdef %}"
395-
)
396-
template = Template(template_source)
473+
template = self.engine.get_template("nested_partials_mixed_end_2_template")
397474

398475
empty_proxy = template.extra_data["partials"]["outer"]
399476
other_proxy = template.extra_data["partials"]["inner"]
400477

401-
outer_result = empty_proxy.find_partial_source(template_source, "outer")
478+
outer_result = empty_proxy.find_partial_source(template.source, "outer")
402479
self.assertEqual(
403480
outer_result,
404481
(
@@ -407,7 +484,7 @@ def test_find_partial_source_supports_nested_partials_and_mixed_end_tags_2(self)
407484
),
408485
)
409486

410-
inner_result = other_proxy.find_partial_source(template_source, "inner")
487+
inner_result = other_proxy.find_partial_source(template.source, "inner")
411488
self.assertEqual(
412489
inner_result, "{% partialdef inner %}...{% endpartialdef inner %}"
413490
)

tests/template_tests/utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
TEMPLATE_DIR = os.path.join(ROOT, "templates")
1010

1111

12-
def setup(templates, *args, test_once=False):
12+
def setup(templates, *args, test_once=False, debug_only=False):
1313
"""
1414
Runs test method multiple times in the following order:
1515
@@ -54,11 +54,14 @@ def inner(self):
5454
self.engine = Engine(
5555
libraries=libraries,
5656
loaders=loaders,
57+
debug=debug_only,
5758
)
5859
func(self)
5960
if test_once:
6061
return
6162
func(self)
63+
if debug_only:
64+
return
6265

6366
self.engine = Engine(
6467
libraries=libraries,

0 commit comments

Comments
 (0)