|
@@ -11,6 +11,7 @@ from django.template.base import (
|
|
|
Token,
|
|
|
TokenType,
|
|
|
Variable,
|
|
|
+ VariableDoesNotExist,
|
|
|
)
|
|
|
from django.template.defaultfilters import register as filter_library
|
|
|
from django.test import SimpleTestCase
|
|
@@ -72,6 +73,27 @@ class ParserTests(SimpleTestCase):
|
|
|
with self.assertRaisesMessage(TemplateSyntaxError, msg):
|
|
|
FilterExpression("article._hidden|upper", p)
|
|
|
|
|
|
+ def test_cannot_parse_characters(self):
|
|
|
+ p = Parser("", builtins=[filter_library])
|
|
|
+ for filter_expression, characters in [
|
|
|
+ ('<>|default:"Default"|upper', '|<>||default:"Default"|upper'),
|
|
|
+ ("test|<>|upper", "test||<>||upper"),
|
|
|
+ ]:
|
|
|
+ with self.subTest(filter_expression=filter_expression):
|
|
|
+ with self.assertRaisesMessage(
|
|
|
+ TemplateSyntaxError,
|
|
|
+ f"Could not parse some characters: {characters}",
|
|
|
+ ):
|
|
|
+ FilterExpression(filter_expression, p)
|
|
|
+
|
|
|
+ def test_cannot_find_variable(self):
|
|
|
+ p = Parser("", builtins=[filter_library])
|
|
|
+ with self.assertRaisesMessage(
|
|
|
+ TemplateSyntaxError,
|
|
|
+ 'Could not find variable at start of |default:"Default"',
|
|
|
+ ):
|
|
|
+ FilterExpression('|default:"Default"', p)
|
|
|
+
|
|
|
def test_variable_parsing(self):
|
|
|
c = {"article": {"section": "News"}}
|
|
|
self.assertEqual(Variable("article.section").resolve(c), "News")
|
|
@@ -148,3 +170,49 @@ class ParserTests(SimpleTestCase):
|
|
|
'1|two_one_opt_arg:"1"',
|
|
|
):
|
|
|
FilterExpression(expr, parser)
|
|
|
+
|
|
|
+ def test_filter_numeric_argument_parsing(self):
|
|
|
+ p = Parser("", builtins=[filter_library])
|
|
|
+
|
|
|
+ cases = {
|
|
|
+ "5": 5,
|
|
|
+ "-5": -5,
|
|
|
+ "5.2": 5.2,
|
|
|
+ ".4": 0.4,
|
|
|
+ "5.2e3": 5200.0, # 5.2 × 10³ = 5200.0.
|
|
|
+ "5.2E3": 5200.0, # Case-insensitive.
|
|
|
+ "5.2e-3": 0.0052, # Negative exponent.
|
|
|
+ "-1.5E4": -15000.0,
|
|
|
+ "+3.0e2": 300.0,
|
|
|
+ ".5e2": 50.0, # 0.5 × 10² = 50.0
|
|
|
+ }
|
|
|
+ for num, expected in cases.items():
|
|
|
+ with self.subTest(num=num):
|
|
|
+ self.assertEqual(FilterExpression(num, p).resolve({}), expected)
|
|
|
+ self.assertEqual(
|
|
|
+ FilterExpression(f"0|default:{num}", p).resolve({}), expected
|
|
|
+ )
|
|
|
+
|
|
|
+ invalid_numbers = [
|
|
|
+ "abc123",
|
|
|
+ "123abc",
|
|
|
+ "foo",
|
|
|
+ "error",
|
|
|
+ "1e",
|
|
|
+ "e400",
|
|
|
+ "1e.2",
|
|
|
+ "1e2.",
|
|
|
+ "1e2.0",
|
|
|
+ "1e2a",
|
|
|
+ "1e2e3",
|
|
|
+ "1e-",
|
|
|
+ "1e-a",
|
|
|
+ ]
|
|
|
+
|
|
|
+ for num in invalid_numbers:
|
|
|
+ with self.subTest(num=num):
|
|
|
+ self.assertIsNone(
|
|
|
+ FilterExpression(num, p).resolve({}, ignore_failures=True)
|
|
|
+ )
|
|
|
+ with self.assertRaises(VariableDoesNotExist):
|
|
|
+ FilterExpression(f"0|default:{num}", p).resolve({})
|