Может быть, вместо парсера, как насчет постобработки запроса.args, который вы получаете?
from pyparsing import Suppress, alphas, alphanums, nums, Word
from itertools import groupby
# you could do this with regular expressions too, if you prefer
LBRACK,RBRACK = map(Suppress, '[]')
ident = Word('_' + alphas, '_' + alphanums)
integer = Word(nums).setParseAction(lambda t : int(t[0]))
subscriptedRef = ident + 2*(LBRACK + (ident | integer) + RBRACK)
def simplify_value(v):
if isinstance(v,list) and len(v)==1:
return simplify_value(v[0])
if v == integer:
return int(v)
return v
def regroup_args(dd):
ret = {}
subscripts = []
for k,v in dd.items():
# this is a pyparsing short-cut to see if a string matches a pattern
# I also used it above in simplify_value to test for integerness of a string
if k == subscriptedRef:
subscripts.append(tuple(subscriptedRef.parseString(k))+
(simplify_value(v),))
else:
ret[k] = simplify_value(v)
# sort all the matched subscripted args, and then use groupby to
# group by name and list index
# this assumes all indexes 0-n are present in the parsed arguments
subscripts.sort()
for name,nameitems in groupby(subscripts, key=lambda x:x[0]):
ret[name] = []
for idx,idxitems in groupby(nameitems, key=lambda x:x[1]):
idd = {}
for item in idxitems:
name, i, attr, val = item
idd[attr] = val
ret[name].append(idd)
return ret
request_args = {'grid[1][y]': ['184'], 'grid[0][y]': ['185'], 'grid[1][x]': ['18'], 'request': ['loadTiles'], 'grid[0][x]': ['17']}
print regroup_args(request_args)
print
{'grid': [{'y': 185, 'x': 17}, {'y': 184, 'x': 18}], 'request': 'loadTiles'}
Обратите внимание, что это также упрощает-элемент перечисляет только 0-е значение элемента и преобразует числовые строки в реальные целые числа.