Skip to content

Commit

Permalink
Handle case where Word(min > 1) (fixes #502)
Browse files Browse the repository at this point in the history
  • Loading branch information
ptmcg committed Jul 29, 2023
1 parent 421e0fc commit 1936b36
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Version 3.2.0 will also discontinue support for Python versions 3.6 and 3.7.

Version 3.1.1 - (in development)
--------------------------------
- Fixed bug in Word(min), reported by Ricardo Coccioli, good catch! (Issue #502)

- Fixed bug in bad exception messages raised by Forward expressions. PR submitted
by Kyle Sunden, thanks for your patience and collaboration on this (#493).

Expand Down
2 changes: 1 addition & 1 deletion pyparsing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def __repr__(self):


__version_info__ = version_info(3, 1, 1, "final", 1)
__version_time__ = "29 Jul 2023 08:18 UTC"
__version_time__ = "29 Jul 2023 09:56 UTC"
__version__ = __version_info__.__version__
__versionTime__ = __version_time__
__author__ = "Paul McGuire <ptmcg.gm+pyparsing@gmail.com>"
Expand Down
6 changes: 4 additions & 2 deletions pyparsing/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1079,7 +1079,9 @@ def enable_left_recursion(
ParserElement._left_recursion_enabled = True

@staticmethod
def enable_packrat(cache_size_limit: Union[int, None] = 128, *, force: bool = False) -> None:
def enable_packrat(
cache_size_limit: Union[int, None] = 128, *, force: bool = False
) -> None:
"""
Enables "packrat" parsing, which adds memoizing to the parsing logic.
Repeated parse attempts at the same string location (which happens
Expand Down Expand Up @@ -2879,7 +2881,7 @@ def __init__(
re_leading_fragment = f"[{_collapse_string_to_ranges(self.initChars)}]"

if self.bodyChars == self.initChars:
if max == 0:
if max == 0 and self.minLen == 1:
repeat = "+"
elif max == 1:
repeat = ""
Expand Down
46 changes: 46 additions & 0 deletions tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -5221,6 +5221,50 @@ def testWordMinMaxExactArgs(self):
["A1234567890"[:exarg]],
)

def testWordMin(self):
# failing tests
for min_val in range(2, 5):
with self.subTest(min_val=min_val):
wd = pp.Word("a", min=min_val)
print(min_val, wd.reString)
with self.assertRaisesParseException():
wd.parse_string("a")

# passing tests
for min_val in range(2, 5):
with self.subTest(min_val=min_val):
wd = pp.Word("a", min=min_val)
test_string = "a" * min_val
self.assertParseAndCheckList(
wd,
test_string,
[test_string],
msg=f"Word(min={min_val}) failed",
verbose=True,
)

def testWordExact(self):
# failing tests
for exact_val in range(2, 5):
with self.subTest(exact_val=exact_val):
wd = pp.Word("a", exact=exact_val)
print(exact_val, wd.reString)
with self.assertRaisesParseException():
wd.parse_string("a")

# passing tests
for exact_val in range(2, 5):
with self.subTest(exact_val=exact_val):
wd = pp.Word("a", exact=exact_val)
test_string = "a" * exact_val
self.assertParseAndCheckList(
wd,
test_string,
[test_string],
msg=f"Word(exact={exact_val}) failed",
verbose=True,
)

def testInvalidMinMaxArgs(self):
with self.assertRaises(ValueError):
wd = pp.Word(min=2, max=1)
Expand Down Expand Up @@ -9915,8 +9959,10 @@ def testForwardReferenceException(self):
text = pp.Word(pp.alphas)
text.setName("text")
fail = pp.Regex(r"\\[A-Za-z]*")("name")

def parse_fail(s, loc, toks):
raise pp.ParseFatalException(s, loc, f"Unknown symbol: {toks['name']}")

fail.set_parse_action(parse_fail)
token <<= num | text | fail

Expand Down

0 comments on commit 1936b36

Please sign in to comment.