diff options
author | Paul McGuire <ptmcg@austin.rr.com> | 2019-08-26 10:53:50 -0500 |
---|---|---|
committer | Paul McGuire <ptmcg@austin.rr.com> | 2019-08-26 10:53:50 -0500 |
commit | 6a899ffd880d7937e6e8fd540552c65f945dce53 (patch) | |
tree | bb1e4663b0bdc1cf07993533c5a52c484d2f3062 | |
parent | 84a12454849a69ca827c64869b65266d6df4c72a (diff) | |
download | pyparsing-git-6a899ffd880d7937e6e8fd540552c65f945dce53.tar.gz |
Fixed bug when ZeroOrMore parses no matching exprs, did not include a named result containing []
-rw-r--r-- | CHANGES | 11 | ||||
-rw-r--r-- | pyparsing.py | 4 | ||||
-rw-r--r-- | unitTests.py | 68 |
3 files changed, 81 insertions, 2 deletions
@@ -33,6 +33,17 @@ Version 3.0.0a1 to help identify those expressions in your parsers that will have changed as a result. +- POTENTIAL API CHANGE: + ZeroOrMore expressions that have results names will now + include empty lists for their name if no matches are found. + Previously, no named result would be present. Code that tested + for the presence of any expressions using "if name in results:" + will now always return True. This code will need to change to + "if name in results and results[name]:" or just + "if results[name]:". Also, any parser unit tests that check the + asDict() contents will now see additional entries for parsers + having named ZeroOrMore expressions, whose values will be `[]`. + - Expanded __diag__ and __compat__ to actual classes instead of just namespaces, to add some helpful behavior: - enable() and .disable() methods to give extra diff --git a/pyparsing.py b/pyparsing.py index c2f1f5a..31a1560 100644 --- a/pyparsing.py +++ b/pyparsing.py @@ -96,7 +96,7 @@ classes inherit from. Use the docstrings for examples of how to: """ __version__ = "3.0.0a1" -__versionTime__ = "26 Aug 2019 01:46 UTC" +__versionTime__ = "26 Aug 2019 11:15 UTC" __author__ = "Paul McGuire <ptmcg@users.sourceforge.net>" import string @@ -4615,7 +4615,7 @@ class ZeroOrMore(_MultipleMatch): try: return super().parseImpl(instring, loc, doActions) except (ParseException, IndexError): - return loc, [] + return loc, ParseResults([], name=self.resultsName) def __str__(self): if hasattr(self, "name"): diff --git a/unitTests.py b/unitTests.py index 4effa89..11ebcc3 100644 --- a/unitTests.py +++ b/unitTests.py @@ -1125,6 +1125,74 @@ class EllipsisRepetionTest(ParseTestCase): self.assertTrue(all_success, "failed getItem_ellipsis test") +class EllipsisRepetionWithResultsNamesTest(ParseTestCase): + def runTest(self): + import pyparsing as pp + + label = pp.Word(pp.alphas) + val = pp.pyparsing_common.integer() + parser = label('label') + pp.ZeroOrMore(val)('values') + + _, results = parser.runTests(""" + a 1 + b 1 2 3 + c + """) + expected = [ + (['a', 1], {'label': 'a', 'values': [1]}), + (['b', 1, 2, 3], {'label': 'b', 'values': [1, 2, 3]}), + (['c'], {'label': 'c', 'values': []}), + ] + for obs, exp in zip(results, expected): + test, result = obs + exp_list, exp_dict = exp + self.assertEqual(result.asList(), exp_list, + "list mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_list, result.asList())) + self.assertEqual(result.asDict(), exp_dict, + "dict mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_dict, result.asDict())) + + parser = label('label') + val[...]('values') + + _, results = parser.runTests(""" + a 1 + b 1 2 3 + c + """) + expected = [ + (['a', 1], {'label': 'a', 'values': [1]}), + (['b', 1, 2, 3], {'label': 'b', 'values': [1, 2, 3]}), + (['c'], {'label': 'c', 'values': []}), + ] + for obs, exp in zip(results, expected): + test, result = obs + exp_list, exp_dict = exp + self.assertEqual(result.asList(), exp_list, + "list mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_list, result.asList())) + self.assertEqual(result.asDict(), exp_dict, + "dict mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_dict, result.asDict())) + + pt = pp.Group(val('x') + pp.Suppress(',') + val('y')) + parser = label('label') + pt[...]("points") + _, results = parser.runTests(""" + a 1,1 + b 1,1 2,2 3,3 + c + """) + expected = [ + (['a', [1, 1]], {'label': 'a', 'points': [{'x': 1, 'y': 1}]}), + (['b', [1, 1], [2, 2], [3, 3]], {'label': 'b', 'points': [{'x': 1, 'y': 1}, + {'x': 2, 'y': 2}, + {'x': 3, 'y': 3}]}), + (['c'], {'label': 'c', 'points': []}), + ] + for obs, exp in zip(results, expected): + test, result = obs + exp_list, exp_dict = exp + self.assertEqual(result.asList(), exp_list, + "list mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_list, result.asList())) + self.assertEqual(result.asDict(), exp_dict, + "dict mismatch {!r}, expected {!r}, actual {!r}".format(test, exp_dict, result.asDict())) + class CustomQuotesTest(ParseTestCase): def runTest(self): |