1111 strings , short_repr , numbers ,
1212 np_ndarray , np_array_factory , numpy_dtypes , get_doc ,
1313 not_found , numpy_dtype_string_to_type , dict_ ,
14- Opcode , FlatDeltaRow , UnkownValueCode ,
14+ Opcode , FlatDeltaRow , UnkownValueCode , FlatDataAction ,
15+ OPCODE_TAG_TO_FLAT_DATA_ACTION ,
16+ FLAT_DATA_ACTION_TO_OPCODE_TAG ,
1517)
1618from deepdiff .path import (
1719 _path_to_elements , _get_nested_obj , _get_nested_obj_and_force ,
@@ -877,8 +879,33 @@ def dumps(self):
877879 def to_dict (self ):
878880 return dict (self .diff )
879881
882+ def _flatten_iterable_opcodes (self , _parse_path ):
883+ """
884+ Converts op_codes to FlatDeltaRows
885+ """
886+ result = []
887+ for path , op_codes in self .diff ['_iterable_opcodes' ].items ():
888+ for op_code in op_codes :
889+ result .append (
890+ FlatDeltaRow (
891+ path = _parse_path (path ),
892+ action = OPCODE_TAG_TO_FLAT_DATA_ACTION [op_code .tag ],
893+ value = op_code .new_values ,
894+ old_value = op_code .old_values ,
895+ type = type (op_code .new_values ),
896+ old_type = type (op_code .old_values ),
897+ new_path = None ,
898+ t1_from_index = op_code .t1_from_index ,
899+ t1_to_index = op_code .t1_to_index ,
900+ t2_from_index = op_code .t2_from_index ,
901+ t2_to_index = op_code .t2_to_index ,
902+
903+ )
904+ )
905+ return result
906+
880907 @staticmethod
881- def _get_flat_row (action , info , _parse_path , keys_and_funcs ):
908+ def _get_flat_row (action , info , _parse_path , keys_and_funcs , report_type_changes = True ):
882909 for path , details in info .items ():
883910 row = {'path' : _parse_path (path ), 'action' : action }
884911 for key , new_key , func in keys_and_funcs :
@@ -887,6 +914,11 @@ def _get_flat_row(action, info, _parse_path, keys_and_funcs):
887914 row [new_key ] = func (details [key ])
888915 else :
889916 row [new_key ] = details [key ]
917+ if report_type_changes :
918+ if 'value' in row and 'type' not in row :
919+ row ['type' ] = type (row ['value' ])
920+ if 'old_value' in row and 'old_type' not in row :
921+ row ['old_type' ] = type (row ['old_value' ])
890922 yield FlatDeltaRow (** row )
891923
892924 @staticmethod
@@ -918,28 +950,44 @@ def _from_flat_dicts(flat_dict_list):
918950 if action in FLATTENING_NEW_ACTION_MAP :
919951 action = FLATTENING_NEW_ACTION_MAP [action ]
920952 index = path .pop ()
921- if action in {'attribute_added' , 'attribute_removed' }:
953+ if action in {
954+ FlatDataAction .attribute_added ,
955+ FlatDataAction .attribute_removed ,
956+ }:
922957 root_element = ('root' , GETATTR )
923958 else :
924959 root_element = ('root' , GET )
925- path_str = stringify_path (path , root_element = root_element ) # We need the string path
960+ if isinstance (path , str ):
961+ path_str = path
962+ else :
963+ path_str = stringify_path (path , root_element = root_element ) # We need the string path
926964 if new_path and new_path != path :
927965 new_path = stringify_path (new_path , root_element = root_element )
928966 else :
929967 new_path = None
930968 if action not in result :
931969 result [action ] = {}
932- if action in {'iterable_items_added_at_indexes' , 'iterable_items_removed_at_indexes' }:
970+ if action in {
971+ 'iterable_items_added_at_indexes' ,
972+ 'iterable_items_removed_at_indexes' ,
973+ }:
933974 if path_str not in result [action ]:
934975 result [action ][path_str ] = {}
935976 result [action ][path_str ][index ] = value
936- elif action in {'set_item_added' , 'set_item_removed' }:
977+ elif action in {
978+ FlatDataAction .set_item_added ,
979+ FlatDataAction .set_item_removed
980+ }:
937981 if path_str not in result [action ]:
938982 result [action ][path_str ] = set ()
939983 result [action ][path_str ].add (value )
940984 elif action in {
941- 'dictionary_item_added' , 'dictionary_item_removed' ,
942- 'attribute_removed' , 'attribute_added' , 'iterable_item_added' , 'iterable_item_removed' ,
985+ FlatDataAction .dictionary_item_added ,
986+ FlatDataAction .dictionary_item_removed ,
987+ FlatDataAction .attribute_removed ,
988+ FlatDataAction .attribute_added ,
989+ FlatDataAction .iterable_item_added ,
990+ FlatDataAction .iterable_item_removed ,
943991 }:
944992 result [action ][path_str ] = value
945993 elif action == 'values_changed' :
@@ -959,8 +1007,29 @@ def _from_flat_dicts(flat_dict_list):
9591007 ]:
9601008 if elem_value != UnkownValueCode :
9611009 result [action ][path_str ][elem ] = elem_value
962- elif action == ' iterable_item_moved' :
1010+ elif action == FlatDataAction . iterable_item_moved :
9631011 result [action ][path_str ] = {'value' : value }
1012+ elif action in {
1013+ FlatDataAction .iterable_items_inserted ,
1014+ FlatDataAction .iterable_items_deleted ,
1015+ FlatDataAction .iterable_items_replaced ,
1016+ FlatDataAction .iterable_items_equal ,
1017+ }:
1018+ if '_iterable_opcodes' not in result :
1019+ result ['_iterable_opcodes' ] = {}
1020+ if path_str not in result ['_iterable_opcodes' ]:
1021+ result ['_iterable_opcodes' ][path_str ] = []
1022+ result ['_iterable_opcodes' ][path_str ].append (
1023+ Opcode (
1024+ tag = FLAT_DATA_ACTION_TO_OPCODE_TAG [action ],
1025+ t1_from_index = flat_dict .get ('t1_from_index' ),
1026+ t1_to_index = flat_dict .get ('t1_to_index' ),
1027+ t2_from_index = flat_dict .get ('t2_from_index' ),
1028+ t2_to_index = flat_dict .get ('t2_to_index' ),
1029+ new_values = flat_dict .get ('value' ),
1030+ old_values = flat_dict .get ('old_value' ),
1031+ )
1032+ )
9641033 if new_path :
9651034 result [action ][path_str ]['new_path' ] = new_path
9661035
@@ -1060,6 +1129,9 @@ def to_flat_rows(self, include_action_in_path=False, report_type_changes=True) -
10601129 'iterable_items_removed_at_indexes' : 'unordered_iterable_item_removed' ,
10611130 }
10621131 for action , info in self .diff .items ():
1132+ if action == '_iterable_opcodes' :
1133+ result .extend (self ._flatten_iterable_opcodes (_parse_path = _parse_path ))
1134+ continue
10631135 if action .startswith ('_' ):
10641136 continue
10651137 if action in FLATTENING_NEW_ACTION_MAP :
@@ -1072,12 +1144,20 @@ def to_flat_rows(self, include_action_in_path=False, report_type_changes=True) -
10721144 path2 .append ((index , 'GET' ))
10731145 else :
10741146 path2 .append (index )
1075- result .append (FlatDeltaRow (path = path2 , value = value , action = new_action ))
1147+ if report_type_changes :
1148+ row = FlatDeltaRow (path = path2 , value = value , action = new_action , type = type (value ))
1149+ else :
1150+ row = FlatDeltaRow (path = path2 , value = value , action = new_action )
1151+ result .append (row )
10761152 elif action in {'set_item_added' , 'set_item_removed' }:
10771153 for path , values in info .items ():
10781154 path = _parse_path (path )
10791155 for value in values :
1080- result .append (FlatDeltaRow (path = path , value = value , action = action ))
1156+ if report_type_changes :
1157+ row = FlatDeltaRow (path = path , value = value , action = action , type = type (value ))
1158+ else :
1159+ row = FlatDeltaRow (path = path , value = value , action = action )
1160+ result .append (row )
10811161 elif action == 'dictionary_item_added' :
10821162 for path , value in info .items ():
10831163 path = _parse_path (path )
@@ -1092,14 +1172,22 @@ def to_flat_rows(self, include_action_in_path=False, report_type_changes=True) -
10921172 elif isinstance (value , set ) and len (value ) == 1 :
10931173 value = value .pop ()
10941174 action = 'set_item_added'
1095- result .append (FlatDeltaRow (path = path , value = value , action = action ))
1175+ if report_type_changes :
1176+ row = FlatDeltaRow (path = path , value = value , action = action , type = type (value ))
1177+ else :
1178+ row = FlatDeltaRow (path = path , value = value , action = action )
1179+ result .append (row )
10961180 elif action in {
10971181 'dictionary_item_removed' , 'iterable_item_added' ,
10981182 'iterable_item_removed' , 'attribute_removed' , 'attribute_added'
10991183 }:
11001184 for path , value in info .items ():
11011185 path = _parse_path (path )
1102- result .append (FlatDeltaRow (path = path , value = value , action = action ))
1186+ if report_type_changes :
1187+ row = FlatDeltaRow (path = path , value = value , action = action , type = type (value ))
1188+ else :
1189+ row = FlatDeltaRow (path = path , value = value , action = action )
1190+ result .append (row )
11031191 elif action == 'type_changes' :
11041192 if not report_type_changes :
11051193 action = 'values_changed'
@@ -1109,16 +1197,16 @@ def to_flat_rows(self, include_action_in_path=False, report_type_changes=True) -
11091197 info = info ,
11101198 _parse_path = _parse_path ,
11111199 keys_and_funcs = keys_and_funcs ,
1200+ report_type_changes = report_type_changes ,
11121201 ):
11131202 result .append (row )
1114- elif action == '_iterable_opcodes' :
1115- result .extend (self ._flatten_iterable_opcodes ())
11161203 else :
11171204 for row in self ._get_flat_row (
11181205 action = action ,
11191206 info = info ,
11201207 _parse_path = _parse_path ,
11211208 keys_and_funcs = keys_and_funcs ,
1209+ report_type_changes = report_type_changes ,
11221210 ):
11231211 result .append (row )
11241212 return result
0 commit comments