@@ -306,9 +306,9 @@ def from_diff(cls, src, dst, optimization=True):
306306 True
307307 """
308308
309- info = _compare_info ()
310- _compare_values ('' , None , info , src , dst )
311- ops = [ op for op in info .execute ()]
309+ builder = DiffBuilder ()
310+ builder . _compare_values ('' , None , src , dst )
311+ ops = list ( builder .execute ())
312312 return cls (ops )
313313
314314 def to_string (self ):
@@ -648,7 +648,7 @@ def apply(self, obj):
648648 return obj
649649
650650
651- class _compare_info (object ):
651+ class DiffBuilder (object ):
652652
653653 def __init__ (self ):
654654 self .index_storage = [{}, {}]
@@ -724,104 +724,104 @@ def execute(self):
724724 yield curr [2 ].operation
725725 curr = curr [1 ]
726726
727- def _path_join (path , key ):
728- if key != None :
729- return path + '/' + str (key ).replace ('~' , '~0' ).replace ('/' , '~1' )
730- return path
731-
732- def _item_added (path , key , info , item ):
733- index = info .take_index (item , _ST_REMOVE )
734- if index != None :
735- op = index [2 ]
736- if type (op .key ) == int :
737- for v in info .iter_from (index ):
738- op .key = v ._on_undo_remove (op .path , op .key )
739- info .remove (index )
740- if op .location != _path_join (path , key ):
741- new_op = MoveOperation ({
742- 'op' : 'move' ,
743- 'from' : op .location ,
727+ def _item_added (self , path , key , item ):
728+ index = self .take_index (item , _ST_REMOVE )
729+ if index != None :
730+ op = index [2 ]
731+ if type (op .key ) == int :
732+ for v in self .iter_from (index ):
733+ op .key = v ._on_undo_remove (op .path , op .key )
734+ self .remove (index )
735+ if op .location != _path_join (path , key ):
736+ new_op = MoveOperation ({
737+ 'op' : 'move' ,
738+ 'from' : op .location ,
739+ 'path' : _path_join (path , key ),
740+ })
741+ self .insert (new_op )
742+ else :
743+ new_op = AddOperation ({
744+ 'op' : 'add' ,
744745 'path' : _path_join (path , key ),
746+ 'value' : item ,
745747 })
746- info .insert (new_op )
747- else :
748- new_op = AddOperation ({
749- 'op' : 'add' ,
748+ new_index = self .insert (new_op )
749+ self .store_index (item , new_index , _ST_ADD )
750+
751+ def _item_removed (self , path , key , item ):
752+ new_op = RemoveOperation ({
753+ 'op' : 'remove' ,
750754 'path' : _path_join (path , key ),
751755 'value' : item ,
752756 })
753- new_index = info .insert (new_op )
754- info .store_index (item , new_index , _ST_ADD )
755-
756- def _item_removed (path , key , info , item ):
757- new_op = RemoveOperation ({
758- 'op' : 'remove' ,
759- 'path' : _path_join (path , key ),
760- 'value' : item ,
761- })
762- index = info .take_index (item , _ST_ADD )
763- new_index = info .insert (new_op )
764- if index != None :
765- op = index [2 ]
766- if type (op .key ) == int :
767- for v in info .iter_from (index ):
768- op .key = v ._on_undo_add (op .path , op .key )
769- info .remove (index )
770- if new_op .location != op .location :
771- new_op = MoveOperation ({
772- 'op' : 'move' ,
773- 'from' : new_op .location ,
774- 'path' : op .location ,
775- })
776- new_index [2 ] = new_op
757+ index = self .take_index (item , _ST_ADD )
758+ new_index = self .insert (new_op )
759+ if index != None :
760+ op = index [2 ]
761+ if type (op .key ) == int :
762+ for v in self .iter_from (index ):
763+ op .key = v ._on_undo_add (op .path , op .key )
764+ self .remove (index )
765+ if new_op .location != op .location :
766+ new_op = MoveOperation ({
767+ 'op' : 'move' ,
768+ 'from' : new_op .location ,
769+ 'path' : op .location ,
770+ })
771+ new_index [2 ] = new_op
772+ else :
773+ self .remove (new_index )
777774 else :
778- info .remove (new_index )
779- else :
780- info .store_index (item , new_index , _ST_REMOVE )
781-
782- def _item_replaced (path , key , info , item ):
783- info .insert (ReplaceOperation ({
784- 'op' : 'replace' ,
785- 'path' : _path_join (path , key ),
786- 'value' : item ,
787- }))
788-
789- def _compare_dicts (path , info , src , dst ):
790- src_keys = _viewkeys (src )
791- dst_keys = _viewkeys (dst )
792- added_keys = dst_keys - src_keys
793- removed_keys = src_keys - dst_keys
794- for key in removed_keys :
795- _item_removed (path , str (key ), info , src [key ])
796- for key in added_keys :
797- _item_added (path , str (key ), info , dst [key ])
798- for key in src_keys & dst_keys :
799- _compare_values (path , key , info , src [key ], dst [key ])
800-
801- def _compare_lists (path , info , src , dst ):
802- len_src , len_dst = len (src ), len (dst )
803- max_len = max (len_src , len_dst )
804- min_len = min (len_src , len_dst )
805- for key in _range (max_len ):
806- if key < min_len :
807- old , new = src [key ], dst [key ]
808- if old == new :
809- continue
810- _item_removed (path , key , info , old )
811- _item_added (path , key , info , new )
812- elif len_src > len_dst :
813- _item_removed (path , len_dst , info , src [key ])
775+ self .store_index (item , new_index , _ST_REMOVE )
776+
777+ def _item_replaced (self , path , key , item ):
778+ self .insert (ReplaceOperation ({
779+ 'op' : 'replace' ,
780+ 'path' : _path_join (path , key ),
781+ 'value' : item ,
782+ }))
783+
784+ def _compare_dicts (self , path , src , dst ):
785+ src_keys = _viewkeys (src )
786+ dst_keys = _viewkeys (dst )
787+ added_keys = dst_keys - src_keys
788+ removed_keys = src_keys - dst_keys
789+ for key in removed_keys :
790+ self ._item_removed (path , str (key ), src [key ])
791+ for key in added_keys :
792+ self ._item_added (path , str (key ), dst [key ])
793+ for key in src_keys & dst_keys :
794+ self ._compare_values (path , key , src [key ], dst [key ])
795+
796+ def _compare_lists (self , path , src , dst ):
797+ len_src , len_dst = len (src ), len (dst )
798+ max_len = max (len_src , len_dst )
799+ min_len = min (len_src , len_dst )
800+ for key in _range (max_len ):
801+ if key < min_len :
802+ old , new = src [key ], dst [key ]
803+ if old == new :
804+ continue
805+ self ._item_removed (path , key , old )
806+ self ._item_added (path , key , new )
807+ elif len_src > len_dst :
808+ self ._item_removed (path , len_dst , src [key ])
809+ else :
810+ self ._item_added (path , key , dst [key ])
811+
812+ def _compare_values (self , path , key , src , dst ):
813+ if src == dst :
814+ return
815+ elif isinstance (src , dict ) and \
816+ isinstance (dst , dict ):
817+ self ._compare_dicts (_path_join (path , key ), src , dst )
818+ elif isinstance (src , list ) and \
819+ isinstance (dst , list ):
820+ self ._compare_lists (_path_join (path , key ), src , dst )
814821 else :
815- _item_added (path , key , info , dst [key ])
816-
817- def _compare_values (path , key , info , src , dst ):
818- if src == dst :
819- return
820- elif isinstance (src , dict ) and \
821- isinstance (dst , dict ):
822- _compare_dicts (_path_join (path , key ), info , src , dst )
823- elif isinstance (src , list ) and \
824- isinstance (dst , list ):
825- _compare_lists (_path_join (path , key ), info , src , dst )
826- else :
827- _item_replaced (path , key , info , dst )
822+ self ._item_replaced (path , key , dst )
823+
824+ def _path_join (path , key ):
825+ if key != None :
826+ return path + '/' + str (key ).replace ('~' , '~0' ).replace ('/' , '~1' )
827+ return path
0 commit comments