Skip to content

Commit d5f23df

Browse files
committed
Adding support for applying deltas to NamedTuple
1 parent c7e581f commit d5f23df

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

deepdiff/delta.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,11 +330,21 @@ def _set_new_value(self, parent, parent_to_obj_elem, parent_to_obj_action,
330330
Set the element value on an object and if necessary convert the object to the proper mutable type
331331
"""
332332
if isinstance(obj, tuple):
333-
# convert this object back to a tuple later
334-
obj = self._coerce_obj(
335-
parent, obj, path, parent_to_obj_elem,
336-
parent_to_obj_action, elements,
337-
to_type=list, from_type=tuple)
333+
# Check if it's a NamedTuple and use _replace() to generate a new copy with the change
334+
if hasattr(obj, '_fields') and hasattr(obj, '_replace'):
335+
if action == GETATTR:
336+
obj = obj._replace(**{elem: new_value})
337+
if parent:
338+
self._simple_set_elem_value(obj=parent, path_for_err_reporting=path,
339+
elem=parent_to_obj_elem, value=obj,
340+
action=parent_to_obj_action)
341+
return
342+
else:
343+
# Regular tuple - convert this object back to a tuple later
344+
obj = self._coerce_obj(
345+
parent, obj, path, parent_to_obj_elem,
346+
parent_to_obj_action, elements,
347+
to_type=list, from_type=tuple)
338348
if elem != 0 and self.force and isinstance(obj, list) and len(obj) == 0:
339349
# it must have been a dictionary
340350
obj = {}

tests/test_delta.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import copy
22
import datetime
3+
from typing import NamedTuple
34
import pytest
45
import os
56
import io
@@ -624,6 +625,17 @@ def compare_func(item1, item2, level=None):
624625
assert flat_rows_list == preserved_flat_dict_list
625626
assert flat_rows_list == flat_rows_list_again
626627

628+
def test_namedtuple_add_delta(self):
629+
class Point(NamedTuple):
630+
x: int
631+
y: int
632+
633+
p1 = Point(1, 1)
634+
p2 = Point(1, 2)
635+
diff = DeepDiff(p1, p2)
636+
delta = Delta(diff)
637+
assert p2 == p1 + delta
638+
627639

628640
picklalbe_obj_without_item = PicklableClass(11)
629641
del picklalbe_obj_without_item.item

0 commit comments

Comments
 (0)