diff --git a/deepdiff/diff.py b/deepdiff/diff.py index 5572c103..c9321665 100755 --- a/deepdiff/diff.py +++ b/deepdiff/diff.py @@ -116,6 +116,7 @@ def __init__(self, cutoff_intersection_for_pairs=CUTOFF_INTERSECTION_FOR_PAIRS_DEFAULT, encodings=None, exclude_obj_callback=None, + exclude_obj_callback_strict=None, exclude_paths=None, exclude_regex_paths=None, exclude_types=None, @@ -194,6 +195,7 @@ def __init__(self, self.type_check_func = type_is_subclass_of_type_group if ignore_type_subclasses else type_in_type_group self.ignore_string_case = ignore_string_case self.exclude_obj_callback = exclude_obj_callback + self.exclude_obj_callback_strict = exclude_obj_callback_strict self.number_to_string = number_to_string_func or number_to_string self.iterable_compare_func = iterable_compare_func self.ignore_private_variables = ignore_private_variables @@ -429,6 +431,10 @@ def _skip_this(self, level): elif self.exclude_obj_callback and \ (self.exclude_obj_callback(level.t1, level.path()) or self.exclude_obj_callback(level.t2, level.path())): skip = True + elif self.exclude_obj_callback_strict and \ + (self.exclude_obj_callback_strict(level.t1, level.path()) and + self.exclude_obj_callback_strict(level.t2, level.path())): + skip = True return skip diff --git a/docs/ignore_types_or_values.rst b/docs/ignore_types_or_values.rst index 464b93ab..bd705107 100644 --- a/docs/ignore_types_or_values.rst +++ b/docs/ignore_types_or_values.rst @@ -272,6 +272,18 @@ exclude_obj_callback: function, default = None >>> DeepDiff(t1, t2, exclude_obj_callback=exclude_obj_callback) {} +exclude_obj_callback_strict: function, default = None + A function works the same way as exclude_obj_callback, but excludes elements from the result only if the function returns True for both elements + + >>> def exclude_obj_callback_strict(obj, path): + ... return True if isinstance(obj, int) and obj > 10 else False + ... + >>> t1 = {"x": 10, "y": "b", "z": "c"} + >>> t2 = {"x": 12, "y": "b", "z": "c"} + >>> DeepDiff(t1, t2, exclude_obj_callback=exclude_obj_callback_strict) + {} + >>> DeepDiff(t1, t2, exclude_obj_callback_strict=exclude_obj_callback_strict) + {'values_changed': {"root['x']": {'new_value': 12, 'old_value': 10}}} .. _truncate_datetime_label: diff --git a/tests/test_delta.py b/tests/test_delta.py index c66a48a1..7a828a9f 100644 --- a/tests/test_delta.py +++ b/tests/test_delta.py @@ -1151,6 +1151,7 @@ def test_delta_view_and_to_delta_dict_are_equal_when_parameteres_passed(self): 'ignore_type_subclasses': False, 'ignore_string_case': False, 'exclude_obj_callback': None, + 'exclude_obj_callback_strict': None, 'ignore_private_variables': True, 'ignore_nan_inequality': False, 'hasher': None, diff --git a/tests/test_diff_text.py b/tests/test_diff_text.py index 2d28103b..03079d74 100755 --- a/tests/test_diff_text.py +++ b/tests/test_diff_text.py @@ -1394,6 +1394,16 @@ def exclude_obj_callback(obj, path): result = {} assert result == ddiff + def test_skip_exclude_obj_callback_strict(self): + def exclude_obj_callback_strict(obj, path): + return True if isinstance(obj, int) and obj > 10 else False + + t1 = {"x": 10, "y": "b", "z": "c"} + t2 = {"x": 12, "y": "b", "z": "c"} + ddiff = DeepDiff(t1, t2, exclude_obj_callback_strict=exclude_obj_callback_strict) + result = {'values_changed': {"root['x']": {'new_value': 12, 'old_value': 10}}} + assert result == ddiff + def test_skip_str_type_in_dictionary(self): t1 = {1: {2: "a"}} t2 = {1: {}}