(Colored) View: Do not show unchanged keys in changed dictionaries
Is your feature request related to a problem? Please describe. I have 2 huge root dictionaries (40k keys) and want to run a single comparison on them. Only a couple of keys commonly differ. I want to generate a colored output (or other formats such as .md or html in future) only for the changed keys. If I generate the view for the root dictionaries, I get a huge lot of unchanged keys reported that users are not interested in:
{
"xxx": {
"type": "something",
"status": "other" -> "active",
},
"yyy": {...},
"yyy1": {...},
"yyy2": {...},
"yyy3": {...},
"yyy4": {...},
}
Can I exclude unchanged root keys already now? If not, is there a mechanism for custom views / report types?
Describe the solution you'd like For dictionary comparisons, generate views that exclude unchanged root keys from the report/view.
Describe alternatives you've considered
- Run the comparison multiple times, first for the root dictionaries to find changed keys, then individual diffs on those. That's a performance nightmare.
- Post-process the colored output to textually filter the unchanged keys. That's bad engineering.
- A new option to generate a view from a given diff result for a specific path in the result, that I can call for all changed root keys.
- Build a custom report from a tree view on my side. Can do that, but would benefit from some guidance / best effort method.
Additional context
Ok, I went and copied https://github.com/seperman/deepdiff/blob/master/deepdiff/colored_view.py to my project.
From there I modified it with a new flag hide_unchanged_root_keys that is used in _colorize_json:
def _path_is_dict_root(self, path: str) -> bool:
"""Check if a path is the root of a dictionary."""
return path.startswith("root['") and path.endswith("']") and path.count("'") == 2
def _colorize_json(self, obj: Any, path: str = "root", indent: int = 0) -> str:
...
if isinstance(obj, dict):
...
for key, value in obj.items():
if (new_path in self.diff_paths and self.diff_paths[new_path][0] == "added"):
...
else:
new_value = self._colorize_json(value, new_path, indent + 1)
if not (
self.hide_unchanged_root_keys
and self._path_is_dict_root(new_path)
and new_value == "{...}"
):
items.append(f'{next_indent}"{key}": {new_value}')
...
Works for me, but the detection of whether I am on the root feels ugly.
Facing the same issue,
yes - working with @Arshadwaqas115 and would love to see an "Ultra Compact" view that shows changes only
e.g. working from you example: https://zepworks.com/deepdiff/current/colored_view.html#colored-compact-view
Current Compact View
from deepdiff import DeepDiff
from deepdiff.helper import COLORED_COMPACT_VIEW
t1 = {"name": "John", "age": 30, "scores": [1, 2, 3], "address": {"city": "New York", "zip": "10001"}}
t2 = {"name": "John", "age": 31, "scores": [1, 2, 4], "address": {"city": "New York", "zip": "10001"}, "new": "value"}
diff = DeepDiff(t1, t2, view=COLORED_COMPACT_VIEW)
print(diff)
{
"name": "John",
"age": 30 -> 31,
"scores": [
1,
2,
3 -> 4
],
"address": {...},
"new": "value"
}
Proposed Ultra-Compact View
from deepdiff import DeepDiff
from deepdiff.helper import COLORED_ULTRACOMPACT_VIEW
t1 = {"name": "John", "age": 30, "scores": [1, 2, 3], "address": {"city": "New York", "zip": "10001"}}
t2 = {"name": "John", "age": 31, "scores": [1, 2, 4], "address": {"city": "New York", "zip": "10001"}, "new": "value"}
diff = DeepDiff(t1, t2, view=COLORED_ULTRACOMPACT_VIEW)
print(diff)
{
"age": 30 -> 31,
"scores": [
3 -> 4
],
"new": "value"
}