Skip to content

Commit

Permalink
Revert results names for packaging compatibility (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
ptmcg committed Nov 12, 2021
1 parent 85fc927 commit e22d4ca
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 21 deletions.
3 changes: 3 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Change Log

Version 3.0.6 -
---------------
- Refactored warning suppression code to preserve internal results names,
which, while undocumented, had been adopted by some projects.

- Fix bug when `delimited_list` was called with a str literal instead of a
parse expression.

Expand Down
31 changes: 24 additions & 7 deletions pyparsing/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,11 @@ def __init__(self, savelist: bool = False):
# avoid redundant calls to preParse
self.callPreparse = True
self.callDuringTry = False
self.suppress_warnings_ = []

def suppress_warning(self, warning_type: Diagnostics):
self.suppress_warnings_.append(warning_type)
return self

def copy(self) -> "ParserElement":
"""
Expand Down Expand Up @@ -3679,12 +3684,17 @@ def copy(self):
return ret

def _setResultsName(self, name, listAllMatches=False):
if __diag__.warn_ungrouped_named_tokens_in_collection:
if (
__diag__.warn_ungrouped_named_tokens_in_collection
and Diagnostics.warn_ungrouped_named_tokens_in_collection
not in self.suppress_warnings_
):
for e in self.exprs:
if (
isinstance(e, ParserElement)
and e.resultsName
and not e.resultsName.startswith("_NOWARN")
and Diagnostics.warn_ungrouped_named_tokens_in_collection
not in e.suppress_warnings_
):
warnings.warn(
"{}: setting results name {!r} on {} expression "
Expand Down Expand Up @@ -3982,7 +3992,8 @@ def _setResultsName(self, name, listAllMatches=False):
warnings.warn(
"{}: setting results name {!r} on {} expression "
"will return a list of all parsed tokens in an And alternative, "
"in prior versions only the first token was returned".format(
"in prior versions only the first token was returned; enclose"
"contained argument in Group".format(
"warn_multiple_tokens_in_named_alternation",
name,
type(self).__name__,
Expand Down Expand Up @@ -4080,8 +4091,9 @@ def _setResultsName(self, name, listAllMatches=False):
if any(isinstance(e, And) for e in self.exprs):
warnings.warn(
"{}: setting results name {!r} on {} expression "
"may only return a single token for an And alternative, "
"in future will return the full list of tokens".format(
"will return a list of all parsed tokens in an And alternative, "
"in prior versions only the first token was returned; enclose"
"contained argument in Group".format(
"warn_multiple_tokens_in_named_alternation",
name,
type(self).__name__,
Expand Down Expand Up @@ -4724,12 +4736,17 @@ def parseImpl(self, instring, loc, doActions=True):
return loc, tokens

def _setResultsName(self, name, listAllMatches=False):
if __diag__.warn_ungrouped_named_tokens_in_collection:
if (
__diag__.warn_ungrouped_named_tokens_in_collection
and Diagnostics.warn_ungrouped_named_tokens_in_collection
not in self.suppress_warnings_
):
for e in [self.expr] + self.expr.recurse():
if (
isinstance(e, ParserElement)
and e.resultsName
and not e.resultsName.startswith("_NOWARN")
and Diagnostics.warn_ungrouped_named_tokens_in_collection
not in e.suppress_warnings_
):
warnings.warn(
"{}: setting results name {!r} on {} expression "
Expand Down
14 changes: 4 additions & 10 deletions pyparsing/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,23 +390,17 @@ def original_text_for(
locMarker = Empty().set_parse_action(lambda s, loc, t: loc)
endlocMarker = locMarker.copy()
endlocMarker.callPreparse = False
# prefix these transient names with _NOWARN to suppress ungrouped name warnings
matchExpr = (
locMarker("_NOWARN_original_start")
+ expr
+ endlocMarker("_NOWARN_original_end")
)
matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end")
if asString:
extractText = lambda s, l, t: s[
t._NOWARN_original_start : t._NOWARN_original_end
]
extractText = lambda s, l, t: s[t._original_start : t._original_end]
else:

def extractText(s, l, t):
t[:] = [s[t.pop("_NOWARN_original_start") : t.pop("_NOWARN_original_end")]]
t[:] = [s[t.pop("_original_start") : t.pop("_original_end")]]

matchExpr.set_parse_action(extractText)
matchExpr.ignoreExprs = expr.ignoreExprs
matchExpr.suppress_warning(Diagnostics.warn_ungrouped_named_tokens_in_collection)
return matchExpr


Expand Down
24 changes: 22 additions & 2 deletions tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,18 @@ def assertRaises(self, expected_exception_type: Any, msg: Any = None):
return ar

@contextlib.contextmanager
def assertDoesNotWarn(self, msg: str = None):
def assertDoesNotWarn(self, warning_type: type = UserWarning, msg: str = None):
if msg is None:
msg = "unexpected warning raised"
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("error")
try:
yield
except Exception as e:
self.fail("{}: {}".format(msg, e))
if isinstance(e, warning_type):
self.fail("{}: {}".format(msg, e))
else:
raise


class Test01_PyparsingTestInit(TestCase):
Expand Down Expand Up @@ -169,6 +172,23 @@ def runTest(self):
self.assertTrue(all_success, "failed warnings enable test")


class Test01b_PyparsingUnitTestUtilitiesTests(TestCase):
def runTest(self):
with ppt.reset_pyparsing_context():
pp.enable_diag(pp.Diagnostics.warn_on_parse_using_empty_Forward)

# test assertDoesNotWarn raises an AssertionError
with self.assertRaises(AssertionError):
with self.assertDoesNotWarn(
msg="failed to warn when naming an empty Forward expression",
):
base = pp.Forward()
try:
print(base.parseString("x"))
except ParseException as pe:
pass


class Test02_WithoutPackrat(ppt.TestParseResultsAsserts, TestCase):
suite_context = None
save_suite_context = None
Expand Down
2 changes: 0 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,5 @@ deps=
commands=
python -c "import shutil,os,stat;os.path.exists('packaging') and shutil.rmtree('packaging', onerror=lambda fn, path, _:os.chmod(path,stat.S_IWRITE) or fn(path))"
git clone --depth 1 https://github.com/pypa/packaging.git
# patch packaging parser pre 21.2 release
python -c "from pathlib import Path;p=Path('packaging/packaging/requirements.py');p.write_text(p.read_text().replace('MARKER_EXPR.setParseAction','MARKER_EXPR.addParseAction').replace('s[t._original_start : t._original_end]','t.marker'))"
python -m pytest packaging/tests
python -c "import shutil,os,stat;shutil.rmtree('packaging', onerror=lambda fn, path, _:os.chmod(path,stat.S_IWRITE) or fn(path))"

0 comments on commit e22d4ca

Please sign in to comment.