summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorptmcg <ptmcg@austin.rr.com>2023-03-27 01:13:38 -0500
committerptmcg <ptmcg@austin.rr.com>2023-03-27 01:13:38 -0500
commit24b0b29ea9e6335a465711d3d6e157effeaf583e (patch)
tree6b569613c1ba565dd58c6ffe0a6a07a1f3628489
parent9d789cbc7331509862060c8b06ebca9fe9d827b2 (diff)
downloadpyparsing-git-24b0b29ea9e6335a465711d3d6e157effeaf583e.tar.gz
Fix #470 - Removed "" from the list of values that ParseResults will not save with a results name
-rw-r--r--CHANGES24
-rw-r--r--pyparsing/results.py2
-rw-r--r--tests/test_unit.py59
3 files changed, 77 insertions, 8 deletions
diff --git a/CHANGES b/CHANGES
index 2886034..a73e2c0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,15 +4,25 @@ Change Log
Version 3.1.0a2 - (in development)
----------------------------------
-Fixed bug in `SkipTo` where ignore expressions were not properly handled while
-scanning for the target expression. Issue #475, reported by elkniwt, thanks
-(this bug has been there for a looooong time!).
+- Fixed bug when parse actions returned an empty string for an expression that
+ had a results name, that the results name was not saved. That is:
-Updated ci.yml permissions to limit default access to source - submitted by Joyce
-Brum of Google. Thanks so much!
+ expr = Literal("X").add_parse_action(lambda tokens: "")("value")
+ result = expr.parse_string("X")
+ print(result["value"])
-Updated the lucene_grammar.py example (better support for '*' and '?' wildcards)
-and corrected the test cases - brought to my attention by Elijah Nicol, good catch!
+ would raise a `KeyError`. Now empty strings will be saved with the associated
+ results name. Raised in Issue #470 by Nicco Kunzmann, thank you.
+
+- Fixed bug in `SkipTo` where ignore expressions were not properly handled while
+ scanning for the target expression. Issue #475, reported by elkniwt, thanks
+ (this bug has been there for a looooong time!).
+
+- Updated ci.yml permissions to limit default access to source - submitted by Joyce
+ Brum of Google. Thanks so much!
+
+- Updated the lucene_grammar.py example (better support for '*' and '?' wildcards)
+ and corrected the test cases - brought to my attention by Elijah Nicol, good catch!
Version 3.1.0a1 - March, 2023
diff --git a/pyparsing/results.py b/pyparsing/results.py
index 1134456..92f89f4 100644
--- a/pyparsing/results.py
+++ b/pyparsing/results.py
@@ -77,7 +77,7 @@ class ParseResults:
- year: '1999'
"""
- _null_values: Tuple[Any, ...] = (None, [], "", ())
+ _null_values: Tuple[Any, ...] = (None, [], ())
_name: str
_parent: "ParseResults"
diff --git a/tests/test_unit.py b/tests/test_unit.py
index 0f1cb5a..8c98a3e 100644
--- a/tests/test_unit.py
+++ b/tests/test_unit.py
@@ -2754,6 +2754,65 @@ class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
with self.assertRaises(AttributeError):
result.__xyz__
+ def testParseResultsNamedResultWithEmptyString(self):
+ # from Issue #470
+
+ # Check which values can be returned from a parse action
+ for test_value, expected_in_result_by_name in [
+ ("x", True),
+ ("", True),
+ (True, True),
+ (False, True),
+ (1, True),
+ (0, True),
+ (None, True),
+ (b"", True),
+ (b"a", True),
+ ([], False),
+ ((), False),
+ ]:
+ msg = (f"value = {test_value!r},"
+ f" expected X {'not ' if not expected_in_result_by_name else ''}in result")
+ with self.subTest(msg):
+ print(msg)
+ grammar = ((pp.Suppress("a") + pp.ZeroOrMore("x"))
+ .add_parse_action(lambda p: test_value)
+ .set_results_name("X"))
+ result = grammar.parse_string("a")
+ print(result.dump())
+ if expected_in_result_by_name:
+ self.assertIn("X", result, f"Expected X not found for parse action value {test_value!r}")
+ print(repr(result["X"]))
+ else:
+ self.assertNotIn("X", result, f"Unexpected X found for parse action value {test_value!r}")
+ with self.assertRaises(KeyError):
+ print(repr(result["X"]))
+ print()
+
+ # Do not add a parse result.
+ msg = "value = <no parse action defined>, expected X in result"
+ with self.subTest(msg):
+ print(msg)
+ grammar = (pp.Suppress("a") + pp.ZeroOrMore("x")).set_results_name("X")
+ result = grammar.parse_string("a")
+ print(result.dump())
+ self.assertIn("X", result, f"Expected X not found with no parse action")
+ print()
+
+ # Test by directly creating a ParseResults
+ print("Create empty string value directly")
+ result = pp.ParseResults("", name="X")
+ print(result.dump())
+ self.assertIn("X", result, "failed to construct ParseResults with named value using empty string")
+ print(repr(result["X"]))
+ print()
+
+ print("Create empty string value from a dict")
+ result = pp.ParseResults.from_dict({"X": ""})
+ print(result.dump())
+ self.assertIn("X", result, "failed to construct ParseResults with named value using from_dict")
+ print(repr(result["X"]))
+
def testMatchOnlyAtCol(self):
"""successfully use matchOnlyAtCol helper function"""