@@ -104,7 +104,8 @@ async def serialize_diff(
104104 attribute_diff , attribute_property_diff = self ._serialize_attribute (
105105 attribute_diff = attr_diff , node_uuid = node .uuid , node_kind = node .kind
106106 )
107- attribute_diffs .append (attribute_diff )
107+ if attribute_diff :
108+ attribute_diffs .append (attribute_diff )
108109 serialized_property_diffs .append (attribute_property_diff )
109110 relationship_diffs = []
110111 for rel_diff in node .relationships :
@@ -113,7 +114,9 @@ async def serialize_diff(
113114 )
114115 for relationship_element_diff in rel_diff .relationships :
115116 element_diffs , relationship_property_diffs = self ._serialize_relationship_element (
116- relationship_diff = relationship_element_diff , relationship_identifier = relationship_identifier
117+ relationship_diff = relationship_element_diff ,
118+ relationship_identifier = relationship_identifier ,
119+ node_uuid = node .uuid ,
117120 )
118121 relationship_diffs .extend (element_diffs )
119122 serialized_property_diffs .extend (relationship_property_diffs )
@@ -153,13 +156,13 @@ def _get_property_actions_and_values(
153156 final_value = self ._convert_property_value (
154157 property_type = property_diff .property_type , raw_value = raw_value , value_type = python_value_type
155158 )
156- if final_value :
159+ if final_value is not None :
157160 actions_and_values .append ((action , final_value ))
158161 return actions_and_values
159162
160163 def _serialize_attribute (
161164 self , attribute_diff : EnrichedDiffAttribute , node_uuid : str , node_kind : str
162- ) -> tuple [AttributeMergeDict , AttributePropertyMergeDict ]:
165+ ) -> tuple [AttributeMergeDict | None , AttributePropertyMergeDict ]:
163166 prop_dicts : list [PropertyMergeDict ] = []
164167 python_type = self ._get_property_type_for_attribute_value (
165168 schema_kind = node_kind , attribute_name = attribute_diff .name
@@ -169,38 +172,105 @@ def _serialize_attribute(
169172 property_diff = property_diff , python_value_type = python_type
170173 )
171174 for action , value in actions_and_values :
175+ # we only delete attributes when the whole attribute is deleted
176+ if action is DiffAction .REMOVED and attribute_diff .action is not DiffAction .REMOVED :
177+ continue
172178 prop_dicts .append (
173179 PropertyMergeDict (
174180 property_type = property_diff .property_type .value ,
175181 action = self ._to_action_str (action = action ),
176182 value = value ,
177183 )
178184 )
179- attr_dict = AttributeMergeDict (
180- name = attribute_diff .name ,
181- action = self ._to_action_str (action = attribute_diff .action ),
182- )
185+ attr_dict = None
186+ if attribute_diff .action in (DiffAction .ADDED , DiffAction .REMOVED ):
187+ attr_dict = AttributeMergeDict (
188+ name = attribute_diff .name ,
189+ action = self ._to_action_str (action = attribute_diff .action ),
190+ )
183191 attr_prop_dict = AttributePropertyMergeDict (
184192 node_uuid = node_uuid , attribute_name = attribute_diff .name , properties = prop_dicts
185193 )
186194 return attr_dict , attr_prop_dict
187195
188196 def _serialize_relationship_element (
189- self , relationship_diff : EnrichedDiffSingleRelationship , relationship_identifier : str
197+ self , relationship_diff : EnrichedDiffSingleRelationship , relationship_identifier : str , node_uuid : str
190198 ) -> tuple [list [RelationshipMergeDict ], list [RelationshipPropertyMergeDict ]]:
191199 relationship_dicts = []
200+ # start with default values for IS_VISIBLE and IS_PROTECTED b/c we always want to update them during a merge
201+ added_property_dicts : dict [DatabaseEdgeType , PropertyMergeDict ] = {
202+ DatabaseEdgeType .IS_VISIBLE : PropertyMergeDict (
203+ property_type = DatabaseEdgeType .IS_VISIBLE .value ,
204+ action = self ._to_action_str (DiffAction .ADDED ),
205+ value = None ,
206+ ),
207+ DatabaseEdgeType .IS_PROTECTED : PropertyMergeDict (
208+ property_type = DatabaseEdgeType .IS_PROTECTED .value ,
209+ action = self ._to_action_str (DiffAction .ADDED ),
210+ value = None ,
211+ ),
212+ }
213+ removed_property_dicts : dict [DatabaseEdgeType , PropertyMergeDict ] = {
214+ DatabaseEdgeType .IS_VISIBLE : PropertyMergeDict (
215+ property_type = DatabaseEdgeType .IS_VISIBLE .value ,
216+ action = self ._to_action_str (DiffAction .REMOVED ),
217+ value = None ,
218+ ),
219+ DatabaseEdgeType .IS_PROTECTED : PropertyMergeDict (
220+ property_type = DatabaseEdgeType .IS_PROTECTED .value ,
221+ action = self ._to_action_str (DiffAction .REMOVED ),
222+ value = None ,
223+ ),
224+ }
225+ added_peer_id : str | None = None
226+ removed_peer_id : str | None = None
192227 for property_diff in relationship_diff .properties :
193- if property_diff . property_type is not DatabaseEdgeType . IS_RELATED :
194- continue
195- # TODO: next PR will add properties to this method
228+ python_value_type : type = str
229+ if property_diff . property_type in ( DatabaseEdgeType . IS_VISIBLE , DatabaseEdgeType . IS_PROTECTED ):
230+ python_value_type = bool
196231 actions_and_values = self ._get_property_actions_and_values (
197- property_diff = property_diff , python_value_type = str
232+ property_diff = property_diff , python_value_type = python_value_type
198233 )
199-
200- for action , value in actions_and_values :
201- relationship_dicts .append (
202- RelationshipMergeDict (
203- peer_id = str (value ), name = relationship_identifier , action = self ._to_action_str (action = action )
234+ if property_diff .property_type is DatabaseEdgeType .IS_RELATED :
235+ for action , value in actions_and_values :
236+ peer_id = str (value )
237+ if action is DiffAction .ADDED :
238+ added_peer_id = peer_id
239+ elif action is DiffAction .REMOVED :
240+ removed_peer_id = peer_id
241+ relationship_dicts .append (
242+ RelationshipMergeDict (
243+ peer_id = peer_id , name = relationship_identifier , action = self ._to_action_str (action = action )
244+ )
204245 )
246+ else :
247+ for action , value in actions_and_values :
248+ property_dict = PropertyMergeDict (
249+ property_type = property_diff .property_type .value ,
250+ action = self ._to_action_str (action = action ),
251+ value = value ,
252+ )
253+ if action is DiffAction .ADDED :
254+ added_property_dicts [property_diff .property_type ] = property_dict
255+ elif action is DiffAction .REMOVED :
256+ removed_property_dicts [property_diff .property_type ] = property_dict
257+ relationship_property_dicts = []
258+ if added_peer_id and added_property_dicts :
259+ relationship_property_dicts .append (
260+ RelationshipPropertyMergeDict (
261+ node_uuid = node_uuid ,
262+ relationship_id = relationship_identifier ,
263+ peer_uuid = added_peer_id ,
264+ properties = list (added_property_dicts .values ()),
205265 )
206- return relationship_dicts , []
266+ )
267+ if removed_peer_id and removed_property_dicts :
268+ relationship_property_dicts .append (
269+ RelationshipPropertyMergeDict (
270+ node_uuid = node_uuid ,
271+ relationship_id = relationship_identifier ,
272+ peer_uuid = removed_peer_id ,
273+ properties = list (removed_property_dicts .values ()),
274+ )
275+ )
276+ return relationship_dicts , relationship_property_dicts
0 commit comments