From b39b9e38fbf76288624846e1a29a99074db7e627 Mon Sep 17 00:00:00 2001 From: David Kerkeslager Date: Fri, 14 Apr 2017 11:46:42 -0400 Subject: [PATCH] Parse constants and integers with leading whitespace --- don/string.py | 19 +++++++++++++++---- test_don.py | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/don/string.py b/don/string.py index e22b328..1e930ac 100644 --- a/don/string.py +++ b/don/string.py @@ -1,5 +1,6 @@ import binascii import collections +import functools import re from don import tags, _shared @@ -60,8 +61,17 @@ def serialize(o): return _STRING_SERIALIZERS[o.tag](o.value) -def _make_constant_parser(constant, value): +def _consume_leading_whitespace(wrapped_parser): + @functools.wraps(wrapped_parser) def parser(s): + s = s.lstrip() + return wrapped_parser(s) + + return parser + +def _make_constant_parser(constant, value): + @_consume_leading_whitespace + def constant_parser(s): if s.startswith(constant): result = _shared.ParseResult( success = True, @@ -72,12 +82,13 @@ def _make_constant_parser(constant, value): return _shared._FAILED_PARSE_RESULT - return parser + return constant_parser def _make_integer_parser(width): matcher = re.compile(r'(-?\d+)i' + str(width)) - def parser(s): + @_consume_leading_whitespace + def integer_parser(s): match = matcher.match(s) if match: @@ -90,7 +101,7 @@ def _make_integer_parser(width): return _shared._FAILED_PARSE_RESULT - return parser + return integer_parser _BINARY32_MATCHER = re.compile(r'(-?\d+\.\d+)f') _BINARY64_MATCHER = re.compile(r'(-?\d+\.\d+)d') diff --git a/test_don.py b/test_don.py index c4e9549..df62ff5 100644 --- a/test_don.py +++ b/test_don.py @@ -180,34 +180,68 @@ class TestStringDeserialize(unittest.TestCase): string.deserialize('null'), ) - def test_deserializes_null(self): + def test_deserializes_null_with_leading_whitespace(self): + self.assertEqual( + None, + string.deserialize(' \t\nnull'), + ) + + def test_deserializes_true(self): self.assertEqual( True, string.deserialize('true'), ) - def test_deserializes_null(self): + def test_deserializes_true_with_leading_whitespace(self): + self.assertEqual( + True, + string.deserialize(' \t\ntrue'), + ) + + def test_deserializes_false(self): self.assertEqual( False, string.deserialize('false'), ) + def test_deserializes_false_with_leading_whitespace(self): + self.assertEqual( + False, + string.deserialize(' \t\nfalse'), + ) + def test_deserializes_int8(self): self.assertEqual(10, string.deserialize('10i8')) self.assertEqual(-1, string.deserialize('-1i8')) + def test_deserializes_int8_with_leading_whitespace(self): + self.assertEqual(10, string.deserialize(' \t\n10i8')) + self.assertEqual(-1, string.deserialize(' \t\n-1i8')) + def test_deserializes_int16(self): self.assertEqual(10, string.deserialize('10i16')) self.assertEqual(-1, string.deserialize('-1i16')) + def test_deserializes_int16_with_leading_whitespace(self): + self.assertEqual(10, string.deserialize(' \t\n10i16')) + self.assertEqual(-1, string.deserialize(' \t\n-1i16')) + def test_deserializes_int32(self): self.assertEqual(10, string.deserialize('10i32')) self.assertEqual(-1, string.deserialize('-1i32')) + def test_deserializes_int32_with_leading_whitespace(self): + self.assertEqual(10, string.deserialize(' \t\n10i32')) + self.assertEqual(-1, string.deserialize(' \t\n-1i32')) + def test_deserializes_int64(self): self.assertEqual(10, string.deserialize('10i64')) self.assertEqual(-1, string.deserialize('-1i64')) + def test_deserializes_int64_with_leading_whitespace(self): + self.assertEqual(10, string.deserialize(' \t\n10i64')) + self.assertEqual(-1, string.deserialize(' \t\n-1i64')) + def test_deserializes_float(self): self.assertEqual(1.0, string.deserialize('1.0f')) -- 2.20.1