Skip to content

Commit 1235def

Browse files
committed
Implemented update method on most JSONPath descendents. Tests included.
1 parent 5a4b2c7 commit 1235def

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

jsonpath_rw/jsonpath.py

+29
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ def find(self, datum):
227227
if not isinstance(subdata, AutoIdForDatum)
228228
for submatch in self.right.find(subdata)]
229229

230+
def update(self, data, val):
231+
for datum in self.left.find(data):
232+
self.right.update(datum.value, val)
233+
return data
234+
230235
def __eq__(self, other):
231236
return isinstance(other, Child) and self.left == other.left and self.right == other.right
232237

@@ -274,6 +279,11 @@ def __init__(self, left, right):
274279
def find(self, data):
275280
return [subdata for subdata in self.left.find(data) if self.right.find(subdata)]
276281

282+
def update(self, data, val):
283+
for datum in self.find(data):
284+
datum.path.update(data, val)
285+
return data
286+
277287
def __str__(self):
278288
return '%s where %s' % (self.left, self.right)
279289

@@ -329,6 +339,11 @@ def match_recursively(datum):
329339
def is_singular():
330340
return False
331341

342+
def update(self, data, val):
343+
for datum in self.left.find(data):
344+
self.right.update(datum.value, val)
345+
return data
346+
332347
def __str__(self):
333348
return '%s..%s' % (self.left, self.right)
334349

@@ -415,6 +430,11 @@ def find(self, datum):
415430
for field_datum in [self.get_field_datum(datum, field) for field in self.reified_fields(datum)]
416431
if field_datum is not None]
417432

433+
def update(self, data, val):
434+
for field in self.reified_fields(DatumInContext.wrap(data)):
435+
data[field] = val
436+
return data
437+
418438
def __str__(self):
419439
return ','.join(map(str, self.fields))
420440

@@ -445,6 +465,10 @@ def find(self, datum):
445465
else:
446466
return []
447467

468+
def update(self, data, val):
469+
data[self.index] = val
470+
return data
471+
448472
def __eq__(self, other):
449473
return isinstance(other, Index) and self.index == other.index
450474

@@ -495,6 +519,11 @@ def find(self, datum):
495519
else:
496520
return [DatumInContext(datum.value[i], path=Index(i), context=datum) for i in range(0, len(datum.value))[self.start:self.end:self.step]]
497521

522+
def update(self, data, val):
523+
for datum in self.find(data):
524+
datum.path.update(data, val)
525+
return data
526+
498527
def __str__(self):
499528
if self.start == None and self.end == None and self.step == None:
500529
return '[*]'

tests/test_update.py

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from __future__ import unicode_literals, print_function, absolute_import, division, generators, nested_scopes
2+
3+
import unittest
4+
import logging
5+
6+
from jsonpath_rw.parser import parse
7+
8+
9+
class TestUpdate(unittest.TestCase):
10+
11+
@classmethod
12+
def setup_class(cls):
13+
logging.basicConfig()
14+
15+
def check_update_cases(self, test_cases):
16+
for original, expr_str, value, expected in test_cases:
17+
print('parse(%r).update(%r, %r) =?= %r'
18+
% (expr_str, original, value, expected))
19+
expr = parse(expr_str)
20+
actual = expr.update(original, value)
21+
assert actual == expected
22+
23+
def test_update_root(self):
24+
self.check_update_cases([
25+
('foo', '$', 'bar', 'bar')
26+
])
27+
28+
def test_update_this(self):
29+
self.check_update_cases([
30+
('foo', '`this`', 'bar', 'bar')
31+
])
32+
33+
def test_update_fields(self):
34+
self.check_update_cases([
35+
({'foo': 1}, 'foo', 5, {'foo': 5}),
36+
({}, 'foo', 1, {'foo': 1}),
37+
({'foo': 1, 'bar': 2}, '$.*', 3, {'foo': 3, 'bar': 3})
38+
])
39+
40+
def test_update_child(self):
41+
self.check_update_cases([
42+
({'foo': 'bar'}, '$.foo', 'baz', {'foo': 'baz'}),
43+
({'foo': {'bar': 1}}, 'foo.bar', 'baz', {'foo': {'bar': 'baz'}})
44+
])
45+
46+
def test_update_where(self):
47+
self.check_update_cases([
48+
({'foo': {'bar': {'baz': 1}}, 'bar': {'baz': 2}},
49+
'*.bar where baz', 5, {'foo': {'bar': 5}, 'bar': {'baz': 2}})
50+
])
51+
52+
def test_update_descendants(self):
53+
self.check_update_cases([
54+
({'foo': {'bar': 1, 'flag': 1}, 'baz': {'bar': 2}},
55+
'* where flag .. bar', 3,
56+
{'foo': {'bar': 3, 'flag': 1}, 'baz': {'bar': 2}})
57+
])
58+
59+
def test_update_index(self):
60+
self.check_update_cases([
61+
(['foo', 'bar', 'baz'], '[0]', 'test', ['test', 'bar', 'baz'])
62+
])
63+
64+
def test_update_slice(self):
65+
self.check_update_cases([
66+
(['foo', 'bar', 'baz'], '[0:2]', 'test', ['test', 'test', 'baz'])
67+
])

0 commit comments

Comments
 (0)