@@ -26,7 +26,11 @@ def find(self, data):
26
26
raise NotImplementedError ()
27
27
28
28
def update (self , data , val ):
29
- "Returns `data` with the specified path replaced by `val`"
29
+ """
30
+ Returns `data` with the specified path replaced by `val`. Only updates
31
+ if the specified path exists.
32
+ """
33
+
30
34
raise NotImplementedError ()
31
35
32
36
def child (self , child ):
@@ -227,6 +231,11 @@ def find(self, datum):
227
231
if not isinstance (subdata , AutoIdForDatum )
228
232
for submatch in self .right .find (subdata )]
229
233
234
+ def update (self , data , val ):
235
+ for datum in self .left .find (data ):
236
+ self .right .update (datum .value , val )
237
+ return data
238
+
230
239
def __eq__ (self , other ):
231
240
return isinstance (other , Child ) and self .left == other .left and self .right == other .right
232
241
@@ -274,6 +283,11 @@ def __init__(self, left, right):
274
283
def find (self , data ):
275
284
return [subdata for subdata in self .left .find (data ) if self .right .find (subdata )]
276
285
286
+ def update (self , data , val ):
287
+ for datum in self .find (data ):
288
+ datum .path .update (data , val )
289
+ return data
290
+
277
291
def __str__ (self ):
278
292
return '%s where %s' % (self .left , self .right )
279
293
@@ -329,6 +343,33 @@ def match_recursively(datum):
329
343
def is_singular ():
330
344
return False
331
345
346
+ def update (self , data , val ):
347
+ # Get all left matches into a list
348
+ left_matches = self .left .find (data )
349
+ if not isinstance (left_matches , list ):
350
+ left_matches = [left_matches ]
351
+
352
+ def update_recursively (data ):
353
+ # Update only mutable values corresponding to JSON types
354
+ if not (isinstance (data , list ) or isinstance (data , dict )):
355
+ return
356
+
357
+ self .right .update (data , val )
358
+
359
+ # Manually do the * or [*] to avoid coercion and recurse just the right-hand pattern
360
+ if isinstance (data , list ):
361
+ for i in range (0 , len (data )):
362
+ update_recursively (data [i ])
363
+
364
+ elif isinstance (data , dict ):
365
+ for field in data .keys ():
366
+ update_recursively (data [field ])
367
+
368
+ for submatch in left_matches :
369
+ update_recursively (submatch .value )
370
+
371
+ return data
372
+
332
373
def __str__ (self ):
333
374
return '%s..%s' % (self .left , self .right )
334
375
@@ -415,6 +456,12 @@ def find(self, datum):
415
456
for field_datum in [self .get_field_datum (datum , field ) for field in self .reified_fields (datum )]
416
457
if field_datum is not None ]
417
458
459
+ def update (self , data , val ):
460
+ for field in self .reified_fields (DatumInContext .wrap (data )):
461
+ if field in data :
462
+ data [field ] = val
463
+ return data
464
+
418
465
def __str__ (self ):
419
466
return ',' .join (map (str , self .fields ))
420
467
@@ -445,6 +492,11 @@ def find(self, datum):
445
492
else :
446
493
return []
447
494
495
+ def update (self , data , val ):
496
+ if len (data ) > self .index :
497
+ data [self .index ] = val
498
+ return data
499
+
448
500
def __eq__ (self , other ):
449
501
return isinstance (other , Index ) and self .index == other .index
450
502
@@ -495,6 +547,11 @@ def find(self, datum):
495
547
else :
496
548
return [DatumInContext (datum .value [i ], path = Index (i ), context = datum ) for i in range (0 , len (datum .value ))[self .start :self .end :self .step ]]
497
549
550
+ def update (self , data , val ):
551
+ for datum in self .find (data ):
552
+ datum .path .update (data , val )
553
+ return data
554
+
498
555
def __str__ (self ):
499
556
if self .start == None and self .end == None and self .step == None :
500
557
return '[*]'
0 commit comments