Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,4 @@ Authors in order of the timeline of their contributions:
- [akshat62](https://github.com/akshat62) for adding Fraction numeric support.
- [akshat62](https://github.com/akshat62) for adding wildcard/glob pattern support for `exclude_paths` and `include_paths`.
- [mgorny](https://github.com/mgorny) for adding missing files to sdist and removing obsolete `MANIFEST.in`.
- [Sanjays2402](https://github.com/Sanjays2402) for fixing missing type changes between equal-comparing list items (e.g. `[2]` vs `[2.0]`).
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# DeepDiff Change log

- Unreleased
- Fixed missing type changes between equal-comparing items inside ordered iterables, e.g. `DeepDiff([2], [2.0])` now reports the `int` → `float` change like `DeepDiff(2, 2.0)` and `DeepDiff({'a': 2}, {'a': 2.0})` already do (issue #605).

- v9-1-0
- Added multiprocessing support for DeepDiff: parallel distance computation and parallel subtree diffing with aggregated worker stats, deterministic ordering, and automatic fallback to serial when unsafe (e.g. `custom_operators`, `*_obj_callback`, `ignore_order_func`)
- Added wildcard/glob pattern support for `exclude_paths` and `include_paths` thanks to [akshat62](https://github.com/akshat62)
Expand Down
16 changes: 16 additions & 0 deletions deepdiff/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,22 @@ def _diff_ordered_iterable_by_difflib(
opcodes_with_values.append(Opcode(
tag, t1_from_index, t1_to_index, t2_from_index, t2_to_index,
))
# SequenceMatcher considers items "equal" when they compare equal
# (e.g. 2 == 2.0), even when their types differ. Recurse into _diff
# for such pairs so that type changes are reported for iterable items
# the same way they are for scalars and dict values (issue #605).
for index in range(t1_to_index - t1_from_index):
x = level.t1[t1_from_index + index]
y = level.t2[t2_from_index + index]
if get_type(x) != get_type(y):
change_level = level.branch_deeper(
x,
y,
child_relationship_class=child_relationship_class,
child_relationship_param=index + t1_from_index,
child_relationship_param2=index + t2_from_index,
)
self._diff(change_level, parents_ids, local_tree=local_tree)
continue
# print('{:7} t1[{}:{}] --> t2[{}:{}] {!r:>8} --> {!r}'.format(
# tag, t1_from_index, t1_to_index, t2_from_index, t2_to_index, level.t1[t1_from_index:t1_to_index], level.t2[t2_from_index:t2_to_index]))
Expand Down
45 changes: 45 additions & 0 deletions tests/test_diff_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,51 @@ def test_item_type_change_less_verbose(self):
}
}} == DeepDiff(t1, t2, verbose_level=0)

def test_item_type_change_in_list(self):
"""A type change between two equal-comparing items (e.g. 2 and 2.0)
inside a list must be reported, consistently with scalars and dicts.

SequenceMatcher considers 2 == 2.0 "equal", which used to make the
difference disappear entirely for lists while DeepDiff(2, 2.0) and
DeepDiff({'a': 2}, {'a': 2.0}) both reported a type change (issue #605).
"""
t1 = [2]
t2 = [2.0]
ddiff = DeepDiff(t1, t2)
assert {
'type_changes': {
"root[0]": {
"old_value": 2,
"old_type": int,
"new_value": 2.0,
"new_type": float
}
}
} == ddiff
# consistent with the scalar and dict equivalents
assert ddiff['type_changes']["root[0]"]["old_type"] is \
DeepDiff(2, 2.0)['type_changes']["root"]["old_type"]

def test_item_type_change_in_list_among_unchanged_items(self):
t1 = [1, 2, 3]
t2 = [1, 2.0, 3]
ddiff = DeepDiff(t1, t2)
assert {
'type_changes': {
"root[1]": {
"old_value": 2,
"old_type": int,
"new_value": 2.0,
"new_type": float
}
}
} == ddiff

def test_item_type_change_in_list_ignored_when_requested(self):
t1 = [2]
t2 = [2.0]
assert DeepDiff(t1, t2, ignore_numeric_type_changes=True) == {}

def test_item_type_change_for_strings_ignored_by_default(self):
""" ignore_string_type_changes = True by default """

Expand Down