Created
January 8, 2015 18:41
-
-
Save nramirezuy/e61e3e0a5eadbd37eebc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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