test_parser.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. """
  2. Testing some internals of the template processing. These are *not* examples to be copied in user code.
  3. """
  4. from __future__ import unicode_literals
  5. from unittest import TestCase
  6. from django.template import Library, Template, TemplateSyntaxError
  7. from django.template.base import FilterExpression, Parser, TokenParser, Variable
  8. from django.test import override_settings
  9. from django.utils import six
  10. class ParserTests(TestCase):
  11. def test_token_parsing(self):
  12. # Tests for TokenParser behavior in the face of quoted strings with
  13. # spaces.
  14. p = TokenParser("tag thevar|filter sometag")
  15. self.assertEqual(p.tagname, "tag")
  16. self.assertEqual(p.value(), "thevar|filter")
  17. self.assertTrue(p.more())
  18. self.assertEqual(p.tag(), "sometag")
  19. self.assertFalse(p.more())
  20. p = TokenParser('tag "a value"|filter sometag')
  21. self.assertEqual(p.tagname, "tag")
  22. self.assertEqual(p.value(), '"a value"|filter')
  23. self.assertTrue(p.more())
  24. self.assertEqual(p.tag(), "sometag")
  25. self.assertFalse(p.more())
  26. p = TokenParser("tag 'a value'|filter sometag")
  27. self.assertEqual(p.tagname, "tag")
  28. self.assertEqual(p.value(), "'a value'|filter")
  29. self.assertTrue(p.more())
  30. self.assertEqual(p.tag(), "sometag")
  31. self.assertFalse(p.more())
  32. def test_filter_parsing(self):
  33. c = {"article": {"section": "News"}}
  34. p = Parser("")
  35. def fe_test(s, val):
  36. self.assertEqual(FilterExpression(s, p).resolve(c), val)
  37. fe_test("article.section", "News")
  38. fe_test("article.section|upper", "NEWS")
  39. fe_test('"News"', "News")
  40. fe_test("'News'", "News")
  41. fe_test(r'"Some \"Good\" News"', 'Some "Good" News')
  42. fe_test(r'"Some \"Good\" News"', 'Some "Good" News')
  43. fe_test(r"'Some \'Bad\' News'", "Some 'Bad' News")
  44. fe = FilterExpression(r'"Some \"Good\" News"', p)
  45. self.assertEqual(fe.filters, [])
  46. self.assertEqual(fe.var, 'Some "Good" News')
  47. # Filtered variables should reject access of attributes beginning with
  48. # underscores.
  49. self.assertRaises(TemplateSyntaxError, FilterExpression, "article._hidden|upper", p)
  50. def test_variable_parsing(self):
  51. c = {"article": {"section": "News"}}
  52. self.assertEqual(Variable("article.section").resolve(c), "News")
  53. self.assertEqual(Variable('"News"').resolve(c), "News")
  54. self.assertEqual(Variable("'News'").resolve(c), "News")
  55. # Translated strings are handled correctly.
  56. self.assertEqual(Variable("_(article.section)").resolve(c), "News")
  57. self.assertEqual(Variable('_("Good News")').resolve(c), "Good News")
  58. self.assertEqual(Variable("_('Better News')").resolve(c), "Better News")
  59. # Escaped quotes work correctly as well.
  60. self.assertEqual(
  61. Variable(r'"Some \"Good\" News"').resolve(c), 'Some "Good" News'
  62. )
  63. self.assertEqual(
  64. Variable(r"'Some \'Better\' News'").resolve(c), "Some 'Better' News"
  65. )
  66. # Variables should reject access of attributes beginning with
  67. # underscores.
  68. self.assertRaises(TemplateSyntaxError, Variable, "article._hidden")
  69. # Variables should raise on non string type
  70. with six.assertRaisesRegex(self, TypeError, "Variable must be a string or number, got <(class|type) 'dict'>"):
  71. Variable({})
  72. @override_settings(DEBUG=True, TEMPLATE_DEBUG=True)
  73. def test_compile_filter_error(self):
  74. # regression test for #19819
  75. msg = "Could not parse the remainder: '@bar' from 'foo@bar'"
  76. with six.assertRaisesRegex(self, TemplateSyntaxError, msg) as cm:
  77. Template("{% if 1 %}{{ foo@bar }}{% endif %}")
  78. self.assertEqual(cm.exception.django_template_source[1], (10, 23))
  79. def test_filter_args_count(self):
  80. p = Parser("")
  81. l = Library()
  82. @l.filter
  83. def no_arguments(value):
  84. pass
  85. @l.filter
  86. def one_argument(value, arg):
  87. pass
  88. @l.filter
  89. def one_opt_argument(value, arg=False):
  90. pass
  91. @l.filter
  92. def two_arguments(value, arg, arg2):
  93. pass
  94. @l.filter
  95. def two_one_opt_arg(value, arg, arg2=False):
  96. pass
  97. p.add_library(l)
  98. for expr in (
  99. '1|no_arguments:"1"',
  100. '1|two_arguments',
  101. '1|two_arguments:"1"',
  102. '1|two_one_opt_arg',
  103. ):
  104. with self.assertRaises(TemplateSyntaxError):
  105. FilterExpression(expr, p)
  106. for expr in (
  107. # Correct number of arguments
  108. '1|no_arguments',
  109. '1|one_argument:"1"',
  110. # One optional
  111. '1|one_opt_argument',
  112. '1|one_opt_argument:"1"',
  113. # Not supplying all
  114. '1|two_one_opt_arg:"1"',
  115. ):
  116. FilterExpression(expr, p)