1. import os
    
  2. 
    
  3. from django.template import Context, Engine, TemplateSyntaxError
    
  4. from django.template.base import Node
    
  5. from django.template.library import InvalidTemplateLibrary
    
  6. from django.test import SimpleTestCase
    
  7. from django.test.utils import extend_sys_path
    
  8. 
    
  9. from .templatetags import custom, inclusion
    
  10. from .utils import ROOT
    
  11. 
    
  12. LIBRARIES = {
    
  13.     "custom": "template_tests.templatetags.custom",
    
  14.     "inclusion": "template_tests.templatetags.inclusion",
    
  15. }
    
  16. 
    
  17. 
    
  18. class CustomFilterTests(SimpleTestCase):
    
  19.     def test_filter(self):
    
  20.         engine = Engine(libraries=LIBRARIES)
    
  21.         t = engine.from_string("{% load custom %}{{ string|trim:5 }}")
    
  22.         self.assertEqual(
    
  23.             t.render(Context({"string": "abcdefghijklmnopqrstuvwxyz"})), "abcde"
    
  24.         )
    
  25. 
    
  26.     def test_decorated_filter(self):
    
  27.         engine = Engine(libraries=LIBRARIES)
    
  28.         t = engine.from_string("{% load custom %}{{ name|make_data_div }}")
    
  29.         self.assertEqual(
    
  30.             t.render(Context({"name": "foo"})), '<div data-name="foo"></div>'
    
  31.         )
    
  32. 
    
  33. 
    
  34. class TagTestCase(SimpleTestCase):
    
  35.     @classmethod
    
  36.     def setUpClass(cls):
    
  37.         cls.engine = Engine(app_dirs=True, libraries=LIBRARIES)
    
  38.         super().setUpClass()
    
  39. 
    
  40.     def verify_tag(self, tag, name):
    
  41.         self.assertEqual(tag.__name__, name)
    
  42.         self.assertEqual(tag.__doc__, "Expected %s __doc__" % name)
    
  43.         self.assertEqual(tag.__dict__["anything"], "Expected %s __dict__" % name)
    
  44. 
    
  45. 
    
  46. class SimpleTagTests(TagTestCase):
    
  47.     def test_simple_tags(self):
    
  48.         c = Context({"value": 42})
    
  49. 
    
  50.         templates = [
    
  51.             ("{% load custom %}{% no_params %}", "no_params - Expected result"),
    
  52.             ("{% load custom %}{% one_param 37 %}", "one_param - Expected result: 37"),
    
  53.             (
    
  54.                 "{% load custom %}{% explicit_no_context 37 %}",
    
  55.                 "explicit_no_context - Expected result: 37",
    
  56.             ),
    
  57.             (
    
  58.                 "{% load custom %}{% no_params_with_context %}",
    
  59.                 "no_params_with_context - Expected result (context value: 42)",
    
  60.             ),
    
  61.             (
    
  62.                 "{% load custom %}{% params_and_context 37 %}",
    
  63.                 "params_and_context - Expected result (context value: 42): 37",
    
  64.             ),
    
  65.             (
    
  66.                 "{% load custom %}{% simple_two_params 37 42 %}",
    
  67.                 "simple_two_params - Expected result: 37, 42",
    
  68.             ),
    
  69.             (
    
  70.                 "{% load custom %}{% simple_keyword_only_param kwarg=37 %}",
    
  71.                 "simple_keyword_only_param - Expected result: 37",
    
  72.             ),
    
  73.             (
    
  74.                 "{% load custom %}{% simple_keyword_only_default %}",
    
  75.                 "simple_keyword_only_default - Expected result: 42",
    
  76.             ),
    
  77.             (
    
  78.                 "{% load custom %}{% simple_keyword_only_default kwarg=37 %}",
    
  79.                 "simple_keyword_only_default - Expected result: 37",
    
  80.             ),
    
  81.             (
    
  82.                 "{% load custom %}{% simple_one_default 37 %}",
    
  83.                 "simple_one_default - Expected result: 37, hi",
    
  84.             ),
    
  85.             (
    
  86.                 '{% load custom %}{% simple_one_default 37 two="hello" %}',
    
  87.                 "simple_one_default - Expected result: 37, hello",
    
  88.             ),
    
  89.             (
    
  90.                 '{% load custom %}{% simple_one_default one=99 two="hello" %}',
    
  91.                 "simple_one_default - Expected result: 99, hello",
    
  92.             ),
    
  93.             (
    
  94.                 "{% load custom %}{% simple_one_default 37 42 %}",
    
  95.                 "simple_one_default - Expected result: 37, 42",
    
  96.             ),
    
  97.             (
    
  98.                 "{% load custom %}{% simple_unlimited_args 37 %}",
    
  99.                 "simple_unlimited_args - Expected result: 37, hi",
    
  100.             ),
    
  101.             (
    
  102.                 "{% load custom %}{% simple_unlimited_args 37 42 56 89 %}",
    
  103.                 "simple_unlimited_args - Expected result: 37, 42, 56, 89",
    
  104.             ),
    
  105.             (
    
  106.                 "{% load custom %}{% simple_only_unlimited_args %}",
    
  107.                 "simple_only_unlimited_args - Expected result: ",
    
  108.             ),
    
  109.             (
    
  110.                 "{% load custom %}{% simple_only_unlimited_args 37 42 56 89 %}",
    
  111.                 "simple_only_unlimited_args - Expected result: 37, 42, 56, 89",
    
  112.             ),
    
  113.             (
    
  114.                 "{% load custom %}"
    
  115.                 '{% simple_unlimited_args_kwargs 37 40|add:2 56 eggs="scrambled" '
    
  116.                 "four=1|add:3 %}",
    
  117.                 "simple_unlimited_args_kwargs - Expected result: 37, 42, 56 / "
    
  118.                 "eggs=scrambled, four=4",
    
  119.             ),
    
  120.         ]
    
  121. 
    
  122.         for entry in templates:
    
  123.             t = self.engine.from_string(entry[0])
    
  124.             self.assertEqual(t.render(c), entry[1])
    
  125. 
    
  126.         for entry in templates:
    
  127.             t = self.engine.from_string(
    
  128.                 "%s as var %%}Result: {{ var }}" % entry[0][0:-2]
    
  129.             )
    
  130.             self.assertEqual(t.render(c), "Result: %s" % entry[1])
    
  131. 
    
  132.     def test_simple_tag_errors(self):
    
  133.         errors = [
    
  134.             (
    
  135.                 "'simple_one_default' received unexpected keyword argument 'three'",
    
  136.                 '{% load custom %}{% simple_one_default 99 two="hello" three="foo" %}',
    
  137.             ),
    
  138.             (
    
  139.                 "'simple_two_params' received too many positional arguments",
    
  140.                 "{% load custom %}{% simple_two_params 37 42 56 %}",
    
  141.             ),
    
  142.             (
    
  143.                 "'simple_one_default' received too many positional arguments",
    
  144.                 "{% load custom %}{% simple_one_default 37 42 56 %}",
    
  145.             ),
    
  146.             (
    
  147.                 "'simple_keyword_only_param' did not receive value(s) for the "
    
  148.                 "argument(s): 'kwarg'",
    
  149.                 "{% load custom %}{% simple_keyword_only_param %}",
    
  150.             ),
    
  151.             (
    
  152.                 "'simple_keyword_only_param' received multiple values for "
    
  153.                 "keyword argument 'kwarg'",
    
  154.                 "{% load custom %}{% simple_keyword_only_param kwarg=42 kwarg=37 %}",
    
  155.             ),
    
  156.             (
    
  157.                 "'simple_keyword_only_default' received multiple values for "
    
  158.                 "keyword argument 'kwarg'",
    
  159.                 "{% load custom %}{% simple_keyword_only_default kwarg=42 "
    
  160.                 "kwarg=37 %}",
    
  161.             ),
    
  162.             (
    
  163.                 "'simple_unlimited_args_kwargs' received some positional argument(s) "
    
  164.                 "after some keyword argument(s)",
    
  165.                 "{% load custom %}"
    
  166.                 "{% simple_unlimited_args_kwargs 37 40|add:2 "
    
  167.                 'eggs="scrambled" 56 four=1|add:3 %}',
    
  168.             ),
    
  169.             (
    
  170.                 "'simple_unlimited_args_kwargs' received multiple values for keyword "
    
  171.                 "argument 'eggs'",
    
  172.                 "{% load custom %}"
    
  173.                 "{% simple_unlimited_args_kwargs 37 "
    
  174.                 'eggs="scrambled" eggs="scrambled" %}',
    
  175.             ),
    
  176.         ]
    
  177. 
    
  178.         for entry in errors:
    
  179.             with self.assertRaisesMessage(TemplateSyntaxError, entry[0]):
    
  180.                 self.engine.from_string(entry[1])
    
  181. 
    
  182.         for entry in errors:
    
  183.             with self.assertRaisesMessage(TemplateSyntaxError, entry[0]):
    
  184.                 self.engine.from_string("%s as var %%}" % entry[1][0:-2])
    
  185. 
    
  186.     def test_simple_tag_escaping_autoescape_off(self):
    
  187.         c = Context({"name": "Jack & Jill"}, autoescape=False)
    
  188.         t = self.engine.from_string("{% load custom %}{% escape_naive %}")
    
  189.         self.assertEqual(t.render(c), "Hello Jack & Jill!")
    
  190. 
    
  191.     def test_simple_tag_naive_escaping(self):
    
  192.         c = Context({"name": "Jack & Jill"})
    
  193.         t = self.engine.from_string("{% load custom %}{% escape_naive %}")
    
  194.         self.assertEqual(t.render(c), "Hello Jack &amp; Jill!")
    
  195. 
    
  196.     def test_simple_tag_explicit_escaping(self):
    
  197.         # Check we don't double escape
    
  198.         c = Context({"name": "Jack & Jill"})
    
  199.         t = self.engine.from_string("{% load custom %}{% escape_explicit %}")
    
  200.         self.assertEqual(t.render(c), "Hello Jack &amp; Jill!")
    
  201. 
    
  202.     def test_simple_tag_format_html_escaping(self):
    
  203.         # Check we don't double escape
    
  204.         c = Context({"name": "Jack & Jill"})
    
  205.         t = self.engine.from_string("{% load custom %}{% escape_format_html %}")
    
  206.         self.assertEqual(t.render(c), "Hello Jack &amp; Jill!")
    
  207. 
    
  208.     def test_simple_tag_registration(self):
    
  209.         # The decorators preserve the decorated function's docstring, name,
    
  210.         # and attributes.
    
  211.         self.verify_tag(custom.no_params, "no_params")
    
  212.         self.verify_tag(custom.one_param, "one_param")
    
  213.         self.verify_tag(custom.explicit_no_context, "explicit_no_context")
    
  214.         self.verify_tag(custom.no_params_with_context, "no_params_with_context")
    
  215.         self.verify_tag(custom.params_and_context, "params_and_context")
    
  216.         self.verify_tag(
    
  217.             custom.simple_unlimited_args_kwargs, "simple_unlimited_args_kwargs"
    
  218.         )
    
  219.         self.verify_tag(
    
  220.             custom.simple_tag_without_context_parameter,
    
  221.             "simple_tag_without_context_parameter",
    
  222.         )
    
  223. 
    
  224.     def test_simple_tag_missing_context(self):
    
  225.         # The 'context' parameter must be present when takes_context is True
    
  226.         msg = (
    
  227.             "'simple_tag_without_context_parameter' is decorated with "
    
  228.             "takes_context=True so it must have a first argument of 'context'"
    
  229.         )
    
  230.         with self.assertRaisesMessage(TemplateSyntaxError, msg):
    
  231.             self.engine.from_string(
    
  232.                 "{% load custom %}{% simple_tag_without_context_parameter 123 %}"
    
  233.             )
    
  234. 
    
  235.     def test_simple_tag_missing_context_no_params(self):
    
  236.         msg = (
    
  237.             "'simple_tag_takes_context_without_params' is decorated with "
    
  238.             "takes_context=True so it must have a first argument of 'context'"
    
  239.         )
    
  240.         with self.assertRaisesMessage(TemplateSyntaxError, msg):
    
  241.             self.engine.from_string(
    
  242.                 "{% load custom %}{% simple_tag_takes_context_without_params %}"
    
  243.             )
    
  244. 
    
  245. 
    
  246. class InclusionTagTests(TagTestCase):
    
  247.     def test_inclusion_tags(self):
    
  248.         c = Context({"value": 42})
    
  249. 
    
  250.         templates = [
    
  251.             (
    
  252.                 "{% load inclusion %}{% inclusion_no_params %}",
    
  253.                 "inclusion_no_params - Expected result\n",
    
  254.             ),
    
  255.             (
    
  256.                 "{% load inclusion %}{% inclusion_one_param 37 %}",
    
  257.                 "inclusion_one_param - Expected result: 37\n",
    
  258.             ),
    
  259.             (
    
  260.                 "{% load inclusion %}{% inclusion_explicit_no_context 37 %}",
    
  261.                 "inclusion_explicit_no_context - Expected result: 37\n",
    
  262.             ),
    
  263.             (
    
  264.                 "{% load inclusion %}{% inclusion_no_params_with_context %}",
    
  265.                 "inclusion_no_params_with_context - Expected result (context value: "
    
  266.                 "42)\n",
    
  267.             ),
    
  268.             (
    
  269.                 "{% load inclusion %}{% inclusion_params_and_context 37 %}",
    
  270.                 "inclusion_params_and_context - Expected result (context value: 42): "
    
  271.                 "37\n",
    
  272.             ),
    
  273.             (
    
  274.                 "{% load inclusion %}{% inclusion_two_params 37 42 %}",
    
  275.                 "inclusion_two_params - Expected result: 37, 42\n",
    
  276.             ),
    
  277.             (
    
  278.                 "{% load inclusion %}{% inclusion_one_default 37 %}",
    
  279.                 "inclusion_one_default - Expected result: 37, hi\n",
    
  280.             ),
    
  281.             (
    
  282.                 '{% load inclusion %}{% inclusion_one_default 37 two="hello" %}',
    
  283.                 "inclusion_one_default - Expected result: 37, hello\n",
    
  284.             ),
    
  285.             (
    
  286.                 '{% load inclusion %}{% inclusion_one_default one=99 two="hello" %}',
    
  287.                 "inclusion_one_default - Expected result: 99, hello\n",
    
  288.             ),
    
  289.             (
    
  290.                 "{% load inclusion %}{% inclusion_one_default 37 42 %}",
    
  291.                 "inclusion_one_default - Expected result: 37, 42\n",
    
  292.             ),
    
  293.             (
    
  294.                 "{% load inclusion %}{% inclusion_keyword_only_default kwarg=37 %}",
    
  295.                 "inclusion_keyword_only_default - Expected result: 37\n",
    
  296.             ),
    
  297.             (
    
  298.                 "{% load inclusion %}{% inclusion_unlimited_args 37 %}",
    
  299.                 "inclusion_unlimited_args - Expected result: 37, hi\n",
    
  300.             ),
    
  301.             (
    
  302.                 "{% load inclusion %}{% inclusion_unlimited_args 37 42 56 89 %}",
    
  303.                 "inclusion_unlimited_args - Expected result: 37, 42, 56, 89\n",
    
  304.             ),
    
  305.             (
    
  306.                 "{% load inclusion %}{% inclusion_only_unlimited_args %}",
    
  307.                 "inclusion_only_unlimited_args - Expected result: \n",
    
  308.             ),
    
  309.             (
    
  310.                 "{% load inclusion %}{% inclusion_only_unlimited_args 37 42 56 89 %}",
    
  311.                 "inclusion_only_unlimited_args - Expected result: 37, 42, 56, 89\n",
    
  312.             ),
    
  313.             (
    
  314.                 "{% load inclusion %}"
    
  315.                 '{% inclusion_unlimited_args_kwargs 37 40|add:2 56 eggs="scrambled" '
    
  316.                 "four=1|add:3 %}",
    
  317.                 "inclusion_unlimited_args_kwargs - Expected result: 37, 42, 56 / "
    
  318.                 "eggs=scrambled, four=4\n",
    
  319.             ),
    
  320.         ]
    
  321. 
    
  322.         for entry in templates:
    
  323.             t = self.engine.from_string(entry[0])
    
  324.             self.assertEqual(t.render(c), entry[1])
    
  325. 
    
  326.     def test_inclusion_tag_errors(self):
    
  327.         errors = [
    
  328.             (
    
  329.                 "'inclusion_one_default' received unexpected keyword argument 'three'",
    
  330.                 "{% load inclusion %}"
    
  331.                 '{% inclusion_one_default 99 two="hello" three="foo" %}',
    
  332.             ),
    
  333.             (
    
  334.                 "'inclusion_two_params' received too many positional arguments",
    
  335.                 "{% load inclusion %}{% inclusion_two_params 37 42 56 %}",
    
  336.             ),
    
  337.             (
    
  338.                 "'inclusion_one_default' received too many positional arguments",
    
  339.                 "{% load inclusion %}{% inclusion_one_default 37 42 56 %}",
    
  340.             ),
    
  341.             (
    
  342.                 "'inclusion_one_default' did not receive value(s) for the argument(s): "
    
  343.                 "'one'",
    
  344.                 "{% load inclusion %}{% inclusion_one_default %}",
    
  345.             ),
    
  346.             (
    
  347.                 "'inclusion_keyword_only_default' received multiple values "
    
  348.                 "for keyword argument 'kwarg'",
    
  349.                 "{% load inclusion %}{% inclusion_keyword_only_default "
    
  350.                 "kwarg=37 kwarg=42 %}",
    
  351.             ),
    
  352.             (
    
  353.                 "'inclusion_unlimited_args' did not receive value(s) for the "
    
  354.                 "argument(s): 'one'",
    
  355.                 "{% load inclusion %}{% inclusion_unlimited_args %}",
    
  356.             ),
    
  357.             (
    
  358.                 "'inclusion_unlimited_args_kwargs' received some positional "
    
  359.                 "argument(s) after some keyword argument(s)",
    
  360.                 "{% load inclusion %}"
    
  361.                 "{% inclusion_unlimited_args_kwargs 37 40|add:2 "
    
  362.                 'eggs="boiled" 56 four=1|add:3 %}',
    
  363.             ),
    
  364.             (
    
  365.                 "'inclusion_unlimited_args_kwargs' received multiple values for "
    
  366.                 "keyword argument 'eggs'",
    
  367.                 "{% load inclusion %}"
    
  368.                 "{% inclusion_unlimited_args_kwargs 37 "
    
  369.                 'eggs="scrambled" eggs="scrambled" %}',
    
  370.             ),
    
  371.         ]
    
  372. 
    
  373.         for entry in errors:
    
  374.             with self.assertRaisesMessage(TemplateSyntaxError, entry[0]):
    
  375.                 self.engine.from_string(entry[1])
    
  376. 
    
  377.     def test_include_tag_missing_context(self):
    
  378.         # The 'context' parameter must be present when takes_context is True
    
  379.         msg = (
    
  380.             "'inclusion_tag_without_context_parameter' is decorated with "
    
  381.             "takes_context=True so it must have a first argument of 'context'"
    
  382.         )
    
  383.         with self.assertRaisesMessage(TemplateSyntaxError, msg):
    
  384.             self.engine.from_string(
    
  385.                 "{% load inclusion %}{% inclusion_tag_without_context_parameter 123 %}"
    
  386.             )
    
  387. 
    
  388.     def test_include_tag_missing_context_no_params(self):
    
  389.         msg = (
    
  390.             "'inclusion_tag_takes_context_without_params' is decorated with "
    
  391.             "takes_context=True so it must have a first argument of 'context'"
    
  392.         )
    
  393.         with self.assertRaisesMessage(TemplateSyntaxError, msg):
    
  394.             self.engine.from_string(
    
  395.                 "{% load inclusion %}{% inclusion_tag_takes_context_without_params %}"
    
  396.             )
    
  397. 
    
  398.     def test_inclusion_tags_from_template(self):
    
  399.         c = Context({"value": 42})
    
  400. 
    
  401.         templates = [
    
  402.             (
    
  403.                 "{% load inclusion %}{% inclusion_no_params_from_template %}",
    
  404.                 "inclusion_no_params_from_template - Expected result\n",
    
  405.             ),
    
  406.             (
    
  407.                 "{% load inclusion %}{% inclusion_one_param_from_template 37 %}",
    
  408.                 "inclusion_one_param_from_template - Expected result: 37\n",
    
  409.             ),
    
  410.             (
    
  411.                 "{% load inclusion %}"
    
  412.                 "{% inclusion_explicit_no_context_from_template 37 %}",
    
  413.                 "inclusion_explicit_no_context_from_template - Expected result: 37\n",
    
  414.             ),
    
  415.             (
    
  416.                 "{% load inclusion %}"
    
  417.                 "{% inclusion_no_params_with_context_from_template %}",
    
  418.                 "inclusion_no_params_with_context_from_template - Expected result "
    
  419.                 "(context value: 42)\n",
    
  420.             ),
    
  421.             (
    
  422.                 "{% load inclusion %}"
    
  423.                 "{% inclusion_params_and_context_from_template 37 %}",
    
  424.                 "inclusion_params_and_context_from_template - Expected result (context "
    
  425.                 "value: 42): 37\n",
    
  426.             ),
    
  427.             (
    
  428.                 "{% load inclusion %}{% inclusion_two_params_from_template 37 42 %}",
    
  429.                 "inclusion_two_params_from_template - Expected result: 37, 42\n",
    
  430.             ),
    
  431.             (
    
  432.                 "{% load inclusion %}{% inclusion_one_default_from_template 37 %}",
    
  433.                 "inclusion_one_default_from_template - Expected result: 37, hi\n",
    
  434.             ),
    
  435.             (
    
  436.                 "{% load inclusion %}{% inclusion_one_default_from_template 37 42 %}",
    
  437.                 "inclusion_one_default_from_template - Expected result: 37, 42\n",
    
  438.             ),
    
  439.             (
    
  440.                 "{% load inclusion %}{% inclusion_unlimited_args_from_template 37 %}",
    
  441.                 "inclusion_unlimited_args_from_template - Expected result: 37, hi\n",
    
  442.             ),
    
  443.             (
    
  444.                 "{% load inclusion %}"
    
  445.                 "{% inclusion_unlimited_args_from_template 37 42 56 89 %}",
    
  446.                 "inclusion_unlimited_args_from_template - Expected result: 37, 42, 56, "
    
  447.                 "89\n",
    
  448.             ),
    
  449.             (
    
  450.                 "{% load inclusion %}{% inclusion_only_unlimited_args_from_template %}",
    
  451.                 "inclusion_only_unlimited_args_from_template - Expected result: \n",
    
  452.             ),
    
  453.             (
    
  454.                 "{% load inclusion %}"
    
  455.                 "{% inclusion_only_unlimited_args_from_template 37 42 56 89 %}",
    
  456.                 "inclusion_only_unlimited_args_from_template - Expected result: 37, "
    
  457.                 "42, 56, 89\n",
    
  458.             ),
    
  459.         ]
    
  460. 
    
  461.         for entry in templates:
    
  462.             t = self.engine.from_string(entry[0])
    
  463.             self.assertEqual(t.render(c), entry[1])
    
  464. 
    
  465.     def test_inclusion_tag_registration(self):
    
  466.         # The decorators preserve the decorated function's docstring, name,
    
  467.         # and attributes.
    
  468.         self.verify_tag(inclusion.inclusion_no_params, "inclusion_no_params")
    
  469.         self.verify_tag(inclusion.inclusion_one_param, "inclusion_one_param")
    
  470.         self.verify_tag(
    
  471.             inclusion.inclusion_explicit_no_context, "inclusion_explicit_no_context"
    
  472.         )
    
  473.         self.verify_tag(
    
  474.             inclusion.inclusion_no_params_with_context,
    
  475.             "inclusion_no_params_with_context",
    
  476.         )
    
  477.         self.verify_tag(
    
  478.             inclusion.inclusion_params_and_context, "inclusion_params_and_context"
    
  479.         )
    
  480.         self.verify_tag(inclusion.inclusion_two_params, "inclusion_two_params")
    
  481.         self.verify_tag(inclusion.inclusion_one_default, "inclusion_one_default")
    
  482.         self.verify_tag(inclusion.inclusion_unlimited_args, "inclusion_unlimited_args")
    
  483.         self.verify_tag(
    
  484.             inclusion.inclusion_only_unlimited_args, "inclusion_only_unlimited_args"
    
  485.         )
    
  486.         self.verify_tag(
    
  487.             inclusion.inclusion_tag_without_context_parameter,
    
  488.             "inclusion_tag_without_context_parameter",
    
  489.         )
    
  490.         self.verify_tag(inclusion.inclusion_tag_use_l10n, "inclusion_tag_use_l10n")
    
  491.         self.verify_tag(
    
  492.             inclusion.inclusion_unlimited_args_kwargs, "inclusion_unlimited_args_kwargs"
    
  493.         )
    
  494. 
    
  495.     def test_15070_use_l10n(self):
    
  496.         """
    
  497.         Inclusion tag passes down `use_l10n` of context to the
    
  498.         Context of the included/rendered template as well.
    
  499.         """
    
  500.         c = Context({})
    
  501.         t = self.engine.from_string("{% load inclusion %}{% inclusion_tag_use_l10n %}")
    
  502.         self.assertEqual(t.render(c).strip(), "None")
    
  503. 
    
  504.         c.use_l10n = True
    
  505.         self.assertEqual(t.render(c).strip(), "True")
    
  506. 
    
  507.     def test_no_render_side_effect(self):
    
  508.         """
    
  509.         #23441 -- InclusionNode shouldn't modify its nodelist at render time.
    
  510.         """
    
  511.         engine = Engine(app_dirs=True, libraries=LIBRARIES)
    
  512.         template = engine.from_string("{% load inclusion %}{% inclusion_no_params %}")
    
  513.         count = template.nodelist.get_nodes_by_type(Node)
    
  514.         template.render(Context({}))
    
  515.         self.assertEqual(template.nodelist.get_nodes_by_type(Node), count)
    
  516. 
    
  517.     def test_render_context_is_cleared(self):
    
  518.         """
    
  519.         #24555 -- InclusionNode should push and pop the render_context stack
    
  520.         when rendering. Otherwise, leftover values such as blocks from
    
  521.         extending can interfere with subsequent rendering.
    
  522.         """
    
  523.         engine = Engine(app_dirs=True, libraries=LIBRARIES)
    
  524.         template = engine.from_string(
    
  525.             "{% load inclusion %}{% inclusion_extends1 %}{% inclusion_extends2 %}"
    
  526.         )
    
  527.         self.assertEqual(template.render(Context({})).strip(), "one\ntwo")
    
  528. 
    
  529. 
    
  530. class TemplateTagLoadingTests(SimpleTestCase):
    
  531.     @classmethod
    
  532.     def setUpClass(cls):
    
  533.         cls.egg_dir = os.path.join(ROOT, "eggs")
    
  534.         super().setUpClass()
    
  535. 
    
  536.     def test_load_error(self):
    
  537.         msg = (
    
  538.             "Invalid template library specified. ImportError raised when "
    
  539.             "trying to load 'template_tests.broken_tag': cannot import name "
    
  540.             "'Xtemplate'"
    
  541.         )
    
  542.         with self.assertRaisesMessage(InvalidTemplateLibrary, msg):
    
  543.             Engine(libraries={"broken_tag": "template_tests.broken_tag"})
    
  544. 
    
  545.     def test_load_error_egg(self):
    
  546.         egg_name = "%s/tagsegg.egg" % self.egg_dir
    
  547.         msg = (
    
  548.             "Invalid template library specified. ImportError raised when "
    
  549.             "trying to load 'tagsegg.templatetags.broken_egg': cannot "
    
  550.             "import name 'Xtemplate'"
    
  551.         )
    
  552.         with extend_sys_path(egg_name):
    
  553.             with self.assertRaisesMessage(InvalidTemplateLibrary, msg):
    
  554.                 Engine(libraries={"broken_egg": "tagsegg.templatetags.broken_egg"})
    
  555. 
    
  556.     def test_load_working_egg(self):
    
  557.         ttext = "{% load working_egg %}"
    
  558.         egg_name = "%s/tagsegg.egg" % self.egg_dir
    
  559.         with extend_sys_path(egg_name):
    
  560.             engine = Engine(
    
  561.                 libraries={
    
  562.                     "working_egg": "tagsegg.templatetags.working_egg",
    
  563.                 }
    
  564.             )
    
  565.             engine.from_string(ttext)
    
  566. 
    
  567.     def test_load_annotated_function(self):
    
  568.         Engine(
    
  569.             libraries={
    
  570.                 "annotated_tag_function": "template_tests.annotated_tag_function",
    
  571.             }
    
  572.         )