1. from django.template import NodeList, TemplateSyntaxError
    
  2. from django.template.base import Node
    
  3. from django.template.loader_tags import ExtendsNode
    
  4. from django.test import SimpleTestCase
    
  5. 
    
  6. from ..utils import setup
    
  7. 
    
  8. inheritance_templates = {
    
  9.     "inheritance01": (
    
  10.         "1{% block first %}&{% endblock %}3{% block second %}_{% endblock %}"
    
  11.     ),
    
  12.     "inheritance02": "{% extends 'inheritance01' %}"
    
  13.     "{% block first %}2{% endblock %}{% block second %}4{% endblock %}",
    
  14.     "inheritance03": "{% extends 'inheritance02' %}",
    
  15.     "inheritance04": "{% extends 'inheritance01' %}",
    
  16.     "inheritance05": "{% extends 'inheritance02' %}",
    
  17.     "inheritance06": "{% extends foo %}",
    
  18.     "inheritance07": "{% extends 'inheritance01' %}{% block second %}5{% endblock %}",
    
  19.     "inheritance08": "{% extends 'inheritance02' %}{% block second %}5{% endblock %}",
    
  20.     "inheritance09": "{% extends 'inheritance04' %}",
    
  21.     "inheritance10": "{% extends 'inheritance04' %}      ",
    
  22.     "inheritance11": "{% extends 'inheritance04' %}"
    
  23.     "{% block first %}2{% endblock %}{% block second %}4{% endblock %}",
    
  24.     "inheritance12": "{% extends 'inheritance07' %}{% block first %}2{% endblock %}",
    
  25.     "inheritance13": "{% extends 'inheritance02' %}"
    
  26.     "{% block first %}a{% endblock %}{% block second %}b{% endblock %}",
    
  27.     "inheritance14": (
    
  28.         "{% extends 'inheritance01' %}{% block newblock %}NO DISPLAY{% endblock %}"
    
  29.     ),
    
  30.     "inheritance15": "{% extends 'inheritance01' %}"
    
  31.     "{% block first %}2{% block inner %}inner{% endblock %}{% endblock %}",
    
  32.     "inheritance16": "{% extends 'inheritance15' %}{% block inner %}out{% endblock %}",
    
  33.     "inheritance17": "{% load testtags %}{% block first %}1234{% endblock %}",
    
  34.     "inheritance18": "{% load testtags %}{% echo this that theother %}5678",
    
  35.     "inheritance19": "{% extends 'inheritance01' %}"
    
  36.     "{% block first %}{% load testtags %}{% echo 400 %}5678{% endblock %}",
    
  37.     "inheritance20": (
    
  38.         "{% extends 'inheritance01' %}{% block first %}{{ block.super }}a{% endblock %}"
    
  39.     ),
    
  40.     "inheritance21": (
    
  41.         "{% extends 'inheritance02' %}{% block first %}{{ block.super }}a{% endblock %}"
    
  42.     ),
    
  43.     "inheritance22": (
    
  44.         "{% extends 'inheritance04' %}{% block first %}{{ block.super }}a{% endblock %}"
    
  45.     ),
    
  46.     "inheritance23": (
    
  47.         "{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}"
    
  48.     ),
    
  49.     "inheritance24": "{% extends context_template %}"
    
  50.     "{% block first %}2{% endblock %}{% block second %}4{% endblock %}",
    
  51.     "inheritance25": "{% extends context_template.1 %}"
    
  52.     "{% block first %}2{% endblock %}{% block second %}4{% endblock %}",
    
  53.     "inheritance26": "no tags",
    
  54.     "inheritance27": "{% extends 'inheritance26' %}",
    
  55.     "inheritance 28": "{% block first %}!{% endblock %}",
    
  56.     "inheritance29": "{% extends 'inheritance 28' %}",
    
  57.     "inheritance30": "1{% if optional %}{% block opt %}2{% endblock %}{% endif %}3",
    
  58.     "inheritance31": "{% extends 'inheritance30' %}{% block opt %}two{% endblock %}",
    
  59.     "inheritance32": "{% extends 'inheritance30' %}{% block opt %}two{% endblock %}",
    
  60.     "inheritance33": (
    
  61.         "1{% if optional == 1 %}{% block opt %}2{% endblock %}{% endif %}3"
    
  62.     ),
    
  63.     "inheritance34": "{% extends 'inheritance33' %}{% block opt %}two{% endblock %}",
    
  64.     "inheritance35": "{% extends 'inheritance33' %}{% block opt %}two{% endblock %}",
    
  65.     "inheritance36": (
    
  66.         "{% for n in numbers %}_{% block opt %}{{ n }}{% endblock %}{% endfor %}_"
    
  67.     ),
    
  68.     "inheritance37": "{% extends 'inheritance36' %}{% block opt %}X{% endblock %}",
    
  69.     "inheritance38": "{% extends 'inheritance36' %}{% block opt %}X{% endblock %}",
    
  70.     "inheritance39": (
    
  71.         "{% extends 'inheritance30' %}{% block opt %}new{{ block.super }}{% endblock %}"
    
  72.     ),
    
  73.     "inheritance40": (
    
  74.         "{% extends 'inheritance33' %}{% block opt %}new{{ block.super }}{% endblock %}"
    
  75.     ),
    
  76.     "inheritance41": (
    
  77.         "{% extends 'inheritance36' %}{% block opt %}new{{ block.super }}{% endblock %}"
    
  78.     ),
    
  79.     "inheritance42": "{% extends 'inheritance02'|cut:' ' %}",
    
  80.     "inheritance_empty": "{% extends %}",
    
  81.     "extends_duplicate": "{% extends 'base.html' %}{% extends 'base.html' %}",
    
  82.     "duplicate_block": (
    
  83.         "{% extends 'base.html' %}{% block content %}2{% endblock %}{% block content %}"
    
  84.         "4{% endblock %}"
    
  85.     ),
    
  86. }
    
  87. 
    
  88. 
    
  89. class InheritanceTests(SimpleTestCase):
    
  90.     libraries = {"testtags": "template_tests.templatetags.testtags"}
    
  91. 
    
  92.     @setup(inheritance_templates)
    
  93.     def test_inheritance01(self):
    
  94.         """
    
  95.         Standard template with no inheritance
    
  96.         """
    
  97.         output = self.engine.render_to_string("inheritance01")
    
  98.         self.assertEqual(output, "1&3_")
    
  99. 
    
  100.     @setup(inheritance_templates)
    
  101.     def test_inheritance02(self):
    
  102.         """
    
  103.         Standard two-level inheritance
    
  104.         """
    
  105.         output = self.engine.render_to_string("inheritance02")
    
  106.         self.assertEqual(output, "1234")
    
  107. 
    
  108.     @setup(inheritance_templates)
    
  109.     def test_inheritance03(self):
    
  110.         """
    
  111.         Three-level with no redefinitions on third level
    
  112.         """
    
  113.         output = self.engine.render_to_string("inheritance03")
    
  114.         self.assertEqual(output, "1234")
    
  115. 
    
  116.     @setup(inheritance_templates)
    
  117.     def test_inheritance04(self):
    
  118.         """
    
  119.         Two-level with no redefinitions on second level
    
  120.         """
    
  121.         output = self.engine.render_to_string("inheritance04")
    
  122.         self.assertEqual(output, "1&3_")
    
  123. 
    
  124.     @setup(inheritance_templates)
    
  125.     def test_inheritance05(self):
    
  126.         """
    
  127.         Two-level with double quotes instead of single quotes
    
  128.         """
    
  129.         output = self.engine.render_to_string("inheritance05")
    
  130.         self.assertEqual(output, "1234")
    
  131. 
    
  132.     @setup(inheritance_templates)
    
  133.     def test_inheritance06(self):
    
  134.         """
    
  135.         Three-level with variable parent-template name
    
  136.         """
    
  137.         output = self.engine.render_to_string("inheritance06", {"foo": "inheritance02"})
    
  138.         self.assertEqual(output, "1234")
    
  139. 
    
  140.     @setup(inheritance_templates)
    
  141.     def test_inheritance07(self):
    
  142.         """
    
  143.         Two-level with one block defined, one block not defined
    
  144.         """
    
  145.         output = self.engine.render_to_string("inheritance07")
    
  146.         self.assertEqual(output, "1&35")
    
  147. 
    
  148.     @setup(inheritance_templates)
    
  149.     def test_inheritance08(self):
    
  150.         """
    
  151.         Three-level with one block defined on this level, two blocks
    
  152.         defined next level
    
  153.         """
    
  154.         output = self.engine.render_to_string("inheritance08")
    
  155.         self.assertEqual(output, "1235")
    
  156. 
    
  157.     @setup(inheritance_templates)
    
  158.     def test_inheritance09(self):
    
  159.         """
    
  160.         Three-level with second and third levels blank
    
  161.         """
    
  162.         output = self.engine.render_to_string("inheritance09")
    
  163.         self.assertEqual(output, "1&3_")
    
  164. 
    
  165.     @setup(inheritance_templates)
    
  166.     def test_inheritance10(self):
    
  167.         """
    
  168.         Three-level with space NOT in a block -- should be ignored
    
  169.         """
    
  170.         output = self.engine.render_to_string("inheritance10")
    
  171.         self.assertEqual(output, "1&3_")
    
  172. 
    
  173.     @setup(inheritance_templates)
    
  174.     def test_inheritance11(self):
    
  175.         """
    
  176.         Three-level with both blocks defined on this level, but none on
    
  177.         second level
    
  178.         """
    
  179.         output = self.engine.render_to_string("inheritance11")
    
  180.         self.assertEqual(output, "1234")
    
  181. 
    
  182.     @setup(inheritance_templates)
    
  183.     def test_inheritance12(self):
    
  184.         """
    
  185.         Three-level with this level providing one and second level
    
  186.         providing the other
    
  187.         """
    
  188.         output = self.engine.render_to_string("inheritance12")
    
  189.         self.assertEqual(output, "1235")
    
  190. 
    
  191.     @setup(inheritance_templates)
    
  192.     def test_inheritance13(self):
    
  193.         """
    
  194.         Three-level with this level overriding second level
    
  195.         """
    
  196.         output = self.engine.render_to_string("inheritance13")
    
  197.         self.assertEqual(output, "1a3b")
    
  198. 
    
  199.     @setup(inheritance_templates)
    
  200.     def test_inheritance14(self):
    
  201.         """
    
  202.         A block defined only in a child template shouldn't be displayed
    
  203.         """
    
  204.         output = self.engine.render_to_string("inheritance14")
    
  205.         self.assertEqual(output, "1&3_")
    
  206. 
    
  207.     @setup(inheritance_templates)
    
  208.     def test_inheritance15(self):
    
  209.         """
    
  210.         A block within another block
    
  211.         """
    
  212.         output = self.engine.render_to_string("inheritance15")
    
  213.         self.assertEqual(output, "12inner3_")
    
  214. 
    
  215.     @setup(inheritance_templates)
    
  216.     def test_inheritance16(self):
    
  217.         """
    
  218.         A block within another block (level 2)
    
  219.         """
    
  220.         output = self.engine.render_to_string("inheritance16")
    
  221.         self.assertEqual(output, "12out3_")
    
  222. 
    
  223.     @setup(inheritance_templates)
    
  224.     def test_inheritance17(self):
    
  225.         """
    
  226.         {% load %} tag (parent -- setup for exception04)
    
  227.         """
    
  228.         output = self.engine.render_to_string("inheritance17")
    
  229.         self.assertEqual(output, "1234")
    
  230. 
    
  231.     @setup(inheritance_templates)
    
  232.     def test_inheritance18(self):
    
  233.         """
    
  234.         {% load %} tag (standard usage, without inheritance)
    
  235.         """
    
  236.         output = self.engine.render_to_string("inheritance18")
    
  237.         self.assertEqual(output, "this that theother5678")
    
  238. 
    
  239.     @setup(inheritance_templates)
    
  240.     def test_inheritance19(self):
    
  241.         """
    
  242.         {% load %} tag (within a child template)
    
  243.         """
    
  244.         output = self.engine.render_to_string("inheritance19")
    
  245.         self.assertEqual(output, "140056783_")
    
  246. 
    
  247.     @setup(inheritance_templates)
    
  248.     def test_inheritance20(self):
    
  249.         """
    
  250.         Two-level inheritance with {{ block.super }}
    
  251.         """
    
  252.         output = self.engine.render_to_string("inheritance20")
    
  253.         self.assertEqual(output, "1&a3_")
    
  254. 
    
  255.     @setup(inheritance_templates)
    
  256.     def test_inheritance21(self):
    
  257.         """
    
  258.         Three-level inheritance with {{ block.super }} from parent
    
  259.         """
    
  260.         output = self.engine.render_to_string("inheritance21")
    
  261.         self.assertEqual(output, "12a34")
    
  262. 
    
  263.     @setup(inheritance_templates)
    
  264.     def test_inheritance22(self):
    
  265.         """
    
  266.         Three-level inheritance with {{ block.super }} from grandparent
    
  267.         """
    
  268.         output = self.engine.render_to_string("inheritance22")
    
  269.         self.assertEqual(output, "1&a3_")
    
  270. 
    
  271.     @setup(inheritance_templates)
    
  272.     def test_inheritance23(self):
    
  273.         """
    
  274.         Three-level inheritance with {{ block.super }} from parent and
    
  275.         grandparent
    
  276.         """
    
  277.         output = self.engine.render_to_string("inheritance23")
    
  278.         self.assertEqual(output, "1&ab3_")
    
  279. 
    
  280.     @setup(inheritance_templates)
    
  281.     def test_inheritance24(self):
    
  282.         """
    
  283.         Inheritance from local context without use of template loader
    
  284.         """
    
  285.         context_template = self.engine.from_string(
    
  286.             "1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}"
    
  287.         )
    
  288.         output = self.engine.render_to_string(
    
  289.             "inheritance24", {"context_template": context_template}
    
  290.         )
    
  291.         self.assertEqual(output, "1234")
    
  292. 
    
  293.     @setup(inheritance_templates)
    
  294.     def test_inheritance25(self):
    
  295.         """
    
  296.         Inheritance from local context with variable parent template
    
  297.         """
    
  298.         context_template = [
    
  299.             self.engine.from_string("Wrong"),
    
  300.             self.engine.from_string(
    
  301.                 "1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}"
    
  302.             ),
    
  303.         ]
    
  304.         output = self.engine.render_to_string(
    
  305.             "inheritance25", {"context_template": context_template}
    
  306.         )
    
  307.         self.assertEqual(output, "1234")
    
  308. 
    
  309.     @setup(inheritance_templates)
    
  310.     def test_inheritance26(self):
    
  311.         """
    
  312.         Set up a base template to extend
    
  313.         """
    
  314.         output = self.engine.render_to_string("inheritance26")
    
  315.         self.assertEqual(output, "no tags")
    
  316. 
    
  317.     @setup(inheritance_templates)
    
  318.     def test_inheritance27(self):
    
  319.         """
    
  320.         Inheritance from a template that doesn't have any blocks
    
  321.         """
    
  322.         output = self.engine.render_to_string("inheritance27")
    
  323.         self.assertEqual(output, "no tags")
    
  324. 
    
  325.     @setup(inheritance_templates)
    
  326.     def test_inheritance_28(self):
    
  327.         """
    
  328.         Set up a base template with a space in it.
    
  329.         """
    
  330.         output = self.engine.render_to_string("inheritance 28")
    
  331.         self.assertEqual(output, "!")
    
  332. 
    
  333.     @setup(inheritance_templates)
    
  334.     def test_inheritance29(self):
    
  335.         """
    
  336.         Inheritance from a template with a space in its name should work.
    
  337.         """
    
  338.         output = self.engine.render_to_string("inheritance29")
    
  339.         self.assertEqual(output, "!")
    
  340. 
    
  341.     @setup(inheritance_templates)
    
  342.     def test_inheritance30(self):
    
  343.         """
    
  344.         Base template, putting block in a conditional {% if %} tag
    
  345.         """
    
  346.         output = self.engine.render_to_string("inheritance30", {"optional": True})
    
  347.         self.assertEqual(output, "123")
    
  348. 
    
  349.     # Inherit from a template with block wrapped in an {% if %} tag
    
  350.     # (in parent), still gets overridden
    
  351.     @setup(inheritance_templates)
    
  352.     def test_inheritance31(self):
    
  353.         output = self.engine.render_to_string("inheritance31", {"optional": True})
    
  354.         self.assertEqual(output, "1two3")
    
  355. 
    
  356.     @setup(inheritance_templates)
    
  357.     def test_inheritance32(self):
    
  358.         output = self.engine.render_to_string("inheritance32")
    
  359.         self.assertEqual(output, "13")
    
  360. 
    
  361.     @setup(inheritance_templates)
    
  362.     def test_inheritance33(self):
    
  363.         """
    
  364.         Base template, putting block in a conditional {% if %} tag
    
  365.         """
    
  366.         output = self.engine.render_to_string("inheritance33", {"optional": 1})
    
  367.         self.assertEqual(output, "123")
    
  368. 
    
  369.     @setup(inheritance_templates)
    
  370.     def test_inheritance34(self):
    
  371.         """
    
  372.         Inherit from a template with block wrapped in an {% if %} tag
    
  373.         (in parent), still gets overridden
    
  374.         """
    
  375.         output = self.engine.render_to_string("inheritance34", {"optional": 1})
    
  376.         self.assertEqual(output, "1two3")
    
  377. 
    
  378.     @setup(inheritance_templates)
    
  379.     def test_inheritance35(self):
    
  380.         """
    
  381.         Inherit from a template with block wrapped in an {% if %} tag
    
  382.         (in parent), still gets overridden
    
  383.         """
    
  384.         output = self.engine.render_to_string("inheritance35", {"optional": 2})
    
  385.         self.assertEqual(output, "13")
    
  386. 
    
  387.     @setup(inheritance_templates)
    
  388.     def test_inheritance36(self):
    
  389.         """
    
  390.         Base template, putting block in a {% for %} tag
    
  391.         """
    
  392.         output = self.engine.render_to_string("inheritance36", {"numbers": "123"})
    
  393.         self.assertEqual(output, "_1_2_3_")
    
  394. 
    
  395.     @setup(inheritance_templates)
    
  396.     def test_inheritance37(self):
    
  397.         """
    
  398.         Inherit from a template with block wrapped in an {% for %} tag
    
  399.         (in parent), still gets overridden
    
  400.         """
    
  401.         output = self.engine.render_to_string("inheritance37", {"numbers": "123"})
    
  402.         self.assertEqual(output, "_X_X_X_")
    
  403. 
    
  404.     @setup(inheritance_templates)
    
  405.     def test_inheritance38(self):
    
  406.         """
    
  407.         Inherit from a template with block wrapped in an {% for %} tag
    
  408.         (in parent), still gets overridden
    
  409.         """
    
  410.         output = self.engine.render_to_string("inheritance38")
    
  411.         self.assertEqual(output, "_")
    
  412. 
    
  413.     # The super block will still be found.
    
  414.     @setup(inheritance_templates)
    
  415.     def test_inheritance39(self):
    
  416.         output = self.engine.render_to_string("inheritance39", {"optional": True})
    
  417.         self.assertEqual(output, "1new23")
    
  418. 
    
  419.     @setup(inheritance_templates)
    
  420.     def test_inheritance40(self):
    
  421.         output = self.engine.render_to_string("inheritance40", {"optional": 1})
    
  422.         self.assertEqual(output, "1new23")
    
  423. 
    
  424.     @setup(inheritance_templates)
    
  425.     def test_inheritance41(self):
    
  426.         output = self.engine.render_to_string("inheritance41", {"numbers": "123"})
    
  427.         self.assertEqual(output, "_new1_new2_new3_")
    
  428. 
    
  429.     @setup(inheritance_templates)
    
  430.     def test_inheritance42(self):
    
  431.         """
    
  432.         Expression starting and ending with a quote
    
  433.         """
    
  434.         output = self.engine.render_to_string("inheritance42")
    
  435.         self.assertEqual(output, "1234")
    
  436. 
    
  437.     @setup(inheritance_templates)
    
  438.     def test_inheritance_empty(self):
    
  439.         with self.assertRaisesMessage(
    
  440.             TemplateSyntaxError, "'extends' takes one argument"
    
  441.         ):
    
  442.             self.engine.render_to_string("inheritance_empty")
    
  443. 
    
  444.     @setup(inheritance_templates)
    
  445.     def test_extends_duplicate(self):
    
  446.         msg = "'extends' cannot appear more than once in the same template"
    
  447.         with self.assertRaisesMessage(TemplateSyntaxError, msg):
    
  448.             self.engine.render_to_string("extends_duplicate")
    
  449. 
    
  450.     @setup(inheritance_templates)
    
  451.     def test_duplicate_block(self):
    
  452.         msg = "'block' tag with name 'content' appears more than once"
    
  453.         with self.assertRaisesMessage(TemplateSyntaxError, msg):
    
  454.             self.engine.render_to_string("duplicate_block")
    
  455. 
    
  456. 
    
  457. class ExtendsNodeTests(SimpleTestCase):
    
  458.     def test_extends_node_repr(self):
    
  459.         extends_node = ExtendsNode(
    
  460.             nodelist=NodeList([]),
    
  461.             parent_name=Node(),
    
  462.             template_dirs=[],
    
  463.         )
    
  464.         self.assertEqual(repr(extends_node), "<ExtendsNode: extends None>")