@@ -379,6 +379,23 @@ def __eq__(self, other):
379
379
def __ne__ (self , other ):
380
380
return not (self == other )
381
381
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
+
382
399
383
400
class RemoveOperation (PatchOperation ):
384
401
"""Removes an object property or an array element."""
@@ -393,6 +410,22 @@ def apply(self, obj):
393
410
394
411
return obj
395
412
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
+
396
429
397
430
class AddOperation (PatchOperation ):
398
431
"""Adds an object property or an array element."""
@@ -427,6 +460,22 @@ def apply(self, obj):
427
460
428
461
return obj
429
462
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
+
430
479
431
480
class ReplaceOperation (PatchOperation ):
432
481
"""Replaces an object property or an array element by new value."""
@@ -457,6 +506,12 @@ def apply(self, obj):
457
506
subobj [part ] = value
458
507
return obj
459
508
509
+ def _on_undo_remove (self , path , key ):
510
+ return key
511
+
512
+ def _on_undo_add (self , path , key ):
513
+ return key
514
+
460
515
461
516
class MoveOperation (PatchOperation ):
462
517
"""Moves an object property or an array element to new location."""
@@ -495,6 +550,51 @@ def apply(self, obj):
495
550
496
551
return obj
497
552
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
+
498
598
499
599
class TestOperation (PatchOperation ):
500
600
"""Test value by specified location."""
@@ -610,115 +710,16 @@ def execute(self):
610
710
while curr is not root :
611
711
if curr [1 ] is not root :
612
712
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
618
718
curr = curr [1 ][1 ]
619
719
continue
620
- yield curr [2 ].get ()
720
+ yield curr [2 ].operation
621
721
curr = curr [1 ]
622
722
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
-
722
723
def _path_join (path , key ):
723
724
if key != None :
724
725
return path + '/' + str (key ).replace ('~' , '~0' ).replace ('/' , '~1' )
@@ -732,16 +733,16 @@ def _item_added(path, key, info, item):
732
733
for v in info .iter_from (index ):
733
734
op .key = v ._on_undo_remove (op .path , op .key )
734
735
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 )} )
737
738
info .insert (new_op )
738
739
else :
739
- new_op = _op_add ( path , key , item )
740
+ new_op = AddOperation ({ 'op' : 'add' , ' path' : _path_join ( path , key ), 'value' : item } )
740
741
new_index = info .insert (new_op )
741
742
info .store_index (item , new_index , _ST_ADD )
742
743
743
744
def _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 } )
745
746
index = info .take_index (item , _ST_ADD )
746
747
new_index = info .insert (new_op )
747
748
if index != None :
@@ -750,16 +751,16 @@ def _item_removed(path, key, info, item):
750
751
for v in info .iter_from (index ):
751
752
op .key = v ._on_undo_add (op .path , op .key )
752
753
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 } )
755
756
new_index [2 ] = new_op
756
757
else :
757
758
info .remove (new_index )
758
759
else :
759
760
info .store_index (item , new_index , _ST_REMOVE )
760
761
761
762
def _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 } ))
763
764
764
765
def _compare_dicts (path , info , src , dst ):
765
766
src_keys = _viewkeys (src )
0 commit comments