Skip to content

Commit

Permalink
Fix #345 - delimitedList calling streamline() changes content of expr…
Browse files Browse the repository at this point in the history
… in some cases; use a copy to generate default expr name
  • Loading branch information
ptmcg committed Dec 15, 2021
1 parent 8bcd844 commit 2f633f4
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -4,6 +4,9 @@ Change Log

Version 3.0.7 -
---------------
- Fixed bug #345, in which delimitedList changed expressions in place
using expr.streamline(). Reported by Kim Gräsman, thanks!

- Added optional "min" and "max" arguments to `delimited_list`. PR
submitted by Marius, thanks!

Expand Down
2 changes: 1 addition & 1 deletion pyparsing/__init__.py
Expand Up @@ -126,7 +126,7 @@ def __repr__(self):


__version_info__ = version_info(3, 0, 7, "final", 0)
__version_time__ = "04 Dec 2021 08:48 UTC"
__version_time__ = "15 Dec 2021 05:56 UTC"
__version__ = __version_info__.__version__
__versionTime__ = __version_time__
__author__ = "Paul McGuire <ptmcg.gm+pyparsing@gmail.com>"
Expand Down
2 changes: 1 addition & 1 deletion pyparsing/helpers.py
Expand Up @@ -40,7 +40,7 @@ def delimited_list(
expr = ParserElement._literalStringClass(expr)

dlName = "{expr} [{delim} {expr}]...{end}".format(
expr=str(expr.streamline()),
expr=str(expr.copy().streamline()),
delim=str(delim),
end=" [{}]".format(str(delim)) if allow_trailing_delim else "",
)
Expand Down
37 changes: 37 additions & 0 deletions tests/test_unit.py
Expand Up @@ -6721,6 +6721,43 @@ def add_total(tokens):
"noop parse action changed ParseResults structure",
)

def testParseActionWithDelimitedList(self):
class AnnotatedToken(object):
def __init__(self, kind, elements):
self.kind = kind
self.elements = elements

def __str__(self):
return 'AnnotatedToken(%r, %r)' % (self.kind, self.elements)

def __eq__(self, other):
return type(self) == type(other) and self.kind == other.kind and self.elements == other.elements

__repr__ = __str__

def annotate(name):
def _(t):
return AnnotatedToken(name, t.asList())
return _

identifier = pp.Word(pp.srange('[a-z0-9]'))
numeral = pp.Word(pp.nums)

named_number_value = pp.Suppress('(') + numeral + pp.Suppress(')')
named_number = identifier + named_number_value

named_number_list = (pp.Suppress('{') +
pp.Group(pp.Optional(pp.delimitedList(named_number))) +
pp.Suppress('}'))

# repro but in #345 - delimitedList silently changes contents of named_number
named_number_value.setParseAction(annotate("val"))

test_string = "{ x1(1), x2(2) }"
expected = [['x1', AnnotatedToken("val", ['1']), 'x2', AnnotatedToken("val", ['2'])]]

self.assertParseAndCheckList(named_number_list, test_string, expected)

def testParseResultsNameBelowUngroupedName(self):

rule_num = pp.Regex("[0-9]+")("LIT_NUM*")
Expand Down

0 comments on commit 2f633f4

Please sign in to comment.