1. """
    
  2. Testing some internals of the template processing.
    
  3. These are *not* examples to be copied in user code.
    
  4. """
    
  5. from django.template import Library, TemplateSyntaxError
    
  6. from django.template.base import (
    
  7.     FilterExpression,
    
  8.     Lexer,
    
  9.     Parser,
    
  10.     Token,
    
  11.     TokenType,
    
  12.     Variable,
    
  13. )
    
  14. from django.template.defaultfilters import register as filter_library
    
  15. from django.test import SimpleTestCase
    
  16. 
    
  17. 
    
  18. class ParserTests(SimpleTestCase):
    
  19.     def test_token_smart_split(self):
    
  20.         """
    
  21.         #7027 -- _() syntax should work with spaces
    
  22.         """
    
  23.         token = Token(
    
  24.             TokenType.BLOCK, 'sometag _("Page not found") value|yesno:_("yes,no")'
    
  25.         )
    
  26.         split = token.split_contents()
    
  27.         self.assertEqual(
    
  28.             split, ["sometag", '_("Page not found")', 'value|yesno:_("yes,no")']
    
  29.         )
    
  30. 
    
  31.     def test_repr(self):
    
  32.         token = Token(TokenType.BLOCK, "some text")
    
  33.         self.assertEqual(repr(token), '<Block token: "some text...">')
    
  34.         parser = Parser([token], builtins=[filter_library])
    
  35.         self.assertEqual(
    
  36.             repr(parser),
    
  37.             '<Parser tokens=[<Block token: "some text...">]>',
    
  38.         )
    
  39.         filter_expression = FilterExpression("news|upper", parser)
    
  40.         self.assertEqual(repr(filter_expression), "<FilterExpression 'news|upper'>")
    
  41.         lexer = Lexer("{% for i in 1 %}{{ a }}\n{% endfor %}")
    
  42.         self.assertEqual(
    
  43.             repr(lexer),
    
  44.             '<Lexer template_string="{% for i in 1 %}{{ a...", verbatim=False>',
    
  45.         )
    
  46. 
    
  47.     def test_filter_parsing(self):
    
  48.         c = {"article": {"section": "News"}}
    
  49.         p = Parser("", builtins=[filter_library])
    
  50. 
    
  51.         def fe_test(s, val):
    
  52.             self.assertEqual(FilterExpression(s, p).resolve(c), val)
    
  53. 
    
  54.         fe_test("article.section", "News")
    
  55.         fe_test("article.section|upper", "NEWS")
    
  56.         fe_test('"News"', "News")
    
  57.         fe_test("'News'", "News")
    
  58.         fe_test(r'"Some \"Good\" News"', 'Some "Good" News')
    
  59.         fe_test(r'"Some \"Good\" News"', 'Some "Good" News')
    
  60.         fe_test(r"'Some \'Bad\' News'", "Some 'Bad' News")
    
  61. 
    
  62.         fe = FilterExpression(r'"Some \"Good\" News"', p)
    
  63.         self.assertEqual(fe.filters, [])
    
  64.         self.assertEqual(fe.var, 'Some "Good" News')
    
  65. 
    
  66.         # Filtered variables should reject access of attributes beginning with
    
  67.         # underscores.
    
  68.         msg = (
    
  69.             "Variables and attributes may not begin with underscores: 'article._hidden'"
    
  70.         )
    
  71.         with self.assertRaisesMessage(TemplateSyntaxError, msg):
    
  72.             FilterExpression("article._hidden|upper", p)
    
  73. 
    
  74.     def test_variable_parsing(self):
    
  75.         c = {"article": {"section": "News"}}
    
  76.         self.assertEqual(Variable("article.section").resolve(c), "News")
    
  77.         self.assertEqual(Variable('"News"').resolve(c), "News")
    
  78.         self.assertEqual(Variable("'News'").resolve(c), "News")
    
  79. 
    
  80.         # Translated strings are handled correctly.
    
  81.         self.assertEqual(Variable("_(article.section)").resolve(c), "News")
    
  82.         self.assertEqual(Variable('_("Good News")').resolve(c), "Good News")
    
  83.         self.assertEqual(Variable("_('Better News')").resolve(c), "Better News")
    
  84. 
    
  85.         # Escaped quotes work correctly as well.
    
  86.         self.assertEqual(
    
  87.             Variable(r'"Some \"Good\" News"').resolve(c), 'Some "Good" News'
    
  88.         )
    
  89.         self.assertEqual(
    
  90.             Variable(r"'Some \'Better\' News'").resolve(c), "Some 'Better' News"
    
  91.         )
    
  92. 
    
  93.         # Variables should reject access of attributes and variables beginning
    
  94.         # with underscores.
    
  95.         for name in ["article._hidden", "_article"]:
    
  96.             msg = f"Variables and attributes may not begin with underscores: '{name}'"
    
  97.             with self.assertRaisesMessage(TemplateSyntaxError, msg):
    
  98.                 Variable(name)
    
  99. 
    
  100.         # Variables should raise on non string type
    
  101.         with self.assertRaisesMessage(
    
  102.             TypeError, "Variable must be a string or number, got <class 'dict'>"
    
  103.         ):
    
  104.             Variable({})
    
  105. 
    
  106.     def test_filter_args_count(self):
    
  107.         parser = Parser("")
    
  108.         register = Library()
    
  109. 
    
  110.         @register.filter
    
  111.         def no_arguments(value):
    
  112.             pass
    
  113. 
    
  114.         @register.filter
    
  115.         def one_argument(value, arg):
    
  116.             pass
    
  117. 
    
  118.         @register.filter
    
  119.         def one_opt_argument(value, arg=False):
    
  120.             pass
    
  121. 
    
  122.         @register.filter
    
  123.         def two_arguments(value, arg, arg2):
    
  124.             pass
    
  125. 
    
  126.         @register.filter
    
  127.         def two_one_opt_arg(value, arg, arg2=False):
    
  128.             pass
    
  129. 
    
  130.         parser.add_library(register)
    
  131.         for expr in (
    
  132.             '1|no_arguments:"1"',
    
  133.             "1|two_arguments",
    
  134.             '1|two_arguments:"1"',
    
  135.             "1|two_one_opt_arg",
    
  136.         ):
    
  137.             with self.assertRaises(TemplateSyntaxError):
    
  138.                 FilterExpression(expr, parser)
    
  139.         for expr in (
    
  140.             # Correct number of arguments
    
  141.             "1|no_arguments",
    
  142.             '1|one_argument:"1"',
    
  143.             # One optional
    
  144.             "1|one_opt_argument",
    
  145.             '1|one_opt_argument:"1"',
    
  146.             # Not supplying all
    
  147.             '1|two_one_opt_arg:"1"',
    
  148.         ):
    
  149.             FilterExpression(expr, parser)