Mercurial > jpath
changeset 6:ba0f10adb44b
add filters
| author | sheep@wintermute |
|---|---|
| date | Wed, 14 Apr 2010 12:14:55 +0200 |
| parents | e69a0207568a |
| children | 8b9133467904 |
| files | jpath.py |
| diffstat | 1 files changed, 54 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/jpath.py Wed Apr 14 11:39:51 2010 +0200 +++ b/jpath.py Wed Apr 14 12:14:55 2010 +0200 @@ -140,6 +140,51 @@ def parse(self, tokens, data): return Token.apply(tokens, data[self.start:self.end:self.step]) +@Tokenizer.token +class FilterToken(Token): + """(foo=3)""" + + regexp = (r'[(](?P<filter_path>[^(=)]+)\s*=\s*' + r'(?P<filter_value>"([^"]|\\")*"|-?[0-9]|true|false)[)]') + name = '_filter' + priority = 50 + + def __init__(self, _filter, filter_path, filter_value): + """ + >>> FilterToken(r'(foo="b\"ar")', r'foo', r'"b\"ar"').value + 'b"ar' + >>> FilterToken(r'(bar=-1)', r'bar', r'-1').value + -1 + """ + self.path = filter_path + if filter_value.startswith('"'): + self.value = filter_value[1:-1].replace(r'\"', '"') + elif filter_value in ('true', 'false'): + self.value = filter_value == 'true' + else: + self.value = int(filter_value) + + def parse(self, tokens, data): + try: + token, *tokens = tokens + except ValueError: + token = NoneToken() + try: + # If it's a dict, iterate over values, not keys. + data = data.values() + except AttributeError: + pass + for item in data: + if get(self.path, item) == self.value: + try: + for value in token.parse(tokens, item): + yield value + except (TypeError, IndexError, KeyError): + # Ignore errors inside branches, because some + # of the branches may have different structure + # than our jpath wants. + pass + @Tokenizer.token class WildcardToken(Token): @@ -201,7 +246,7 @@ except TypeError: continue for item in data: - if not isinstance(item, (str, int)): + if not isinstance(item, str): # Strings are nasty, because they can be iterated # recursively idefinitely. stack.append(item) @@ -276,6 +321,14 @@ [[2, 3]] >>> get_all('[:-1]', [1, 2, 3]) [[1, 2]] + >>> get_all('[::2]', [1, 2, 3, 4]) + [[1, 3]] + >>> get_all('(x=1).y', [{'x':1, 'y':2}, {'x':0, 'y':3}, {'x':1, 'y':4}]) + [2, 4] + >>> get_all('(x=1).y', [{'x':1, 'y':2}, {'x':0, 'y':3}, {'x':1}]) + [2] + >>> get_all('..', {'a':1, 'x':[2], 'c':[{'b': '3'}]}) + [{'a': 1, 'x': [2], 'c': [{'b': '3'}]}, 1, [2], [{'b': '3'}], {'b': '3'}, 2] """ return list(Token.apply(TOKENIZER.tokenize(jpath), data))
