annotate jpath.py @ 28:0a216b982fd1 default tip

Bump version to 1.6
author Radomir Dopieralski <sheep-devel@sheep.art.pl>
date Mon, 22 Jan 2018 15:45:20 +0100
parents a607cb7f6333
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
1 #!/usr/bin/env python
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
2 # -*- coding: utf-8 -*-
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
3
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
4 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
5 Access nested dicts and lists using JSON-like path notation.
8
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
6
10
6cea15b348e2 filter no longer ignores errors
sheep@wintermute
parents: 9
diff changeset
7 Note that this code is written for python 3.
6cea15b348e2 filter no longer ignores errors
sheep@wintermute
parents: 9
diff changeset
8
8
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
9 The notation is as follows:
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
10
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
11 You can just write the names of components in your path like you
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
12 would in javascript:
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
13
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
14 foo.bar.baz
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
15
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
16 To access arrays or names with spaces in them, use the '[]' notation.
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
17 You can use negative indices with arrays to count from the end.
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
18
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
19 ["foo"]["bar"]["baz"]
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
20 array[-1].attr
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
21 [3]
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
22
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
23 You can use the wildcard character '*' to iterate over all elements:
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
24
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
25 foo.*.baz
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
26 ["foo"][*]["baz"]
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
27
9
ead552bcd268 add setup.py and prepare for publishing
sheep@wintermute
parents: 8
diff changeset
28 This may return more or less than a single element. Use get to get the
ead552bcd268 add setup.py and prepare for publishing
sheep@wintermute
parents: 8
diff changeset
29 first one, and get_all to get a list of all possibilities.
8
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
30 If you want to skip any number of elements in path, use two dots '..':
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
31
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
32 foo..baz
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
33
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
34 You can slice the arrays just like in python:
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
35
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
36 array[1:-1:2]
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
37
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
38 Finally, you can filter the elements:
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
39
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
40 foo(bar.baz=true)
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
41 foo.bar(baz>0).baz
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
42 foo(bar="yawn").bar
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
43
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
44 At the moment only =, >, <, >=, <= and != operators are available,
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
45 and you can only use them with strings, integers and boolean values.
13
c46a837e2bfc added MANIFEST
Radomir Dopieralski <sheep@stxnext.pl>
parents: 12
diff changeset
46
c46a837e2bfc added MANIFEST
Radomir Dopieralski <sheep@stxnext.pl>
parents: 12
diff changeset
47 This code was written in STX Next.
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
48 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
49
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
50 # We use very simple top-down parsing using recursive function calls.
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
51 # This may break in python for very very very long jpaths.
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
52
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
53
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
54 import re
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
55 import operator
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
56
5
e69a0207568a some small cleaup
sheep@wintermute
parents: 4
diff changeset
57 __all__ = ['get', 'get_all']
28
0a216b982fd1 Bump version to 1.6
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 27
diff changeset
58 __version__ = '1.6'
18
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
59
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
60
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
61 # Make it work both in python 2.x and 3.x
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
62 try:
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
63 basestring
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
64 except NameError:
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
65 basestring = str
5
e69a0207568a some small cleaup
sheep@wintermute
parents: 4
diff changeset
66
15
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
67
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
68 def _pop_token(tokens):
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
69 try:
20
5c844a14d835 Fix the error with parsing get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 19
diff changeset
70 token = tokens.pop()
5c844a14d835 Fix the error with parsing get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 19
diff changeset
71 except IndexError:
15
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
72 token = NoneToken()
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
73 return token
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
74
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
75
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
76 class Tokenizer:
8
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
77 # list of all token classes marked with @Tokenizer.token
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
78 tokens = {}
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
79
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
80 def __init__(self):
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
81 self.tokens_re = re.compile(r'|'.join(
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
82 r'(?P<{0}>{1})'.format(token.name, token.regexp)
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
83 for token in sorted(self.tokens.values(),
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
84 key=operator.attrgetter("priority"))
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
85 ))
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
86
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
87 @classmethod
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
88 def token(cls, token_class):
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
89 """Marks a token class to be used in tokenizer."""
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
90
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
91 cls.tokens[token_class.name] = token_class
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
92 return cls
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
93
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
94 def tokenize(self, jpath):
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
95 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
96 Breaks a string into tokens.
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
97
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
98 >>> [(t.name, t.value) for t in TOKENIZER.tokenize("ziew")]
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
99 [('fragment', 'ziew')]
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
100 >>> [(t.name, t.value) for t in TOKENIZER.tokenize("ziew.yawn")]
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
101 [('fragment', 'ziew'), ('fragment', 'yawn')]
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
102 >>> [(t.name, t.value) for t in TOKENIZER.tokenize('ziew["yawn"]')]
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
103 [('fragment', 'ziew'), ('element', 'yawn')]
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
104 >>> [(t.name, t.value) for t in TOKENIZER.tokenize('ziew[0]')]
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
105 [('fragment', 'ziew'), ('index', 0)]
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
106 >>> [(t.name, t.value) for t in TOKENIZER.tokenize("ziew.yawn+")]
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
107 [('fragment', 'ziew'), ('fragment', 'yawn'), ('error', '+')]
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
108 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
109
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
110 for match in self.tokens_re.finditer(jpath):
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
111 name = match.lastgroup
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
112 if match.group(name):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
113 params = dict(p for p in match.groupdict().items()
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
114 if p[1] is not None)
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
115 yield self.tokens[name](**params)
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
116
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
117
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
118 class Token:
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
119 """Base class for tokens."""
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
120
2
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
121 @staticmethod
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
122 def apply(tokens, data):
15
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
123 token = _pop_token(tokens)
2
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
124 for value in token.parse(tokens, data):
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
125 yield value
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
126
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
127 def parse(self, tokens, data):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
128 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
129 Default parsing method for most tokens: parse the subtree
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
130 under token's value in data.
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
131 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
132
27
a607cb7f6333 Fix #1: KeyError instead of returning []
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 26
diff changeset
133 try:
a607cb7f6333 Fix #1: KeyError instead of returning []
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 26
diff changeset
134 value = data[self.value]
a607cb7f6333 Fix #1: KeyError instead of returning []
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 26
diff changeset
135 except (IndexError, KeyError):
a607cb7f6333 Fix #1: KeyError instead of returning []
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 26
diff changeset
136 return []
a607cb7f6333 Fix #1: KeyError instead of returning []
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 26
diff changeset
137 return Token.apply(tokens, value)
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
138
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
139
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
140 @Tokenizer.token
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
141 class FragmentToken(Token):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
142 """foo.bar.baz"""
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
143
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
144 regexp = r'(^|(?<=\.\.)|\.)(?P<fragment_name>[a-zA-Z0-9_]+)'
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
145 name = 'fragment'
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
146 priority = 50
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
147
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
148 def __init__(self, fragment, fragment_name):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
149 self.value = fragment_name
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
150
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
151
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
152 @Tokenizer.token
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
153 class ElementToken(Token):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
154 """["foo"]["bar"]["baz"], with quote escaping"""
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
155
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
156 regexp = r'\["(?P<element_name>([^"]|\\")*)"\]'
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
157 name = 'element'
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
158 priority = 50
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
159
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
160 def __init__(self, element, element_name):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
161 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
162 >>> ElementToken(r'["ziew"]', r'ziew').value
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
163 'ziew'
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
164 >>> ElementToken('[r'["\"quotes\""]', r'\"quotes\"').value
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
165 '"quotes"'
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
166 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
167
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
168 # Un-escape escaped double quotes.
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
169 self.value = element_name.replace(r'\"', '"')
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
170
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
171
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
172 @Tokenizer.token
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
173 class IndexToken(Token):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
174 """[0][1][-1]"""
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
175
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
176 regexp = r'\[(?P<index_value>-?[0-9]+)\]'
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
177 name = 'index'
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
178 priority = 50
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
179
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
180 def __init__(self, index, index_value):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
181 self.value = int(index_value)
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
182
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
183
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
184 @Tokenizer.token
2
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
185 class SliceToken(Token):
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
186 """[0:-1:2], may return multiple results"""
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
187
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
188 regexp = (r'\[(?P<slice_start>-?[0-9]+)?:(?P<slice_end>-?[0-9]+)?'
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
189 r'(:(?P<slice_step>-?[0-9]+))?\]')
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
190 name = '_slice'
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
191 priority = 50
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
192
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
193 def __init__(self, _slice, slice_start=None, slice_end=None,
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
194 slice_step=None):
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
195 self.start = int(slice_start) if slice_start is not None else None
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
196 self.end = int(slice_end) if slice_end is not None else None
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
197 self.step = int(slice_step) if slice_step is not None else None
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
198
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
199 def parse(self, tokens, data):
25
28dc252c2300 Go back to the original slice semantics
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 24
diff changeset
200 return Token.apply(tokens, data[self.start:self.end:self.step])
22
4b25553183cc Change the semantics of the slice operator to be more intuitive
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 21
diff changeset
201
2
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
202
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
203 @Tokenizer.token
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
204 class FilterToken(Token):
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
205 """(foo=3)"""
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
206
7
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
207 regexp = (r'[(](?P<filter_path>[^(<=>)!]+)'
8
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
208 r'\s*(?P<filter_operator>[<=>]|>=|<=|!=|==)\s*'
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
209 r'(?P<filter_value>"([^"]|\\")*"|-?[0-9]|true|false)[)]')
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
210 name = '_filter'
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
211 priority = 50
7
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
212 op = {
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
213 '=': operator.eq,
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
214 '>': operator.gt,
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
215 '<': operator.lt,
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
216 '!=': operator.ne,
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
217 '>=': operator.ge,
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
218 '<=': operator.le,
8
1ad7cf9159dd some basic documentation
sheep@wintermute
parents: 7
diff changeset
219 '==': operator.eq
7
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
220 }
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
221
7
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
222 def __init__(self, _filter, filter_path, filter_operator, filter_value):
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
223 """
7
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
224 >>> FilterToken(r'(foo="b\"ar")', r'foo', r'=', r'"b\"ar"').value
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
225 'b"ar'
7
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
226 >>> FilterToken(r'(bar=-1)', r'bar', r'=', r'-1').value
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
227 -1
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
228 """
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
229 self.path = filter_path
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
230 if filter_value.startswith('"'):
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
231 self.value = filter_value[1:-1].replace(r'\"', '"')
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
232 elif filter_value in ('true', 'false'):
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
233 self.value = filter_value == 'true'
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
234 else:
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
235 self.value = int(filter_value)
7
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
236 self.operator = filter_operator
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
237
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
238 def parse(self, tokens, data):
15
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
239 token = _pop_token(tokens)
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
240 try:
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
241 # If it's a dict, iterate over values, not keys.
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
242 data = data.values()
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
243 except AttributeError:
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
244 pass
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
245 for item in data:
10
6cea15b348e2 filter no longer ignores errors
sheep@wintermute
parents: 9
diff changeset
246 try:
6cea15b348e2 filter no longer ignores errors
sheep@wintermute
parents: 9
diff changeset
247 item_value = get(self.path, item)
6cea15b348e2 filter no longer ignores errors
sheep@wintermute
parents: 9
diff changeset
248 except (TypeError, IndexError, KeyError):
6cea15b348e2 filter no longer ignores errors
sheep@wintermute
parents: 9
diff changeset
249 # Skip the branches that don't have the value we look for.
6cea15b348e2 filter no longer ignores errors
sheep@wintermute
parents: 9
diff changeset
250 continue
6cea15b348e2 filter no longer ignores errors
sheep@wintermute
parents: 9
diff changeset
251 if self.op[self.operator](item_value, self.value):
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
252 for value in token.parse(tokens, item):
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
253 yield value
2
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
254
28
0a216b982fd1 Bump version to 1.6
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 27
diff changeset
255
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
256 @Tokenizer.token
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
257 class WildcardToken(Token):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
258 """*[*].*, may return multiple results"""
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
259
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
260 regexp = r'(^|(?<=\.\.)|\.)\*|\[\*\]'
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
261 name = 'wildcard'
2
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
262 priority = 50
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
263
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
264 def __init__(self, wildcard):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
265 self.value = None
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
266
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
267 def parse(self, tokens, data):
15
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
268 token = _pop_token(tokens)
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
269 try:
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
270 # If it's a dict, iterate over values, not keys.
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
271 data = data.values()
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
272 except AttributeError:
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
273 pass
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
274 for item in data:
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
275 try:
20
5c844a14d835 Fix the error with parsing get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 19
diff changeset
276 for value in token.parse(list(tokens), item):
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
277 yield value
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
278 except (TypeError, IndexError, KeyError):
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
279 # Ignore errors inside branches, because some
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
280 # of the branches may have different structure
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
281 # than our jpath wants.
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
282 pass
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
283
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
284
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
285 @Tokenizer.token
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
286 class EllipsisToken(Token):
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
287 """.., may return multiple results"""
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
288
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
289 regexp = r'\.\.'
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
290 name = 'ellipsis'
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
291 priority = 60
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
292
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
293 def __init__(self, ellipsis):
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
294 self.value = None
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
295
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
296 def parse(self, tokens, data):
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
297 def dive(data):
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
298 yield data
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
299 stack = [data]
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
300 while stack:
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
301 data = stack.pop()
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
302 try:
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
303 # If it's a dict, iterate over values, not keys.
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
304 data = data.values()
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
305 except AttributeError:
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
306 pass
18
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
307 orig_data = data
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
308 try:
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
309 # Skip non-iterable datatypes.
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
310 data = iter(data)
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
311 except TypeError:
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
312 continue
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
313 for item in data:
18
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
314 if isinstance(item, basestring):
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
315 # Strings are nasty, because they can be iterated
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
316 # recursively idefinitely.
18
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
317 continue
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
318 if item is orig_data:
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
319 # We are iterating over something that behaves like
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
320 # the strings, refuse to descend.
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
321 break
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
322 stack.append(item)
7dccdab5061e Fix problems with infinite recursion into unicode strings and magical null objects
Radomir Dopieralski <devel@sheep.art.pl>
parents: 17
diff changeset
323 yield item
15
0b466831544d compatibility with python 2.7+
Wojciech Lichota <wojciech.lichota@stxnext.pl>
parents: 13
diff changeset
324 token = _pop_token(tokens)
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
325 for item in dive(data):
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
326 try:
20
5c844a14d835 Fix the error with parsing get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 19
diff changeset
327 for value in token.parse(list(tokens), item):
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
328 yield value
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
329 except (TypeError, IndexError, KeyError):
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
330 # Ignore errors inside branches, because some
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
331 # of the branches may have different structure
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
332 # than our jpath wants.
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
333 pass
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
334
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
335
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
336 @Tokenizer.token
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
337 class ErrorToken(Token):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
338 """Catchall for everything that didn't match other tokens."""
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
339
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
340 regexp = r'.*'
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
341 name = 'error'
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
342 priority = 100
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
343
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
344 def __init__(self, error):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
345 self.value = error
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
346
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
347 def parse(self, tokens, data):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
348 raise SyntaxError("Unexpexted '{0}' in jpath.".format(self.value))
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
349 yield None
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
350
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
351
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
352 class NoneToken(Token):
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
353 """Special token for marking lack of tokens."""
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
354
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
355 def parse(self, tokens, data):
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
356 yield data
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
357
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
358
3
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
359 # We only ever need one tokenizer
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
360 TOKENIZER = Tokenizer()
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
361
d0fecf87e3bc move tokenizer to separate class
sheep@wintermute
parents: 2
diff changeset
362
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
363 def get_all(jpath, data):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
364 """
5
e69a0207568a some small cleaup
sheep@wintermute
parents: 4
diff changeset
365 Get list of all elements matched by given jpath in the data datastructure.
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
366
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
367 >>> get_all('', 1)
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
368 [1]
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
369 >>> get_all('[1]', [1, 2])
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
370 [2]
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
371 >>> get_all('[*]', [1, 2])
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
372 [1, 2]
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
373 >>> get_all('*', [1, 2])
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
374 [1, 2]
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
375 >>> get_all('*[0]', [1, [2, 4], 3])
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
376 [2]
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
377 >>> get_all('*[0]', [1, [2, 4], 3, []])
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
378 [2]
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
379 >>> get_all('*.ziew', [1, {'ziew':2}, [3], []])
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
380 [2]
1
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
381 >>> get_all('..ziew', [1, 'ziew', {'ziew': 3, 'yawn': [{'ziew': 4}]}])
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
382 [3, 4]
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
383 >>> get_all('a.b', {'a': {'b': 3, 'c': {'b': 4}}})
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
384 [3]
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
385 >>> get_all('a..b', {'a': {'b': 3, 'c': {'b': 4}}})
1e04d0ab763b implemented ellipsis ..
sheep@wintermute
parents: 0
diff changeset
386 [3, 4]
2
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
387 >>> get_all('[1:]', [1, 2, 3])
25
28dc252c2300 Go back to the original slice semantics
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 24
diff changeset
388 [[2, 3]]
2
5b63c545fa4a added slices
sheep@wintermute
parents: 1
diff changeset
389 >>> get_all('[:-1]', [1, 2, 3])
25
28dc252c2300 Go back to the original slice semantics
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 24
diff changeset
390 [[1, 2]]
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
391 >>> get_all('[::2]', [1, 2, 3, 4])
25
28dc252c2300 Go back to the original slice semantics
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 24
diff changeset
392 [[1, 3]]
24
64328843ba3b one more slice test
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 23
diff changeset
393 >>> get_all('[::2][0]', [[1, 2], [3, 4], [5, 6]])
25
28dc252c2300 Go back to the original slice semantics
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 24
diff changeset
394 [[1, 2]]
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
395 >>> get_all('(x=1).y', [{'x':1, 'y':2}, {'x':0, 'y':3}, {'x':1, 'y':4}])
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
396 [2, 4]
7
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
397 >>> get_all('(x>0).y', [{'x':1, 'y':2}, {'x':0, 'y':3}, {'x':1, 'y':4}])
8b9133467904 add unequality operators to filter
sheep@wintermute
parents: 6
diff changeset
398 [2, 4]
6
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
399 >>> get_all('..', {'a':1, 'x':[2], 'c':[{'b': '3'}]})
ba0f10adb44b add filters
sheep@wintermute
parents: 5
diff changeset
400 [{'a': 1, 'x': [2], 'c': [{'b': '3'}]}, 1, [2], [{'b': '3'}], {'b': '3'}, 2]
19
b21203132ef6 Add a test for the issue reported by James Hendricks
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 18
diff changeset
401 >>> get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
b21203132ef6 Add a test for the issue reported by James Hendricks
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 18
diff changeset
402 [0, 1]
27
a607cb7f6333 Fix #1: KeyError instead of returning []
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 26
diff changeset
403 >>> get_all('a', {})
a607cb7f6333 Fix #1: KeyError instead of returning []
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 26
diff changeset
404 []
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
405 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
406
20
5c844a14d835 Fix the error with parsing get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 19
diff changeset
407 tokens = list(TOKENIZER.tokenize(jpath))
5c844a14d835 Fix the error with parsing get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 19
diff changeset
408 # Popping from the end of the list is faster.
5c844a14d835 Fix the error with parsing get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 19
diff changeset
409 tokens.reverse()
5c844a14d835 Fix the error with parsing get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 19
diff changeset
410 return list(Token.apply(tokens, data))
5c844a14d835 Fix the error with parsing get_all('a[*].b.c', {'a': [{'b': {'c': 0}}, {'b': {'c': 1}}]})
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 19
diff changeset
411
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
412
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
413 def get(jpath, data):
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
414 """
5
e69a0207568a some small cleaup
sheep@wintermute
parents: 4
diff changeset
415 Get the first element matched by given jpath in the data datastructure.
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
416
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
417 >>> get('', 3)
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
418 3
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
419 >>> get('ziew', {"ziew": 3})
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
420 3
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
421 >>> get('ziew.yawn', {"ziew": {"yawn": 3}})
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
422 3
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
423 >>> get('ziew["yawn"]', {"ziew": {"yawn": 3}})
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
424 3
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
425 >>> get('ziew[2]', {"ziew": [1, 2, 3]})
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
426 3
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
427 >>> get('[2]', [1, 2, 3])
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
428 3
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
429 >>> get('[*]', [1, 2, 3])
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
430 1
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
431 """
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
432
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
433 return get_all(jpath, data)[0]
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
434
28
0a216b982fd1 Bump version to 1.6
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents: 27
diff changeset
435
0
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
436 if __name__ == "__main__":
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
437 # Run tests when started.
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
438 import doctest
f39bd05f3be9 initial commit
sheep@wintermute
parents:
diff changeset
439 doctest.testmod()