summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul McGuire <ptmcg@austin.rr.com>2019-08-26 10:53:50 -0500
committerPaul McGuire <ptmcg@austin.rr.com>2019-08-26 10:53:50 -0500
commit6a899ffd880d7937e6e8fd540552c65f945dce53 (patch)
treebb1e4663b0bdc1cf07993533c5a52c484d2f3062
parent84a12454849a69ca827c64869b65266d6df4c72a (diff)
downloadpyparsing-git-6a899ffd880d7937e6e8fd540552c65f945dce53.tar.gz
Fixed bug when ZeroOrMore parses no matching exprs, did not include a named result containing []
-rw-r--r--CHANGES11
-rw-r--r--pyparsing.py4
-rw-r--r--unitTests.py68
3 files changed, 81 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 741e17c..48a34e1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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):