From 1bbc83267f33471f25b885c5376b65316a6d1968 Mon Sep 17 00:00:00 2001 From: ptmcg Date: Wed, 27 Oct 2021 12:57:15 -0500 Subject: [PATCH] Fix whitespace skipping bug introduced while reverting LineStart() changes - Issue #319 --- CHANGES | 4 ++++ pyparsing/core.py | 9 +++++---- tests/test_unit.py | 23 +++++++++++++---------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 2d9225c9..c4c2ab94 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,10 @@ Version 3.0.3 - --------------- - Fixed regex typo in `one_of` fix for `as_keyword=True`. +- Fixed a whitespace-skipping bug, Issue #319, introduced as part of the revert + of the `LineStart` changes. Reported by Marc-Alexandre Côté, + thanks! + Version 3.0.2 - --------------- diff --git a/pyparsing/core.py b/pyparsing/core.py index 0e91666a..ab178f32 100644 --- a/pyparsing/core.py +++ b/pyparsing/core.py @@ -3853,7 +3853,9 @@ def __init__(self, exprs: IterableType[ParserElement], savelist: bool = False): def streamline(self): super().streamline() if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) self.saveAsList = any(e.saveAsList for e in self.exprs) + self.skipWhitespace = all(e.skipWhitespace for e in self.exprs) else: self.saveAsList = False return self @@ -3967,7 +3969,7 @@ def _setResultsName(self, name, listAllMatches=False): class MatchFirst(ParseExpression): """Requires that at least one :class:`ParseExpression` is found. If - two expressions match, the first one listed is the one that will + more than one expression matches, the first one listed is the one that will match. May be constructed using the ``'|'`` operator. Example:: @@ -3987,7 +3989,6 @@ def __init__(self, exprs: IterableType[ParserElement], savelist: bool = False): super().__init__(exprs, savelist) if self.exprs: self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - self.callPreparse = all(e.callPreparse for e in self.exprs) self.skipWhitespace = all(e.skipWhitespace for e in self.exprs) else: self.mayReturnEmpty = True @@ -4000,7 +4001,7 @@ def streamline(self): if self.exprs: self.saveAsList = any(e.saveAsList for e in self.exprs) self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) - self.callPreparse = all(e.callPreparse for e in self.exprs) + self.skipWhitespace = all(e.skipWhitespace for e in self.exprs) else: self.saveAsList = False self.mayReturnEmpty = True @@ -4013,7 +4014,7 @@ def parseImpl(self, instring, loc, doActions=True): for e in self.exprs: try: return e._parse( - instring, loc, doActions, callPreParse=not self.callPreparse + instring, loc, doActions, ) except ParseFatalException as pfe: pfe.__traceback__ = None diff --git a/tests/test_unit.py b/tests/test_unit.py index 0a954000..f90e42ac 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -3617,16 +3617,19 @@ def testLineStart2(self): def testLineStartWithLeadingSpaces(self): # testing issue #272 + # reverted in 3.0.2 - LineStart() + expr will match expr even if there + # are leading spaces. To force "only at column 1" matching, use + # AtLineStart(expr). instring = dedent( """ - a - b - c - d - e - f - g - """ + a + b + c + d + e + f + g + """ ) print(pp.testing.with_line_numbers(instring)) @@ -7711,10 +7714,10 @@ def testEnableDebugWithCachedExpressionsMarkedWithAsterisk(self): Match leading_a at loc 1(1,2) aba ^ - *Match A at loc 1(1,2) + Match A at loc 1(1,2) aba ^ - *Match A failed, ParseException raised: Expected A, found 'ba' (at char 1), (line:1, col:2) + Match A failed, ParseException raised: Expected A, found 'ba' (at char 1), (line:1, col:2) Match leading_a failed, ParseException raised: Expected A, found 'ba' (at char 1), (line:1, col:2) *Match B at loc 1(1,2) aba