123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- from unittest import mock
- from django.http import HttpRequest
- from django.template import (
- Context,
- Engine,
- RequestContext,
- Template,
- Variable,
- VariableDoesNotExist,
- )
- from django.template.context import RenderContext
- from django.test import RequestFactory, SimpleTestCase, override_settings
- class ContextTests(SimpleTestCase):
- def test_context(self):
- c = Context({"a": 1, "b": "xyzzy"})
- self.assertEqual(c["a"], 1)
- self.assertEqual(c.push(), {})
- c["a"] = 2
- self.assertEqual(c["a"], 2)
- self.assertEqual(c.get("a"), 2)
- self.assertEqual(c.pop(), {"a": 2})
- self.assertEqual(c["a"], 1)
- self.assertEqual(c.get("foo", 42), 42)
- self.assertEqual(c, mock.ANY)
- def test_push_context_manager(self):
- c = Context({"a": 1})
- with c.push():
- c["a"] = 2
- self.assertEqual(c["a"], 2)
- self.assertEqual(c["a"], 1)
- with c.push(a=3):
- self.assertEqual(c["a"], 3)
- self.assertEqual(c["a"], 1)
- def test_update_context_manager(self):
- c = Context({"a": 1})
- with c.update({}):
- c["a"] = 2
- self.assertEqual(c["a"], 2)
- self.assertEqual(c["a"], 1)
- with c.update({"a": 3}):
- self.assertEqual(c["a"], 3)
- self.assertEqual(c["a"], 1)
- def test_push_context_manager_with_context_object(self):
- c = Context({"a": 1})
- with c.push(Context({"a": 3})):
- self.assertEqual(c["a"], 3)
- self.assertEqual(c["a"], 1)
- def test_update_context_manager_with_context_object(self):
- c = Context({"a": 1})
- with c.update(Context({"a": 3})):
- self.assertEqual(c["a"], 3)
- self.assertEqual(c["a"], 1)
- def test_push_proper_layering(self):
- c = Context({"a": 1})
- c.push(Context({"b": 2}))
- c.push(Context({"c": 3, "d": {"z": "26"}}))
- self.assertEqual(
- c.dicts,
- [
- {"False": False, "None": None, "True": True},
- {"a": 1},
- {"b": 2},
- {"c": 3, "d": {"z": "26"}},
- ],
- )
- def test_update_proper_layering(self):
- c = Context({"a": 1})
- c.update(Context({"b": 2}))
- c.update(Context({"c": 3, "d": {"z": "26"}}))
- self.assertEqual(
- c.dicts,
- [
- {"False": False, "None": None, "True": True},
- {"a": 1},
- {"b": 2},
- {"c": 3, "d": {"z": "26"}},
- ],
- )
- def test_setdefault(self):
- c = Context()
- x = c.setdefault("x", 42)
- self.assertEqual(x, 42)
- self.assertEqual(c["x"], 42)
- x = c.setdefault("x", 100)
- self.assertEqual(x, 42)
- self.assertEqual(c["x"], 42)
- def test_resolve_on_context_method(self):
- """
- #17778 -- Variable shouldn't resolve RequestContext methods
- """
- empty_context = Context()
- with self.assertRaises(VariableDoesNotExist):
- Variable("no_such_variable").resolve(empty_context)
- with self.assertRaises(VariableDoesNotExist):
- Variable("new").resolve(empty_context)
- self.assertEqual(
- Variable("new").resolve(Context({"new": "foo"})),
- "foo",
- )
- def test_render_context(self):
- test_context = RenderContext({"fruit": "papaya"})
- # push() limits access to the topmost dict
- test_context.push()
- test_context["vegetable"] = "artichoke"
- self.assertEqual(list(test_context), ["vegetable"])
- self.assertNotIn("fruit", test_context)
- with self.assertRaises(KeyError):
- test_context["fruit"]
- self.assertIsNone(test_context.get("fruit"))
- def test_flatten_context(self):
- a = Context()
- a.update({"a": 2})
- a.update({"b": 4})
- a.update({"c": 8})
- self.assertEqual(
- a.flatten(),
- {"False": False, "None": None, "True": True, "a": 2, "b": 4, "c": 8},
- )
- def test_flatten_context_with_context(self):
- """
- Context.push() with a Context argument should work.
- """
- a = Context({"a": 2})
- a.push(Context({"z": "8"}))
- self.assertEqual(
- a.flatten(),
- {
- "False": False,
- "None": None,
- "True": True,
- "a": 2,
- "z": "8",
- },
- )
- def test_flatten_context_with_context_copy(self):
- ctx1 = Context({"a": 2})
- ctx2 = ctx1.new(Context({"b": 4}))
- self.assertEqual(
- ctx2.dicts, [{"True": True, "False": False, "None": None}, {"b": 4}]
- )
- self.assertEqual(
- ctx2.flatten(),
- {"False": False, "None": None, "True": True, "b": 4},
- )
- def test_context_comparable(self):
- """
- #21765 -- equality comparison should work
- """
- test_data = {"x": "y", "v": "z", "d": {"o": object, "a": "b"}}
- self.assertEqual(Context(test_data), Context(test_data))
- a = Context()
- b = Context()
- self.assertEqual(a, b)
- # update only a
- a.update({"a": 1})
- self.assertNotEqual(a, b)
- # update both to check regression
- a.update({"c": 3})
- b.update({"c": 3})
- self.assertNotEqual(a, b)
- # make contexts equals again
- b.update({"a": 1})
- self.assertEqual(a, b)
- def test_copy_request_context_twice(self):
- """
- #24273 -- Copy twice shouldn't raise an exception
- """
- RequestContext(HttpRequest()).new().new()
- def test_set_upward(self):
- c = Context({"a": 1})
- c.set_upward("a", 2)
- self.assertEqual(c.get("a"), 2)
- def test_set_upward_empty_context(self):
- empty_context = Context()
- empty_context.set_upward("a", 1)
- self.assertEqual(empty_context.get("a"), 1)
- def test_set_upward_with_push(self):
- """
- The highest context which has the given key is used.
- """
- c = Context({"a": 1})
- c.push({"a": 2})
- c.set_upward("a", 3)
- self.assertEqual(c.get("a"), 3)
- c.pop()
- self.assertEqual(c.get("a"), 1)
- def test_set_upward_with_push_no_match(self):
- """
- The highest context is used if the given key isn't found.
- """
- c = Context({"b": 1})
- c.push({"b": 2})
- c.set_upward("a", 2)
- self.assertEqual(len(c.dicts), 3)
- self.assertEqual(c.dicts[-1]["a"], 2)
- def context_process_returning_none(request):
- return None
- class RequestContextTests(SimpleTestCase):
- request_factory = RequestFactory()
- def test_include_only(self):
- """
- #15721 -- ``{% include %}`` and ``RequestContext`` should work
- together.
- """
- engine = Engine(
- loaders=[
- (
- "django.template.loaders.locmem.Loader",
- {
- "child": '{{ var|default:"none" }}',
- },
- ),
- ]
- )
- request = self.request_factory.get("/")
- ctx = RequestContext(request, {"var": "parent"})
- self.assertEqual(
- engine.from_string('{% include "child" %}').render(ctx), "parent"
- )
- self.assertEqual(
- engine.from_string('{% include "child" only %}').render(ctx), "none"
- )
- def test_stack_size(self):
- """Optimized RequestContext construction (#7116)."""
- request = self.request_factory.get("/")
- ctx = RequestContext(request, {})
- # The stack contains 4 items:
- # [builtins, supplied context, context processor, empty dict]
- self.assertEqual(len(ctx.dicts), 4)
- def test_context_comparable(self):
- # Create an engine without any context processors.
- test_data = {"x": "y", "v": "z", "d": {"o": object, "a": "b"}}
- # test comparing RequestContext to prevent problems if somebody
- # adds __eq__ in the future
- request = self.request_factory.get("/")
- self.assertEqual(
- RequestContext(request, dict_=test_data),
- RequestContext(request, dict_=test_data),
- )
- def test_modify_context_and_render(self):
- template = Template("{{ foo }}")
- request = self.request_factory.get("/")
- context = RequestContext(request, {})
- context["foo"] = "foo"
- self.assertEqual(template.render(context), "foo")
- @override_settings(
- TEMPLATES=[
- {
- "BACKEND": "django.template.backends.django.DjangoTemplates",
- "OPTIONS": {
- "context_processors": [
- "django.template.context_processors.request",
- "template_tests.test_context.context_process_returning_none",
- ],
- },
- }
- ],
- )
- def test_template_context_processor_returning_none(self):
- request_context = RequestContext(HttpRequest())
- msg = (
- "Context processor context_process_returning_none didn't return a "
- "dictionary."
- )
- with self.assertRaisesMessage(TypeError, msg):
- with request_context.bind_template(Template("")):
- pass
|