1. from unittest import mock
    
  2. 
    
  3. from django.http import HttpRequest
    
  4. from django.template import (
    
  5.     Context,
    
  6.     Engine,
    
  7.     RequestContext,
    
  8.     Template,
    
  9.     Variable,
    
  10.     VariableDoesNotExist,
    
  11. )
    
  12. from django.template.context import RenderContext
    
  13. from django.test import RequestFactory, SimpleTestCase
    
  14. 
    
  15. 
    
  16. class ContextTests(SimpleTestCase):
    
  17.     def test_context(self):
    
  18.         c = Context({"a": 1, "b": "xyzzy"})
    
  19.         self.assertEqual(c["a"], 1)
    
  20.         self.assertEqual(c.push(), {})
    
  21.         c["a"] = 2
    
  22.         self.assertEqual(c["a"], 2)
    
  23.         self.assertEqual(c.get("a"), 2)
    
  24.         self.assertEqual(c.pop(), {"a": 2})
    
  25.         self.assertEqual(c["a"], 1)
    
  26.         self.assertEqual(c.get("foo", 42), 42)
    
  27.         self.assertEqual(c, mock.ANY)
    
  28. 
    
  29.     def test_push_context_manager(self):
    
  30.         c = Context({"a": 1})
    
  31.         with c.push():
    
  32.             c["a"] = 2
    
  33.             self.assertEqual(c["a"], 2)
    
  34.         self.assertEqual(c["a"], 1)
    
  35. 
    
  36.         with c.push(a=3):
    
  37.             self.assertEqual(c["a"], 3)
    
  38.         self.assertEqual(c["a"], 1)
    
  39. 
    
  40.     def test_update_context_manager(self):
    
  41.         c = Context({"a": 1})
    
  42.         with c.update({}):
    
  43.             c["a"] = 2
    
  44.             self.assertEqual(c["a"], 2)
    
  45.         self.assertEqual(c["a"], 1)
    
  46. 
    
  47.         with c.update({"a": 3}):
    
  48.             self.assertEqual(c["a"], 3)
    
  49.         self.assertEqual(c["a"], 1)
    
  50. 
    
  51.     def test_push_context_manager_with_context_object(self):
    
  52.         c = Context({"a": 1})
    
  53.         with c.push(Context({"a": 3})):
    
  54.             self.assertEqual(c["a"], 3)
    
  55.         self.assertEqual(c["a"], 1)
    
  56. 
    
  57.     def test_update_context_manager_with_context_object(self):
    
  58.         c = Context({"a": 1})
    
  59.         with c.update(Context({"a": 3})):
    
  60.             self.assertEqual(c["a"], 3)
    
  61.         self.assertEqual(c["a"], 1)
    
  62. 
    
  63.     def test_push_proper_layering(self):
    
  64.         c = Context({"a": 1})
    
  65.         c.push(Context({"b": 2}))
    
  66.         c.push(Context({"c": 3, "d": {"z": "26"}}))
    
  67.         self.assertEqual(
    
  68.             c.dicts,
    
  69.             [
    
  70.                 {"False": False, "None": None, "True": True},
    
  71.                 {"a": 1},
    
  72.                 {"b": 2},
    
  73.                 {"c": 3, "d": {"z": "26"}},
    
  74.             ],
    
  75.         )
    
  76. 
    
  77.     def test_update_proper_layering(self):
    
  78.         c = Context({"a": 1})
    
  79.         c.update(Context({"b": 2}))
    
  80.         c.update(Context({"c": 3, "d": {"z": "26"}}))
    
  81.         self.assertEqual(
    
  82.             c.dicts,
    
  83.             [
    
  84.                 {"False": False, "None": None, "True": True},
    
  85.                 {"a": 1},
    
  86.                 {"b": 2},
    
  87.                 {"c": 3, "d": {"z": "26"}},
    
  88.             ],
    
  89.         )
    
  90. 
    
  91.     def test_setdefault(self):
    
  92.         c = Context()
    
  93. 
    
  94.         x = c.setdefault("x", 42)
    
  95.         self.assertEqual(x, 42)
    
  96.         self.assertEqual(c["x"], 42)
    
  97. 
    
  98.         x = c.setdefault("x", 100)
    
  99.         self.assertEqual(x, 42)
    
  100.         self.assertEqual(c["x"], 42)
    
  101. 
    
  102.     def test_resolve_on_context_method(self):
    
  103.         """
    
  104.         #17778 -- Variable shouldn't resolve RequestContext methods
    
  105.         """
    
  106.         empty_context = Context()
    
  107. 
    
  108.         with self.assertRaises(VariableDoesNotExist):
    
  109.             Variable("no_such_variable").resolve(empty_context)
    
  110. 
    
  111.         with self.assertRaises(VariableDoesNotExist):
    
  112.             Variable("new").resolve(empty_context)
    
  113. 
    
  114.         self.assertEqual(
    
  115.             Variable("new").resolve(Context({"new": "foo"})),
    
  116.             "foo",
    
  117.         )
    
  118. 
    
  119.     def test_render_context(self):
    
  120.         test_context = RenderContext({"fruit": "papaya"})
    
  121. 
    
  122.         # push() limits access to the topmost dict
    
  123.         test_context.push()
    
  124. 
    
  125.         test_context["vegetable"] = "artichoke"
    
  126.         self.assertEqual(list(test_context), ["vegetable"])
    
  127. 
    
  128.         self.assertNotIn("fruit", test_context)
    
  129.         with self.assertRaises(KeyError):
    
  130.             test_context["fruit"]
    
  131.         self.assertIsNone(test_context.get("fruit"))
    
  132. 
    
  133.     def test_flatten_context(self):
    
  134.         a = Context()
    
  135.         a.update({"a": 2})
    
  136.         a.update({"b": 4})
    
  137.         a.update({"c": 8})
    
  138. 
    
  139.         self.assertEqual(
    
  140.             a.flatten(),
    
  141.             {"False": False, "None": None, "True": True, "a": 2, "b": 4, "c": 8},
    
  142.         )
    
  143. 
    
  144.     def test_flatten_context_with_context(self):
    
  145.         """
    
  146.         Context.push() with a Context argument should work.
    
  147.         """
    
  148.         a = Context({"a": 2})
    
  149.         a.push(Context({"z": "8"}))
    
  150.         self.assertEqual(
    
  151.             a.flatten(),
    
  152.             {
    
  153.                 "False": False,
    
  154.                 "None": None,
    
  155.                 "True": True,
    
  156.                 "a": 2,
    
  157.                 "z": "8",
    
  158.             },
    
  159.         )
    
  160. 
    
  161.     def test_context_comparable(self):
    
  162.         """
    
  163.         #21765 -- equality comparison should work
    
  164.         """
    
  165. 
    
  166.         test_data = {"x": "y", "v": "z", "d": {"o": object, "a": "b"}}
    
  167. 
    
  168.         self.assertEqual(Context(test_data), Context(test_data))
    
  169. 
    
  170.         a = Context()
    
  171.         b = Context()
    
  172.         self.assertEqual(a, b)
    
  173. 
    
  174.         # update only a
    
  175.         a.update({"a": 1})
    
  176.         self.assertNotEqual(a, b)
    
  177. 
    
  178.         # update both to check regression
    
  179.         a.update({"c": 3})
    
  180.         b.update({"c": 3})
    
  181.         self.assertNotEqual(a, b)
    
  182. 
    
  183.         # make contexts equals again
    
  184.         b.update({"a": 1})
    
  185.         self.assertEqual(a, b)
    
  186. 
    
  187.     def test_copy_request_context_twice(self):
    
  188.         """
    
  189.         #24273 -- Copy twice shouldn't raise an exception
    
  190.         """
    
  191.         RequestContext(HttpRequest()).new().new()
    
  192. 
    
  193.     def test_set_upward(self):
    
  194.         c = Context({"a": 1})
    
  195.         c.set_upward("a", 2)
    
  196.         self.assertEqual(c.get("a"), 2)
    
  197. 
    
  198.     def test_set_upward_empty_context(self):
    
  199.         empty_context = Context()
    
  200.         empty_context.set_upward("a", 1)
    
  201.         self.assertEqual(empty_context.get("a"), 1)
    
  202. 
    
  203.     def test_set_upward_with_push(self):
    
  204.         """
    
  205.         The highest context which has the given key is used.
    
  206.         """
    
  207.         c = Context({"a": 1})
    
  208.         c.push({"a": 2})
    
  209.         c.set_upward("a", 3)
    
  210.         self.assertEqual(c.get("a"), 3)
    
  211.         c.pop()
    
  212.         self.assertEqual(c.get("a"), 1)
    
  213. 
    
  214.     def test_set_upward_with_push_no_match(self):
    
  215.         """
    
  216.         The highest context is used if the given key isn't found.
    
  217.         """
    
  218.         c = Context({"b": 1})
    
  219.         c.push({"b": 2})
    
  220.         c.set_upward("a", 2)
    
  221.         self.assertEqual(len(c.dicts), 3)
    
  222.         self.assertEqual(c.dicts[-1]["a"], 2)
    
  223. 
    
  224. 
    
  225. class RequestContextTests(SimpleTestCase):
    
  226.     request_factory = RequestFactory()
    
  227. 
    
  228.     def test_include_only(self):
    
  229.         """
    
  230.         #15721 -- ``{% include %}`` and ``RequestContext`` should work
    
  231.         together.
    
  232.         """
    
  233.         engine = Engine(
    
  234.             loaders=[
    
  235.                 (
    
  236.                     "django.template.loaders.locmem.Loader",
    
  237.                     {
    
  238.                         "child": '{{ var|default:"none" }}',
    
  239.                     },
    
  240.                 ),
    
  241.             ]
    
  242.         )
    
  243.         request = self.request_factory.get("/")
    
  244.         ctx = RequestContext(request, {"var": "parent"})
    
  245.         self.assertEqual(
    
  246.             engine.from_string('{% include "child" %}').render(ctx), "parent"
    
  247.         )
    
  248.         self.assertEqual(
    
  249.             engine.from_string('{% include "child" only %}').render(ctx), "none"
    
  250.         )
    
  251. 
    
  252.     def test_stack_size(self):
    
  253.         """Optimized RequestContext construction (#7116)."""
    
  254.         request = self.request_factory.get("/")
    
  255.         ctx = RequestContext(request, {})
    
  256.         # The stack contains 4 items:
    
  257.         # [builtins, supplied context, context processor, empty dict]
    
  258.         self.assertEqual(len(ctx.dicts), 4)
    
  259. 
    
  260.     def test_context_comparable(self):
    
  261.         # Create an engine without any context processors.
    
  262.         test_data = {"x": "y", "v": "z", "d": {"o": object, "a": "b"}}
    
  263. 
    
  264.         # test comparing RequestContext to prevent problems if somebody
    
  265.         # adds __eq__ in the future
    
  266.         request = self.request_factory.get("/")
    
  267. 
    
  268.         self.assertEqual(
    
  269.             RequestContext(request, dict_=test_data),
    
  270.             RequestContext(request, dict_=test_data),
    
  271.         )
    
  272. 
    
  273.     def test_modify_context_and_render(self):
    
  274.         template = Template("{{ foo }}")
    
  275.         request = self.request_factory.get("/")
    
  276.         context = RequestContext(request, {})
    
  277.         context["foo"] = "foo"
    
  278.         self.assertEqual(template.render(context), "foo")