Skip to content

Commit 051c6d8

Browse files
committed
better support for Pydantic models. Ignore model_fields_set when
comparing pydantic objects
1 parent f86033f commit 051c6d8

File tree

2 files changed

+14
-4
lines changed

2 files changed

+14
-4
lines changed

deepdiff/deephash.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
convert_item_or_items_into_compiled_regexes_else_none,
1313
get_id, type_is_subclass_of_type_group, type_in_type_group,
1414
number_to_string, datetime_normalize, KEY_TO_VAL_STR, short_repr,
15-
get_truncate_datetime, dict_, add_root_to_paths)
15+
get_truncate_datetime, dict_, add_root_to_paths, PydanticBaseModel)
1616
from deepdiff.base import Base
1717

1818
try:
@@ -331,13 +331,15 @@ def values(self):
331331
def items(self):
332332
return ((i, v[0]) for i, v in self.hashes.items())
333333

334-
def _prep_obj(self, obj, parent, parents_ids=EMPTY_FROZENSET, is_namedtuple=False):
334+
def _prep_obj(self, obj, parent, parents_ids=EMPTY_FROZENSET, is_namedtuple=False, is_pydantic_object=False):
335335
"""prepping objects"""
336336
original_type = type(obj) if not isinstance(obj, type) else obj
337337

338338
obj_to_dict_strategies = []
339339
if is_namedtuple:
340340
obj_to_dict_strategies.append(lambda o: o._asdict())
341+
elif is_pydantic_object:
342+
obj_to_dict_strategies.append(lambda o: {k: v for (k, v) in o.__dict__.items() if v !="model_fields_set"})
341343
else:
342344
obj_to_dict_strategies.append(lambda o: o.__dict__)
343345

@@ -562,6 +564,8 @@ def gen():
562564

563565
elif obj == BoolObj.TRUE or obj == BoolObj.FALSE:
564566
result = 'bool:true' if obj is BoolObj.TRUE else 'bool:false'
567+
elif isinstance(obj, PydanticBaseModel):
568+
result, counts = self._prep_obj(obj=obj, parent=parent, parents_ids=parents_ids, is_pydantic_object=True)
565569
else:
566570
result, counts = self._prep_obj(obj=obj, parent=parent, parents_ids=parents_ids)
567571

deepdiff/diff.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ def _report_progress(_stats, progress_logger, duration):
8080
PURGE_LEVEL_RANGE_MSG = 'cache_purge_level should be 0, 1, or 2.'
8181
_ENABLE_CACHE_EVERY_X_DIFF = '_ENABLE_CACHE_EVERY_X_DIFF'
8282

83+
model_fields_set = frozenset(["model_fields_set"])
84+
85+
8386
# What is the threshold to consider 2 items to be pairs. Only used when ignore_order = True.
8487
CUTOFF_DISTANCE_FOR_PAIRS_DEFAULT = 0.3
8588

@@ -437,13 +440,16 @@ def _diff_enum(self, level, parents_ids=frozenset(), local_tree=None):
437440
local_tree=local_tree,
438441
)
439442

440-
def _diff_obj(self, level, parents_ids=frozenset(), is_namedtuple=False, local_tree=None):
443+
def _diff_obj(self, level, parents_ids=frozenset(), is_namedtuple=False, local_tree=None, is_pydantic_object=False):
441444
"""Difference of 2 objects"""
442445
processing_error = False
443446
try:
444447
if is_namedtuple:
445448
t1 = level.t1._asdict()
446449
t2 = level.t2._asdict()
450+
elif is_pydantic_object:
451+
t1 = detailed__dict__(level.t1, ignore_private_variables=self.ignore_private_variables, ignore_keys=model_fields_set)
452+
t2 = detailed__dict__(level.t2, ignore_private_variables=self.ignore_private_variables, ignore_keys=model_fields_set)
447453
elif all('__dict__' in dir(t) for t in level):
448454
t1 = detailed__dict__(level.t1, ignore_private_variables=self.ignore_private_variables)
449455
t2 = detailed__dict__(level.t2, ignore_private_variables=self.ignore_private_variables)
@@ -1678,7 +1684,7 @@ def _diff(self, level, parents_ids=frozenset(), _original_type=None, local_tree=
16781684
self._diff_numpy_array(level, parents_ids, local_tree=local_tree)
16791685

16801686
elif isinstance(level.t1, PydanticBaseModel):
1681-
self._diff_obj(level, parents_ids, local_tree=local_tree)
1687+
self._diff_obj(level, parents_ids, local_tree=local_tree, is_pydantic_object=True)
16821688

16831689
elif isinstance(level.t1, Iterable):
16841690
self._diff_iterable(level, parents_ids, _original_type=_original_type, local_tree=local_tree)

0 commit comments

Comments
 (0)