summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfarhan <farhanalirazaazeemi@gmail.com>2025-09-02 14:59:30 -0400
committerJacob Walls <jacobtylerwalls@gmail.com>2025-09-03 10:59:58 -0400
commit3485599ef08811e2fd066458aa083b2567f3cb84 (patch)
treec3e092941d0fc14e88a5f540f1314ea3633f3602
parentf0c05a40d27d69ef3a7b4e5e0199b5dba5b11feb (diff)
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.
-rw-r--r--django/template/base.py8
-rw-r--r--tests/template_tests/test_partials.py205
-rw-r--r--tests/template_tests/utils.py5
3 files changed, 153 insertions, 65 deletions
diff --git a/django/template/base.py b/django/template/base.py
index 74b3987410..d7bc59d668 100644
--- a/django/template/base.py
+++ b/django/template/base.py
@@ -53,6 +53,7 @@ times with multiple contexts)
import inspect
import logging
import re
+import warnings
from enum import Enum
from django.template.context import BaseContext
@@ -329,6 +330,13 @@ class PartialTemplate:
@property
def source(self):
template = self.origin.loader.get_template(self.origin.template_name)
+ if not template.engine.debug:
+ warnings.warn(
+ "PartialTemplate.source is only available when template "
+ "debugging is enabled.",
+ RuntimeWarning,
+ stacklevel=2,
+ )
return self.find_partial_source(template.source, self.name)
def _render(self, context):
diff --git a/tests/template_tests/test_partials.py b/tests/template_tests/test_partials.py
index 8f1a74b2ec..cc3ef7fb25 100644
--- a/tests/template_tests/test_partials.py
+++ b/tests/template_tests/test_partials.py
@@ -4,7 +4,9 @@ from unittest import mock
from django.http import HttpResponse
from django.template import (
Context,
+ NodeList,
Origin,
+ PartialTemplate,
Template,
TemplateDoesNotExist,
TemplateSyntaxError,
@@ -15,6 +17,8 @@ from django.template.loader import render_to_string
from django.test import TestCase, override_settings
from django.urls import path, reverse
+from .utils import setup
+
engine = engines["django"]
@@ -30,18 +34,30 @@ class PartialTagsTests(TestCase):
def test_template_source_is_correct(self):
partial = engine.get_template("partial_examples.html#test-partial")
- self.assertEqual(
- partial.template.source,
- "{% partialdef test-partial %}\nTEST-PARTIAL-CONTENT\n{% endpartialdef %}",
+ msg = (
+ "PartialTemplate.source is only available when "
+ "template debugging is enabled."
)
+ with self.assertRaisesMessage(RuntimeWarning, msg):
+ self.assertEqual(
+ partial.template.source,
+ "{% partialdef test-partial %}\n"
+ "TEST-PARTIAL-CONTENT\n"
+ "{% endpartialdef %}",
+ )
def test_template_source_inline_is_correct(self):
partial = engine.get_template("partial_examples.html#inline-partial")
- self.assertEqual(
- partial.template.source,
- "{% partialdef inline-partial inline %}\nINLINE-CONTENT\n"
- "{% endpartialdef %}",
+ msg = (
+ "PartialTemplate.source is only available when "
+ "template debugging is enabled."
)
+ with self.assertRaisesMessage(RuntimeWarning, msg):
+ self.assertEqual(
+ partial.template.source,
+ "{% partialdef inline-partial inline %}\nINLINE-CONTENT\n"
+ "{% endpartialdef %}",
+ )
def test_full_template_from_loader(self):
template = engine.get_template("partial_examples.html")
@@ -149,6 +165,20 @@ class PartialTagsTests(TestCase):
rendered_content = template_with_partial.render({})
self.assertEqual("TEST-PARTIAL-CONTENT", rendered_content.strip())
+ def test_template_source_warning(self):
+ partial = engine.get_template("partial_examples.html#test-partial")
+ with self.assertWarnsMessage(
+ RuntimeWarning,
+ "PartialTemplate.source is only available when template "
+ "debugging is enabled.",
+ ):
+ self.assertEqual(
+ partial.template.source,
+ "{% partialdef test-partial %}\n"
+ "TEST-PARTIAL-CONTENT\n"
+ "{% endpartialdef %}",
+ )
+
class RobustPartialHandlingTests(TestCase):
@@ -219,8 +249,18 @@ class RobustPartialHandlingTests(TestCase):
class FindPartialSourceTests(TestCase):
+ @setup(
+ {
+ "partial_source_success_template": (
+ "{% partialdef test-partial %}\n"
+ "TEST-PARTIAL-CONTENT\n"
+ "{% endpartialdef %}\n"
+ ),
+ },
+ debug_only=True,
+ )
def test_find_partial_source_success(self):
- template = engine.get_template("partial_examples.html").template
+ template = self.engine.get_template("partial_source_success_template")
partial_proxy = template.extra_data["partials"]["test-partial"]
expected = """{% partialdef test-partial %}
@@ -228,8 +268,18 @@ TEST-PARTIAL-CONTENT
{% endpartialdef %}"""
self.assertEqual(partial_proxy.source.strip(), expected.strip())
+ @setup(
+ {
+ "partial_source_with_inline_template": (
+ "{% partialdef inline-partial inline %}\n"
+ "INLINE-CONTENT\n"
+ "{% endpartialdef %}\n"
+ ),
+ },
+ debug_only=True,
+ )
def test_find_partial_source_with_inline(self):
- template = engine.get_template("partial_examples.html").template
+ template = self.engine.get_template("partial_source_with_inline_template")
partial_proxy = template.extra_data["partials"]["inline-partial"]
expected = """{% partialdef inline-partial inline %}
@@ -237,38 +287,38 @@ INLINE-CONTENT
{% endpartialdef %}"""
self.assertEqual(partial_proxy.source.strip(), expected.strip())
- def test_find_partial_source_nonexistent_partial(self):
- template = engine.get_template("partial_examples.html").template
- partial_proxy = template.extra_data["partials"]["test-partial"]
-
- result = partial_proxy.find_partial_source(
- template.source, "nonexistent-partial"
- )
- self.assertEqual(result, "")
-
+ @setup(
+ {
+ "empty_partial_template": ("{% partialdef empty %}{% endpartialdef %}"),
+ },
+ debug_only=True,
+ )
def test_find_partial_source_empty_partial(self):
- template_source = "{% partialdef empty %}{% endpartialdef %}"
- template = Template(template_source)
+ template = self.engine.get_template("empty_partial_template")
partial_proxy = template.extra_data["partials"]["empty"]
- result = partial_proxy.find_partial_source(template_source, "empty")
+ result = partial_proxy.find_partial_source(template.source, "empty")
self.assertEqual(result, "{% partialdef empty %}{% endpartialdef %}")
+ @setup(
+ {
+ "consecutive_partials_template": (
+ "{% partialdef empty %}{% endpartialdef %}"
+ "{% partialdef other %}...{% endpartialdef %}"
+ ),
+ },
+ debug_only=True,
+ )
def test_find_partial_source_multiple_consecutive_partials(self):
-
- template_source = (
- "{% partialdef empty %}{% endpartialdef %}"
- "{% partialdef other %}...{% endpartialdef %}"
- )
- template = Template(template_source)
+ template = self.engine.get_template("consecutive_partials_template")
empty_proxy = template.extra_data["partials"]["empty"]
other_proxy = template.extra_data["partials"]["other"]
- empty_result = empty_proxy.find_partial_source(template_source, "empty")
+ empty_result = empty_proxy.find_partial_source(template.source, "empty")
self.assertEqual(empty_result, "{% partialdef empty %}{% endpartialdef %}")
- other_result = other_proxy.find_partial_source(template_source, "other")
+ other_result = other_proxy.find_partial_source(template.source, "other")
self.assertEqual(other_result, "{% partialdef other %}...{% endpartialdef %}")
def test_partials_with_duplicate_names(self):
@@ -306,28 +356,40 @@ INLINE-CONTENT
):
Template(template_source, origin=Origin(name="template.html"))
+ @setup(
+ {
+ "named_end_tag_template": (
+ "{% partialdef thing %}CONTENT{% endpartialdef thing %}"
+ ),
+ },
+ debug_only=True,
+ )
def test_find_partial_source_supports_named_end_tag(self):
- template_source = "{% partialdef thing %}CONTENT{% endpartialdef thing %}"
- template = Template(template_source)
+ template = self.engine.get_template("named_end_tag_template")
partial_proxy = template.extra_data["partials"]["thing"]
- result = partial_proxy.find_partial_source(template_source, "thing")
+ result = partial_proxy.find_partial_source(template.source, "thing")
self.assertEqual(
result, "{% partialdef thing %}CONTENT{% endpartialdef thing %}"
)
+ @setup(
+ {
+ "nested_partials_basic_template": (
+ "{% partialdef outer %}"
+ "{% partialdef inner %}...{% endpartialdef %}"
+ "{% endpartialdef %}"
+ ),
+ },
+ debug_only=True,
+ )
def test_find_partial_source_supports_nested_partials(self):
- template_source = (
- "{% partialdef outer %}"
- "{% partialdef inner %}...{% endpartialdef %}"
- "{% endpartialdef %}"
- )
- template = Template(template_source)
+ template = self.engine.get_template("nested_partials_basic_template")
empty_proxy = template.extra_data["partials"]["outer"]
other_proxy = template.extra_data["partials"]["inner"]
- outer_result = empty_proxy.find_partial_source(template_source, "outer")
+ outer_result = empty_proxy.find_partial_source(template.source, "outer")
self.assertEqual(
outer_result,
(
@@ -336,21 +398,26 @@ INLINE-CONTENT
),
)
- inner_result = other_proxy.find_partial_source(template_source, "inner")
+ inner_result = other_proxy.find_partial_source(template.source, "inner")
self.assertEqual(inner_result, "{% partialdef inner %}...{% endpartialdef %}")
+ @setup(
+ {
+ "nested_partials_named_end_template": (
+ "{% partialdef outer %}"
+ "{% partialdef inner %}...{% endpartialdef inner %}"
+ "{% endpartialdef outer %}"
+ ),
+ },
+ debug_only=True,
+ )
def test_find_partial_source_supports_nested_partials_and_named_end_tags(self):
- template_source = (
- "{% partialdef outer %}"
- "{% partialdef inner %}...{% endpartialdef inner %}"
- "{% endpartialdef outer %}"
- )
- template = Template(template_source)
+ template = self.engine.get_template("nested_partials_named_end_template")
empty_proxy = template.extra_data["partials"]["outer"]
other_proxy = template.extra_data["partials"]["inner"]
- outer_result = empty_proxy.find_partial_source(template_source, "outer")
+ outer_result = empty_proxy.find_partial_source(template.source, "outer")
self.assertEqual(
outer_result,
(
@@ -359,23 +426,28 @@ INLINE-CONTENT
),
)
- inner_result = other_proxy.find_partial_source(template_source, "inner")
+ inner_result = other_proxy.find_partial_source(template.source, "inner")
self.assertEqual(
inner_result, "{% partialdef inner %}...{% endpartialdef inner %}"
)
+ @setup(
+ {
+ "nested_partials_mixed_end_1_template": (
+ "{% partialdef outer %}"
+ "{% partialdef inner %}...{% endpartialdef %}"
+ "{% endpartialdef outer %}"
+ ),
+ },
+ debug_only=True,
+ )
def test_find_partial_source_supports_nested_partials_and_mixed_end_tags_1(self):
- template_source = (
- "{% partialdef outer %}"
- "{% partialdef inner %}...{% endpartialdef %}"
- "{% endpartialdef outer %}"
- )
- template = Template(template_source)
+ template = self.engine.get_template("nested_partials_mixed_end_1_template")
empty_proxy = template.extra_data["partials"]["outer"]
other_proxy = template.extra_data["partials"]["inner"]
- outer_result = empty_proxy.find_partial_source(template_source, "outer")
+ outer_result = empty_proxy.find_partial_source(template.source, "outer")
self.assertEqual(
outer_result,
(
@@ -384,21 +456,26 @@ INLINE-CONTENT
),
)
- inner_result = other_proxy.find_partial_source(template_source, "inner")
+ inner_result = other_proxy.find_partial_source(template.source, "inner")
self.assertEqual(inner_result, "{% partialdef inner %}...{% endpartialdef %}")
+ @setup(
+ {
+ "nested_partials_mixed_end_2_template": (
+ "{% partialdef outer %}"
+ "{% partialdef inner %}...{% endpartialdef inner %}"
+ "{% endpartialdef %}"
+ ),
+ },
+ debug_only=True,
+ )
def test_find_partial_source_supports_nested_partials_and_mixed_end_tags_2(self):
- template_source = (
- "{% partialdef outer %}"
- "{% partialdef inner %}...{% endpartialdef inner %}"
- "{% endpartialdef %}"
- )
- template = Template(template_source)
+ template = self.engine.get_template("nested_partials_mixed_end_2_template")
empty_proxy = template.extra_data["partials"]["outer"]
other_proxy = template.extra_data["partials"]["inner"]
- outer_result = empty_proxy.find_partial_source(template_source, "outer")
+ outer_result = empty_proxy.find_partial_source(template.source, "outer")
self.assertEqual(
outer_result,
(
@@ -407,7 +484,7 @@ INLINE-CONTENT
),
)
- inner_result = other_proxy.find_partial_source(template_source, "inner")
+ inner_result = other_proxy.find_partial_source(template.source, "inner")
self.assertEqual(
inner_result, "{% partialdef inner %}...{% endpartialdef inner %}"
)
diff --git a/tests/template_tests/utils.py b/tests/template_tests/utils.py
index 9bab583e79..da5da123f1 100644
--- a/tests/template_tests/utils.py
+++ b/tests/template_tests/utils.py
@@ -9,7 +9,7 @@ ROOT = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_DIR = os.path.join(ROOT, "templates")
-def setup(templates, *args, test_once=False):
+def setup(templates, *args, test_once=False, debug_only=False):
"""
Runs test method multiple times in the following order:
@@ -54,11 +54,14 @@ def setup(templates, *args, test_once=False):
self.engine = Engine(
libraries=libraries,
loaders=loaders,
+ debug=debug_only,
)
func(self)
if test_once:
return
func(self)
+ if debug_only:
+ return
self.engine = Engine(
libraries=libraries,