Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dict(asdict=True) with items created/modified with parse action can't be nested in Each #432

Open
grv87 opened this issue Jul 18, 2022 · 4 comments

Comments

@grv87
Copy link

grv87 commented Jul 18, 2022

from pyparsing import *
s = """
1 2 3
"""

def get_name_lambda(name):
    return lambda: name

POINT = Dict(And([Group(Empty().add_parse_action(get_name_lambda(name)) + pyparsing_common.signed_integer) for name in ["x", "y", "z"]]))
# 1 This works: [['x', 1], ['y', 2], ['z', 3]]
print(Each(POINT).parse_string(s))

POINT_AS_DICT = Dict(And([Group(Empty().add_parse_action(get_name_lambda(name)) + pyparsing_common.signed_integer) for name in ["x", "y", "z"]]), asdict=True)
# 2 This works: [{'x': 1, 'y': 2, 'z': 3}]
print(Each(POINT_AS_DICT).parse_string(s))

s = """
1 2 3
4 5 6
"""

POINTS = Dict(And([Group(Empty().add_parse_action(get_name_lambda(name)) + POINT) for name in ["point1", "point2"]]))
# 3 This works: [['point1', ['x', 1], ['y', 2], ['z', 3]], ['point2', ['x', 4], ['y', 5], ['z', 6]]]
print(POINTS.parse_string(s).as_list())
# 4 This works: [['point1', ['x', 1], ['y', 2], ['z', 3]], ['point2', ['x', 4], ['y', 5], ['z', 6]]]
print(Each(POINTS).parse_string(s))

POINTS_AS_DICTS = Dict(And([Group(Empty().add_parse_action(get_name_lambda(name)) + POINT_AS_DICT) for name in ["point1", "point2"]]))
# 5 This works: [['point1', {'x': 1, 'y': 2, 'z': 3}], ['point2', {'x': 4, 'y': 5, 'z': 6}]]
print(POINTS_AS_DICTS.parse_string(s))
# 6 This gives an error
print(Each(POINTS_AS_DICTS).parse_string(s))

The last case gives the error:

This gives error:
Traceback (most recent call last):
  File "…\pyparsing_spikes\issue_YYY.py", line 20, in <module>
    print(Each(POINTS).parse_string(s))
  File "C:\root\Python\3.10\w64\lib\site-packages\pyparsing\core.py", line 1131, in parse_string
    loc, tokens = self._parse(instring, 0)
  File "C:\root\Python\3.10\w64\lib\site-packages\pyparsing\core.py", line 817, in _parseNoCache
    loc, tokens = self.parseImpl(instring, pre_loc, doActions)
  File "C:\root\Python\3.10\w64\lib\site-packages\pyparsing\core.py", line 4296, in parseImpl
    tmpLoc = e.try_parse(instring, tmpLoc, raise_fatal=True)
  File "C:\root\Python\3.10\w64\lib\site-packages\pyparsing\core.py", line 880, in try_parse
    return self._parse(instring, loc, doActions=False)[0]
  File "C:\root\Python\3.10\w64\lib\site-packages\pyparsing\core.py", line 823, in _parseNoCache
    tokens = self.postParse(instring, loc, tokens)
  File "C:\root\Python\3.10\w64\lib\site-packages\pyparsing\core.py", line 5524, in postParse
    tokenlist[ikey] = _ParseResultsWithOffset("", i)
  File "C:\root\Python\3.10\w64\lib\site-packages\pyparsing\results.py", line 202, in __setitem__
    self._tokdict[k] = self._tokdict.get(k, list()) + [v]
TypeError: unhashable type: 'dict'

So, the problem occurs with asdict=True only. And only inside Each (or maybe other containers that call try_parse).
Debugging shows that case # 2 actually has the same behavior/problem. So, the depth of nesting doesn't matter. It's just that '1' is hashable, so it doesn't crash.

Is there any reason why try_parse should call postParse at all?

@ptmcg
Copy link
Member

ptmcg commented Jul 18, 2022

Of the 4 ParseExpression classes, Each and Or have this issue, And and MatchFirst do not. I'll have to dig deeper this evening.

@grv87
Copy link
Author

grv87 commented Jul 19, 2022

@ptmcg, any news?

Looks that my issue can be easily fixed with

.add_parse_action(…, call_during_try = True)

So, it's again a documentation/misunderstanding problem.

@ptmcg
Copy link
Member

ptmcg commented Jul 20, 2022 via email

@ptmcg
Copy link
Member

ptmcg commented Nov 5, 2022

Basil -

And here it is November, much further than just "mid next week". Working on a book (with hard deadlines) was more intense than I expected.

I have been holding off the next release of pyparsing because of this open item. I may actually have to break some current behavior, and if I do that, I'll probably not do that in the 3.0.x versions, but release as a 3.1.0, and probably do some early release candidates too.

Thanks for your patience!
-- Paul

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants