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
16 changes: 8 additions & 8 deletions deepdiff/colored_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@ def _colorize_json(self, obj: Any, path: str = 'root', indent: int = 0) -> str:
if isinstance(obj, (dict, list)) and self.compact and not self._has_differences(path):
return '{...}' if isinstance(obj, dict) else '[...]'

removed_items = self._get_path_removed(path)
if isinstance(obj, dict):
if not obj:
if not obj and not removed_items:
return '{}'
items = []
for key, value in obj.items():
Expand All @@ -103,27 +104,26 @@ def _colorize_json(self, obj: Any, path: str = 'root', indent: int = 0) -> str:
items.append(f'{next_indent}{GREEN}"{key}": {self._colorize_json(value, new_path, indent + 1)}{RESET}')
else:
items.append(f'{next_indent}"{key}": {self._colorize_json(value, new_path, indent + 1)}')
for key, value in self._get_path_removed(path).items():
for key, value in removed_items.items():
new_path = f"{path}['{key}']" if isinstance(key, str) else f"{path}[{key}]"
items.append(f'{next_indent}{RED}"{key}": {self._colorize_json(value, new_path, indent + 1)}{RESET}')
return '{\n' + ',\n'.join(items) + f'\n{current_indent}' + '}'

elif isinstance(obj, (list, tuple)):
if not obj:
if not obj and not removed_items:
return '[]'
removed_map = self._get_path_removed(path)
for index in removed_map:
for index in removed_items:
self._colorize_skip_paths.add(f"{path}[{index}]")

items = []
remove_index = 0
for index, value in enumerate(obj):
while remove_index == next(iter(removed_map), None):
items.append(f'{next_indent}{RED}{self._format_value(removed_map.pop(remove_index))}{RESET}')
while remove_index == next(iter(removed_items), None):
items.append(f'{next_indent}{RED}{self._format_value(removed_items.pop(remove_index))}{RESET}')
remove_index += 1
items.append(f'{next_indent}{self._colorize_json(value, f"{path}[{index}]", indent + 1)}')
remove_index += 1
for value in removed_map.values():
for value in removed_items.values():
items.append(f'{next_indent}{RED}{self._format_value(value)}{RESET}')
return '[\n' + ',\n'.join(items) + f'\n{current_indent}' + ']'
else:
Expand Down
97 changes: 68 additions & 29 deletions tests/test_colored_view.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from deepdiff import DeepDiff
from deepdiff.colored_view import ColoredView, RED, RESET
from deepdiff.colored_view import GREEN
from deepdiff.helper import COLORED_VIEW, COLORED_COMPACT_VIEW
from deepdiff.colored_view import RED, GREEN, RESET


def test_colored_view_basic():
Expand Down Expand Up @@ -52,20 +53,20 @@ def test_colored_view_nested_changes():
"level1": {
"level2": {
"level3": {
"level4": True
}
}
}
"level4": True,
},
},
},
}

t2 = {
"level1": {
"level2": {
"level3": {
"level4": False
}
}
}
"level4": False,
},
},
},
}

diff = DeepDiff(t1, t2, view=COLORED_VIEW)
Expand Down Expand Up @@ -187,16 +188,16 @@ def test_colored_view_list_with_ignore_order():
t1 = {
"hobbies": [
"reading",
"hiking"
]
"hiking",
],
}

t2 = {
"hobbies": [
"hiking",
"painting",
"coding"
]
"coding",
],
}

diff = DeepDiff(t1, t2, view=COLORED_VIEW, ignore_order=True)
Expand Down Expand Up @@ -238,10 +239,10 @@ def test_compact_view_basic():
"zip": "10001",
"details": {
"type": "apartment",
"floor": 5
}
"floor": 5,
},
},
"hobbies": ["reading", {"sport": "tennis", "level": "advanced"}]
"hobbies": ["reading", {"sport": "tennis", "level": "advanced"}],
}

t2 = {
Expand All @@ -253,11 +254,11 @@ def test_compact_view_basic():
"zip": "10001",
"details": {
"type": "apartment",
"floor": 5
}
"floor": 5,
},
},
"team": "abc", # Added
"hobbies": ["reading", {"sport": "tennis", "level": "advanced"}]
"hobbies": ["reading", {"sport": "tennis", "level": "advanced"}],
}

diff = DeepDiff(t1, t2, view=COLORED_COMPACT_VIEW)
Expand Down Expand Up @@ -288,32 +289,32 @@ def test_compact_view_nested_changes():
"level1": {
"unchanged1": {
"deep1": True,
"deep2": [1, 2, 3]
"deep2": [1, 2, 3],
},
"level2": {
"a": 1,
"b": "test",
"c": [1, 2, 3],
"d": {"x": 1, "y": 2}
"d": {"x": 1, "y": 2},
},
"unchanged2": [1, 2, {"a": 1}]
}
"unchanged2": [1, 2, {"a": 1}],
},
}

t2 = {
"level1": {
"unchanged1": {
"deep1": True,
"deep2": [1, 2, 3]
"deep2": [1, 2, 3],
},
"level2": {
"a": 2, # Changed
"b": "test",
"c": [1, 2, 4], # Changed
"d": {"x": 1, "y": 3} # Changed
"d": {"x": 1, "y": 3}, # Changed
},
"unchanged2": [1, 2, {"a": 1}]
}
"unchanged2": [1, 2, {"a": 1}],
},
}

diff = DeepDiff(t1, t2, view=COLORED_COMPACT_VIEW)
Expand Down Expand Up @@ -379,15 +380,15 @@ def test_compact_view_primitive_siblings():
"str_sibling": "hello",
"int_sibling": 42,
"bool_sibling": True,
"nested_sibling": {"a": 1, "b": 2}
"nested_sibling": {"a": 1, "b": 2},
}

t2 = {
"changed": 2,
"str_sibling": "hello",
"int_sibling": 42,
"bool_sibling": True,
"nested_sibling": {"a": 1, "b": 2}
"nested_sibling": {"a": 1, "b": 2},
}

diff = DeepDiff(t1, t2, view=COLORED_COMPACT_VIEW)
Expand Down Expand Up @@ -425,3 +426,41 @@ def test_colored_view_bool_evaluation():
# Scenario 2: With differences
diff_with_diff_compact = DeepDiff(t1_with_diff, t2_with_diff, view=COLORED_COMPACT_VIEW)
assert bool(diff_with_diff_compact), "bool(diff) should be True when diffs exist (compact view)"


def test_colored_view_with_empty_list_shows_removals():
"""
Tests ColoredView correctly shows about an empty list.
This covers the bug where it would just show '[]'.
"""
t1 = [1, 2, 3]
t2 = []
ddiff = DeepDiff(t1, t2)
view = ColoredView(t2, ddiff.tree)
result = str(view)

# The output should contain the removed items, colored in red.
assert f"{RED}1{RESET}" in result
assert f"{RED}2{RESET}" in result
assert f"{RED}3{RESET}" in result
assert result.strip().startswith('[')
assert result.strip().endswith(']')
assert result != '[]'


def test_colored_view_with_empty_dict_shows_removals():
"""
Tests ColoredView correctly shows about an empty dict.
This covers the bug where it would just show '{}'.
"""
t1 = {'a': 1, 'b': 2}
t2 = {}
ddiff = DeepDiff(t1, t2)
view = ColoredView(t2, ddiff.tree)
result = str(view)

assert f'{RED}{{"a": 1' in result
assert f'"b": 2}}{RESET}' in result
assert result.strip().startswith(RED)
assert result.strip().endswith(RESET)
assert result != '{}'
Loading