@@ -171,6 +171,14 @@ def make_patch(src, dst):
171
171
>>> new == dst
172
172
True
173
173
"""
174
+
175
+ # TODO: fix patch optimiztion and remove the following check
176
+ # fix when patch with optimization is incorrect
177
+ patch = JsonPatch .from_diff (src , dst )
178
+ new = patch .apply (src )
179
+ if new != dst :
180
+ return JsonPatch .from_diff (src , dst , False )
181
+
174
182
return JsonPatch .from_diff (src , dst )
175
183
176
184
@@ -268,7 +276,7 @@ def from_string(cls, patch_str):
268
276
return cls (patch )
269
277
270
278
@classmethod
271
- def from_diff (cls , src , dst ):
279
+ def from_diff (cls , src , dst , optimization = True ):
272
280
"""Creates JsonPatch instance based on comparing of two document
273
281
objects. Json patch would be created for `src` argument against `dst`
274
282
one.
@@ -320,7 +328,7 @@ def compare_dicts(path, src, dst):
320
328
'value' : dst [key ]}
321
329
322
330
def compare_lists (path , src , dst ):
323
- return _compare_lists (path , src , dst )
331
+ return _compare_lists (path , src , dst , optimization = optimization )
324
332
325
333
return cls (list (compare_values ([], src , dst )))
326
334
@@ -561,9 +569,12 @@ def apply(self, obj):
561
569
return obj
562
570
563
571
564
- def _compare_lists (path , src , dst ):
572
+ def _compare_lists (path , src , dst , optimization = True ):
565
573
"""Compares two lists objects and return JSON patch about."""
566
- return _optimize (_compare (path , src , dst , * _split_by_common_seq (src , dst )))
574
+ patch = list (_compare (path , src , dst , * _split_by_common_seq (src , dst )))
575
+ if optimization :
576
+ return list (_optimize (patch ))
577
+ return patch
567
578
568
579
569
580
def _longest_common_subseq (src , dst ):
@@ -770,7 +781,16 @@ def _optimize_using_replace(prev, cur):
770
781
if cur ['op' ] == 'add' :
771
782
# make recursive patch
772
783
patch = make_patch (prev ['value' ], cur ['value' ])
773
- if len (patch .patch ) == 1 and patch .patch [0 ]['op' ] != 'remove' :
784
+ # check case when dict "remove" is less than "add" and has a same key
785
+ if isinstance (prev ['value' ], dict ) and isinstance (cur ['value' ], dict ) and len (prev ['value' ].keys ()) == 1 :
786
+ prev_set = set (prev ['value' ].keys ())
787
+ cur_set = set (cur ['value' ].keys ())
788
+ if prev_set & cur_set == prev_set :
789
+ patch = make_patch (cur ['value' ], prev ['value' ])
790
+
791
+ if len (patch .patch ) == 1 and \
792
+ patch .patch [0 ]['op' ] != 'remove' and \
793
+ patch .patch [0 ]['path' ] and patch .patch [0 ]['path' ].split ('/' )[1 ] in prev ['value' ]:
774
794
prev ['path' ] = prev ['path' ] + patch .patch [0 ]['path' ]
775
795
prev ['value' ] = patch .patch [0 ]['value' ]
776
796
else :
0 commit comments