@@ -379,6 +379,23 @@ def __eq__(self, other):
379379 def __ne__ (self , other ):
380380 return not (self == other )
381381
382+ @property
383+ def path (self ):
384+ return '/' .join (self .pointer .parts [:- 1 ])
385+
386+ @property
387+ def key (self ):
388+ try :
389+ return int (self .pointer .parts [- 1 ])
390+ except ValueError :
391+ return self .pointer .parts [- 1 ]
392+
393+ @key .setter
394+ def key (self , value ):
395+ self .pointer .parts [- 1 ] = str (value )
396+ self .location = self .pointer .path
397+ self .operation ['path' ] = self .location
398+
382399
383400class RemoveOperation (PatchOperation ):
384401 """Removes an object property or an array element."""
@@ -393,6 +410,22 @@ def apply(self, obj):
393410
394411 return obj
395412
413+ def _on_undo_remove (self , path , key ):
414+ if self .path == path :
415+ if self .key >= key :
416+ self .key += 1
417+ else :
418+ key -= 1
419+ return key
420+
421+ def _on_undo_add (self , path , key ):
422+ if self .path == path :
423+ if self .key > key :
424+ self .key -= 1
425+ else :
426+ key -= 1
427+ return key
428+
396429
397430class AddOperation (PatchOperation ):
398431 """Adds an object property or an array element."""
@@ -427,6 +460,22 @@ def apply(self, obj):
427460
428461 return obj
429462
463+ def _on_undo_remove (self , path , key ):
464+ if self .path == path :
465+ if self .key > key :
466+ self .key += 1
467+ else :
468+ key += 1
469+ return key
470+
471+ def _on_undo_add (self , path , key ):
472+ if self .path == path :
473+ if self .key > key :
474+ self .key -= 1
475+ else :
476+ key += 1
477+ return key
478+
430479
431480class ReplaceOperation (PatchOperation ):
432481 """Replaces an object property or an array element by new value."""
@@ -457,6 +506,12 @@ def apply(self, obj):
457506 subobj [part ] = value
458507 return obj
459508
509+ def _on_undo_remove (self , path , key ):
510+ return key
511+
512+ def _on_undo_add (self , path , key ):
513+ return key
514+
460515
461516class MoveOperation (PatchOperation ):
462517 """Moves an object property or an array element to new location."""
@@ -495,6 +550,51 @@ def apply(self, obj):
495550
496551 return obj
497552
553+ @property
554+ def oldpath (self ):
555+ oldptr = JsonPointer (self .operation ['from' ])
556+ return '/' .join (oldptr .parts [:- 1 ])
557+
558+ @property
559+ def oldkey (self ):
560+ oldptr = JsonPointer (self .operation ['from' ])
561+ try :
562+ return int (oldptr .parts [- 1 ])
563+ except TypeError :
564+ return oldptr .parts [- 1 ]
565+
566+ @oldkey .setter
567+ def oldkey (self , value ):
568+ oldptr = JsonPointer (self .operation ['from' ])
569+ oldptr .parts [- 1 ] = str (value )
570+ self .operation ['from' ] = oldptr .path
571+
572+ def _on_undo_remove (self , path , key ):
573+ if self .oldpath == path :
574+ if self .oldkey >= key :
575+ self .oldkey += 1
576+ else :
577+ key -= 1
578+ if self .path == path :
579+ if self .key > key :
580+ self .key += 1
581+ else :
582+ key += 1
583+ return key
584+
585+ def _on_undo_add (self , path , key ):
586+ if self .oldpath == path :
587+ if self .oldkey > key :
588+ self .oldkey -= 1
589+ else :
590+ key -= 1
591+ if self .path == path :
592+ if self .key > key :
593+ self .key -= 1
594+ else :
595+ key += 1
596+ return key
597+
498598
499599class TestOperation (PatchOperation ):
500600 """Test value by specified location."""
@@ -610,115 +710,16 @@ def execute(self):
610710 while curr is not root :
611711 if curr [1 ] is not root :
612712 op_first , op_second = curr [2 ], curr [1 ][2 ]
613- if op_first .key == op_second .key and \
614- op_first .path == op_second .path and \
615- type (op_first ) == _op_remove and \
616- type (op_second ) == _op_add :
617- yield _op_replace ( op_second . path , op_second .key , op_second .value ). get ()
713+ if ( # op_first.key == op_second.key and \
714+ op_first .location == op_second .location and \
715+ type (op_first ) == RemoveOperation and \
716+ type (op_second ) == AddOperation ) :
717+ yield ReplaceOperation ({ 'op' : 'replace' , 'path' : op_second .location , 'value' : op_second .operation [ ' value' ]}). operation
618718 curr = curr [1 ][1 ]
619719 continue
620- yield curr [2 ].get ()
720+ yield curr [2 ].operation
621721 curr = curr [1 ]
622722
623- class _op_base (object ):
624- def __init__ (self , path , key , value ):
625- self .path = path
626- self .key = key
627- self .value = value
628-
629- def __repr__ (self ):
630- return str (self .get ())
631-
632- class _op_add (_op_base ):
633- def _on_undo_remove (self , path , key ):
634- if self .path == path :
635- if self .key > key :
636- self .key += 1
637- else :
638- key += 1
639- return key
640-
641- def _on_undo_add (self , path , key ):
642- if self .path == path :
643- if self .key > key :
644- self .key -= 1
645- else :
646- key += 1
647- return key
648-
649- def get (self ):
650- return {'op' : 'add' , 'path' : _path_join (self .path , self .key ), 'value' : self .value }
651-
652- class _op_remove (_op_base ):
653- def _on_undo_remove (self , path , key ):
654- if self .path == path :
655- if self .key >= key :
656- self .key += 1
657- else :
658- key -= 1
659- return key
660-
661- def _on_undo_add (self , path , key ):
662- if self .path == path :
663- if self .key > key :
664- self .key -= 1
665- else :
666- key -= 1
667- return key
668-
669- def get (self ):
670- return {'op' : 'remove' , 'path' : _path_join (self .path , self .key )}
671-
672- class _op_replace (_op_base ):
673- def _on_undo_remove (self , path , key ):
674- return key
675-
676- def _on_undo_add (self , path , key ):
677- return key
678-
679- def get (self ):
680- return {'op' : 'replace' , 'path' : _path_join (self .path , self .key ), 'value' : self .value }
681-
682-
683- class _op_move (object ):
684- def __init__ (self , oldpath , oldkey , path , key ):
685- self .oldpath = oldpath
686- self .oldkey = oldkey
687- self .path = path
688- self .key = key
689-
690- def _on_undo_remove (self , path , key ):
691- if self .oldpath == path :
692- if self .oldkey >= key :
693- self .oldkey += 1
694- else :
695- key -= 1
696- if self .path == path :
697- if self .key > key :
698- self .key += 1
699- else :
700- key += 1
701- return key
702-
703- def _on_undo_add (self , path , key ):
704- if self .oldpath == path :
705- if self .oldkey > key :
706- self .oldkey -= 1
707- else :
708- key -= 1
709- if self .path == path :
710- if self .key > key :
711- self .key -= 1
712- else :
713- key += 1
714- return key
715-
716- def get (self ):
717- return {'op' : 'move' , 'path' : _path_join (self .path , self .key ), 'from' : _path_join (self .oldpath , self .oldkey )}
718-
719- def __repr__ (self ):
720- return str (self .get ())
721-
722723def _path_join (path , key ):
723724 if key != None :
724725 return path + '/' + str (key ).replace ('~' , '~0' ).replace ('/' , '~1' )
@@ -732,16 +733,16 @@ def _item_added(path, key, info, item):
732733 for v in info .iter_from (index ):
733734 op .key = v ._on_undo_remove (op .path , op .key )
734735 info .remove (index )
735- if op .path != path or op . key != key :
736- new_op = _op_move ( op . path , op .key , path , key )
736+ if op .location != _path_join ( path , key ) :
737+ new_op = MoveOperation ({ 'op' : 'move' , 'from' : op .location , ' path' : _path_join ( path , key )} )
737738 info .insert (new_op )
738739 else :
739- new_op = _op_add ( path , key , item )
740+ new_op = AddOperation ({ 'op' : 'add' , ' path' : _path_join ( path , key ), 'value' : item } )
740741 new_index = info .insert (new_op )
741742 info .store_index (item , new_index , _ST_ADD )
742743
743744def _item_removed (path , key , info , item ):
744- new_op = _op_remove ( path , key , item )
745+ new_op = RemoveOperation ({ 'op' : 'remove' , ' path' : _path_join ( path , key ), 'value' : item } )
745746 index = info .take_index (item , _ST_ADD )
746747 new_index = info .insert (new_op )
747748 if index != None :
@@ -750,16 +751,16 @@ def _item_removed(path, key, info, item):
750751 for v in info .iter_from (index ):
751752 op .key = v ._on_undo_add (op .path , op .key )
752753 info .remove (index )
753- if new_op .path != op .path or new_op . key != op . key :
754- new_op = _op_move ( new_op . path , new_op .key , op . path , op .key )
754+ if new_op .location != op .location :
755+ new_op = MoveOperation ({ 'op' : 'move' , 'from' : new_op .location , ' path' : op .location } )
755756 new_index [2 ] = new_op
756757 else :
757758 info .remove (new_index )
758759 else :
759760 info .store_index (item , new_index , _ST_REMOVE )
760761
761762def _item_replaced (path , key , info , item ):
762- info .insert (_op_replace ( path , key , item ))
763+ info .insert (ReplaceOperation ({ 'op' : 'replace' , ' path' : _path_join ( path , key ), 'value' : item } ))
763764
764765def _compare_dicts (path , info , src , dst ):
765766 src_keys = _viewkeys (src )
0 commit comments