Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is pyparser's asDict() returning an empty dict instead of a list?

I'm trying to write a parser to handle response data from a registrar's API. The format isn't one that I've seen before, so this might be really easy; If anyone recognizes it, let me know and there is probably a pre-existing library to deal with it. But for now I'm operating on the assumption that I'll need to parse it myself.

My grammar looks like this:

equals = Literal("=").suppress()
lbracket = Literal("[").suppress()
rbracket = Literal("]").suppress()
lbrace = Literal("{").suppress()
rbrace = Literal("}").suppress()

value_dict          = Forward()
value_list          = Forward()
value_string        = Word(alphanums + "@. ")

value               = value_list ^ value_dict ^ value_string
values              = Group(delimitedList(value, ","))
value_list          << lbracket + values + rbracket

identifier          = Word(alphanums + "_.")

assignment          = Group(identifier + equals + Optional(value))
assignments         = Dict(delimitedList(assignment, ';'))
value_dict          << lbrace + assignments + rbrace

response = assignments

When I run this simple test case:

rsp = 'username=goat; errors={username=[already taken, too short]}; empty_field='
result = response.parseString(rsp)
print result.asDict()

I get the following:

{'username': 'goat', 'empty_field': '', 'errors': {'username': {}}}

errors['username'] should be a list of strings, but is showing as an empty dict. When I .dump() the params, it looks like everything is fine:

ss = response.searchString(rsp)
for i in ss:
    print i.dump()

yields:

- empty_field: 
- errors: [['username', ['already taken', 'too short']]]
  - username: ['already taken', 'too short']
- username: goat

What am I doing wrong here?

like image 454
Gerald Thibault Avatar asked Dec 30 '25 06:12

Gerald Thibault


1 Answers

It is a naive implementation of asDict() in the current version of pyparsing. In yoru grammar, you create ParseResults of two different styles: results with names, and results that are just plain lists. asList() simply iterates through a nested ParseResults getting lists and sublists, so asDict() works similarly. However, asDict() really needs to be a little smarter about the types of values that there can be - for now, this is a bug in pyparsing.

EDIT

To work around this, you need to do a little work to store the lists as actual lists, not as ParseResults. Redefine the values expression to:

values = delimitedList(value, ",").setParseAction(lambda toks: [toks.asList()])

Since this will return the parsed list not as a ParseResults, but as an actual list, toDict() will not try to turn it into a dict.

like image 131
PaulMcG Avatar answered Jan 01 '26 18:01

PaulMcG



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!