Skip to content

Commit a00b218

Browse files
author
Laurent PINSON
committed
new rule idx_comma + change Index() to handle indices instead of index
1 parent d7bec79 commit a00b218

File tree

2 files changed

+33
-20
lines changed

2 files changed

+33
-20
lines changed

jsonpath_ng/jsonpath.py

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -606,8 +606,8 @@ class Index(JSONPath):
606606
NOTE: For the concrete syntax of `[*]`, the abstract syntax is a Slice() with no parameters (equiv to `[:]`
607607
"""
608608

609-
def __init__(self, index):
610-
self.index = index
609+
def __init__(self, *indices):
610+
self.indices = indices
611611

612612
def find(self, datum):
613613
return self._find_base(datum, create=False)
@@ -621,10 +621,12 @@ def _find_base(self, datum, create):
621621
if datum.value == {}:
622622
datum.value = _create_list_key(datum.value)
623623
self._pad_value(datum.value)
624-
if datum.value and len(datum.value) > self.index:
625-
return [DatumInContext(datum.value[self.index], path=self, context=datum)]
626-
else:
627-
return []
624+
rv = []
625+
for index in self.indices:
626+
# invalid indices do not crash, return [] instead
627+
if datum.value and len(datum.value) > index:
628+
rv += [DatumInContext(datum.value[index], path=self, context=datum)]
629+
return rv
628630

629631
def update(self, data, val):
630632
return self._update_base(data, val, create=False)
@@ -638,31 +640,38 @@ def _update_base(self, data, val, create):
638640
data = _create_list_key(data)
639641
self._pad_value(data)
640642
if hasattr(val, '__call__'):
641-
val.__call__(data[self.index], data, self.index)
642-
elif len(data) > self.index:
643-
data[self.index] = val
643+
for index in self.indices:
644+
val.__call__(data[index], data, index)
645+
else:
646+
if not isinstance(val, list):
647+
val = [val]
648+
# allows somelist[5,1,2] = [some_value, another_value, third_value]
649+
for index in self.indices:
650+
if len(data) > index:
651+
data[index] = val.pop(0)
644652
return data
645653

646654
def filter(self, fn, data):
647-
if fn(data[self.index]):
648-
data.pop(self.index) # relies on mutation :(
655+
for index in self.indices:
656+
if fn(data[index]):
657+
data.pop(index) # relies on mutation :(
649658
return data
650659

651660
def __eq__(self, other):
652-
return isinstance(other, Index) and self.index == other.index
661+
return isinstance(other, Index) and sorted(self.indices) == sorted(other.indices)
653662

654663
def __str__(self):
655-
return '[%i]' % self.index
664+
return '[%i]' % self.indices
656665

657666
def __repr__(self):
658-
return '%s(index=%r)' % (self.__class__.__name__, self.index)
667+
return '%s(indices=%r)' % (self.__class__.__name__, self.indices)
659668

660669
def _pad_value(self, value):
661-
if len(value) <= self.index:
662-
pad = self.index - len(value) + 1
670+
_max = max(self.indices)
671+
if len(value) <= _max:
672+
pad = _max - len(value) + 1
663673
value += [{} for __ in range(pad)]
664674

665-
666675
class Slice(JSONPath):
667676
"""
668677
JSONPath matching a slice of an array.

jsonpath_ng/parser.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def p_jsonpath_root(self, p):
120120

121121
def p_jsonpath_idx(self, p):
122122
"jsonpath : '[' idx ']'"
123-
p[0] = p[2]
123+
p[0] = Index(*p[2])
124124

125125
def p_jsonpath_slice(self, p):
126126
"jsonpath : '[' slice ']'"
@@ -136,7 +136,7 @@ def p_jsonpath_child_fieldbrackets(self, p):
136136

137137
def p_jsonpath_child_idxbrackets(self, p):
138138
"jsonpath : jsonpath '[' idx ']'"
139-
p[0] = Child(p[1], p[3])
139+
p[0] = Child(p[1], Index(*p[3]))
140140

141141
def p_jsonpath_child_slicebrackets(self, p):
142142
"jsonpath : jsonpath '[' slice ']'"
@@ -165,8 +165,12 @@ def p_fields_comma(self, p):
165165

166166
def p_idx(self, p):
167167
"idx : NUMBER"
168-
p[0] = Index(p[1])
168+
p[0] = [p[1]]
169169

170+
def p_idx_comma(self, p):
171+
"idx : idx ',' idx "
172+
p[0] = p[1] + p[3]
173+
170174
def p_slice_any(self, p):
171175
"slice : '*'"
172176
p[0] = Slice()

0 commit comments

Comments
 (0)