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 @@ -89,3 +89,4 @@ Authors in order of the timeline of their contributions:
- [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]`).
- [ChrisJr404](https://github.com/ChrisJr404) for adding `t1_name`/`t2_name` to rename the tree view's `t1`/`t2` labels.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# DeepDiff Change log

- Unreleased
- Added `t1_name` and `t2_name` parameters to rename the `t1`/`t2` labels shown in the tree view's string representation, e.g. `<root['a'] before:1, after:2>` (issue #531)
- 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
Expand Down
12 changes: 11 additions & 1 deletion deepdiff/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ def __init__(self,
progress_logger: Callable[[str], None]=logger.info,
report_repetition: bool=False,
significant_digits: Optional[int]=None,
t1_name: str="t1",
t2_name: str="t2",
threshold_to_diff_deeper: float = 0.33,
truncate_datetime: Optional[str]=None,
use_enum_value: bool=False,
Expand All @@ -223,6 +225,7 @@ def __init__(self,
"number_format_notation, exclude_paths, include_paths, exclude_types, exclude_regex_paths, ignore_type_in_groups, "
"ignore_string_type_changes, ignore_numeric_type_changes, ignore_type_subclasses, ignore_uuid_types, truncate_datetime, "
"ignore_private_variables, ignore_nan_inequality, number_to_string_func, verbose_level, "
"t1_name, t2_name, "
"view, hasher, hashes, max_passes, max_diffs, zip_ordered_iterables, "
"cutoff_distance_for_pairs, cutoff_intersection_for_pairs, log_frequency_in_sec, cache_size, "
"cache_tuning_sample_size, get_deep_distance, group_by, group_by_sort_key, cache_purge_level, log_stacktrace,"
Expand All @@ -233,6 +236,10 @@ def __init__(self,

if _parameters:
self.__dict__.update(_parameters)
# Backward compatibility: t1_name/t2_name may be absent from an
# externally-supplied _parameters dict, so fall back to the defaults.
self.t1_name = _parameters.get('t1_name', t1_name)
self.t2_name = _parameters.get('t2_name', t2_name)
else:
self.custom_operators = custom_operators or []
self.ignore_order = ignore_order
Expand Down Expand Up @@ -309,6 +316,8 @@ def _group_by_sort_key(x):
self.verbose_level = verbose_level
else:
raise ValueError(VERBOSE_LEVEL_RANGE_MSG)
self.t1_name = t1_name
self.t2_name = t2_name
if cache_purge_level not in {0, 1, 2}:
raise ValueError(PURGE_LEVEL_RANGE_MSG)
self.view = view
Expand Down Expand Up @@ -400,7 +409,8 @@ def _group_by_sort_key(x):
self.t2 = t2

try:
root = DiffLevel(t1, t2, verbose_level=self.verbose_level)
root = DiffLevel(t1, t2, verbose_level=self.verbose_level,
t1_name=self.t1_name, t2_name=self.t2_name)
# _original_type is only used to pass the original type of the data. Currently only used for numpy arrays.
# The reason is that we convert the numpy array to python list and then later for distance calculations
# we convert only the the last dimension of it into numpy arrays.
Expand Down
1 change: 1 addition & 0 deletions deepdiff/docstrings/authors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ 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``.
- `ChrisJr404 <https://github.com/ChrisJr404>`__ for adding ``t1_name``/``t2_name`` to rename the tree view's ``t1``/``t2`` labels.


.. _Sep Dehpour (Seperman): http://www.zepworks.com
Expand Down
6 changes: 6 additions & 0 deletions deepdiff/docstrings/diff_doc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,12 @@ significant_digits : int >= 0, default=None
truncate_datetime: string, default = None
:ref:`truncate_datetime_label` can take value one of 'second', 'minute', 'hour', 'day' and truncate with this value datetime objects before hashing it

t1_name: string, default = "t1"
The label used for the first object when a level of the tree view is represented as a string. For example, passing ``t1_name="before"`` turns ``<root['a'] t1:1, t2:2>`` into ``<root['a'] before:1, t2:2>``. This only affects the ``repr`` of tree view levels; it has no effect on the text view or the comparison itself.

t2_name: string, default = "t2"
The label used for the second object when a level of the tree view is represented as a string. See ``t1_name`` above.

threshold_to_diff_deeper: float, default = 0.33
:ref:`threshold_to_diff_deeper_label` is a number between 0 and 1. When comparing dictionaries that have a small intersection of keys, we will report the dictionary as a new_value instead of reporting individual keys changed. If you set it to zero, you get the same results as DeepDiff 7.0.1 and earlier, which means this feature is disabled. The new default is 0.33 which means if less that one third of keys between dictionaries intersect, report it as a new object.

Expand Down
9 changes: 9 additions & 0 deletions deepdiff/docstrings/view.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ Value of an item has changed (Tree View)
>>> changed.up
<root t1:{1: 1, 2: 2,...}, t2:{1: 1, 2: 4,...}>

Custom labels for the compared objects (Tree View)
The ``t1`` and ``t2`` labels shown in the string representation can be renamed via the ``t1_name`` and ``t2_name`` parameters. This is handy when the two objects have meaningful roles such as "before" and "after".

>>> t1 = {1:1, 2:2, 3:3}
>>> t2 = {1:1, 2:4, 3:3}
>>> ddiff = DeepDiff(t1, t2, view='tree', t1_name="before", t2_name="after")
>>> ddiff
{'values_changed': [<root[2] before:2, after:4>]}

List difference (Tree View)
>>> t1 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2, 3, 4]}}
>>> t2 = {1:1, 2:2, 3:3, 4:{"a":"hello", "b":[1, 2]}}
Expand Down
15 changes: 12 additions & 3 deletions deepdiff/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,9 @@ def __init__(self,
child_rel1: Optional['ChildRelationship'] = None,
child_rel2: Optional['ChildRelationship'] = None,
additional: Optional[Dict[str, Any]] = None,
verbose_level: int = 1) -> None:
verbose_level: int = 1,
t1_name: str = "t1",
t2_name: str = "t2") -> None:
"""
:param child_rel1: Either:
- An existing ChildRelationship object describing the "down" relationship for t1; or
Expand Down Expand Up @@ -589,6 +591,11 @@ def __init__(self,

self.verbose_level = verbose_level

# Labels used for t1 and t2 when this level is represented as a string.
# Customizable so the tree view repr can use meaningful names, e.g. "before"/"after".
self.t1_name = t1_name
self.t2_name = t2_name

def __repr__(self) -> str:
if self.verbose_level:
from deepdiff.summarize import summarize
Expand All @@ -599,7 +606,8 @@ def __repr__(self) -> str:
else:
t1_repr = summarize(self.t1, max_length=35)
t2_repr = summarize(self.t2, max_length=35)
result = "<{} t1:{}, t2:{}>".format(self.path(), t1_repr, t2_repr)
result = "<{} {}:{}, {}:{}>".format(
self.path(), self.t1_name, t1_repr, self.t2_name, t2_repr)
else:
result = "<{}>".format(self.path())
return result
Expand Down Expand Up @@ -792,7 +800,8 @@ def create_deeper(self,
"""
level = self.all_down
result = DiffLevel(
new_t1, new_t2, down=None, up=level, report_type=report_type, verbose_level=self.verbose_level)
new_t1, new_t2, down=None, up=level, report_type=report_type, verbose_level=self.verbose_level,
t1_name=self.t1_name, t2_name=self.t2_name)
level.down = result
level.auto_generate_child_rel(
klass=child_relationship_class, param=child_relationship_param, param2=child_relationship_param2)
Expand Down
18 changes: 18 additions & 0 deletions tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,24 @@ def test_repr_very_long(self):
self.lowest.verbose_level = level
assert item_repr == '<root[1337].a t1:"very long text here, much long...e.", t2:313>'

def test_repr_custom_t1_t2_names(self):
node = DiffLevel(2, 3, t1_name="before", t2_name="after")
assert repr(node) == "<root before:2, after:3>"

def test_custom_t1_t2_names_propagate_to_children(self):
diff = DeepDiff({'a': {'b': 1}}, {'a': {'b': 2}}, view='tree',
t1_name='expected', t2_name='actual')
level = diff['values_changed'][0]
assert repr(level) == "<root['a']['b'] expected:1, actual:2>"

def test_default_t1_t2_names_unchanged(self):
diff = DeepDiff({'a': 1}, {'a': 2}, view='tree')
assert repr(diff['values_changed'][0]) == "<root['a'] t1:1, t2:2>"

def test_custom_t1_t2_names_do_not_affect_text_view(self):
diff = DeepDiff({'a': 1}, {'a': 2}, t1_name='before', t2_name='after')
assert diff == {'values_changed': {"root['a']": {'new_value': 2, 'old_value': 1}}}

def test_repetition_attribute_and_repr(self):
t1 = [1, 1]
t2 = [1]
Expand Down