Skip to content

Instantly share code, notes, and snippets.

@nramirezuy
Created January 8, 2015 18:41
Show Gist options
  • Save nramirezuy/e61e3e0a5eadbd37eebc to your computer and use it in GitHub Desktop.
Save nramirezuy/e61e3e0a5eadbd37eebc to your computer and use it in GitHub Desktop.
def dictpath(dct, path):
"""Resolve dictpath
>>> r = {'also_viewed': ['url1', 'url2']}
>>> list(dictpath(r, 'also_viewed'))
['url1', 'url2']
>>> r = {'related': [{'url': 'url1'}, {'url': 'url2'}]}
>>> list(dictpath(r, 'related:url'))
['url1', 'url2']
>>> r = {'related': [{'urls': ['url1', 'url2']}, {'urls': ['url3', 'url4']}]}
>>> list(dictpath(r, 'related:urls'))
['url1', 'url2', 'url3', 'url4']
>>> r = {'related': [['name1', 'url1', 'image1'], ['name2', 'url2', 'image2']]}
>>> list(dictpath(r, 'related[1]'))
['url1', 'url2']
>>> r = {'related': [['name1', 'url1', 'url2'], ['name2', 'url3', 'url4']]}
>>> list(dictpath(r, 'related[1:3]'))
['url1', 'url2', 'url3', 'url4']
>>> list(dictpath(r, 'related[1:]'))
['url1', 'url2', 'url3', 'url4']
>>> r = {'related': [['url1', 'url2'], ['url3', 'url4']]}
>>> list(dictpath(r, 'related[:]'))
['url1', 'url2', 'url3', 'url4']
>>> r = {'related': [['url1', 'name1'], ['url2', 'name2']]}
>>> list(dictpath(r, 'related[:-1]'))
['url1', 'url2']
"""
lex = shlex.shlex(path)
lex.wordchars += '-'
rr = dct
for token in lex:
if token == ':':
continue
elif token == '[':
assert isinstance(rr, list), 'Dicts can\'t be sliced'
slice_args = []
last_token = None
for token in lex:
if token == ']':
if last_token == ':':
slice_args.append(None)
break
if token == ':':
if not slice_args:
slice_args.append(None)
else:
slice_args.append(int(token))
last_token = token
if len(slice_args) == 1:
slice_args = [slice_args[0], slice_args[0] + 1]
slice_obj = slice(*slice_args)
if rr and isinstance(rr[0], list):
rr = [itemgetter(slice_obj)(x) for x in rr]
else:
rr = itemgetter(slice_obj)(rr)
else:
if isinstance(rr, dict):
if token not in rr:
break
rr = rr[token]
elif isinstance(rr, list):
rr = [x[token] for x in rr if token in x]
if not rr:
break
else:
if isinstance(rr, basestring):
rr = [rr]
if isinstance(rr, list):
for url in flatten(rr):
yield url
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment