Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add print() option #492

Merged
merged 1 commit into from
Oct 13, 2024
Merged
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 @@ -64,3 +64,4 @@ Authors in order of the timeline of their contributions:
- [dtorres-sf](https://github.com/dtorres-sf) for fixing iterable moved items when iterable_compare_func is used.
- [Florian Finkernagel](https://github.com/TyberiusPrime) for pandas and polars support.
- Mathis Chenuet [artemisart](https://github.com/artemisart) for fixing slots classes comparison.
- [Aaron D. Marasco](https://github.com/AaronDMarasco) added `prefix` option to `pretty()`
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

- v8-0-1
- Bugfix. Numpy should be optional.
- Added `prefix` option to `pretty()`

- v8-0-0

Expand Down
8 changes: 6 additions & 2 deletions deepdiff/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ def _to_delta_dict(self, directed=True, report_repetition_required=True, always_

return deepcopy(dict(result))

def pretty(self):
def pretty(self, prefix=None):
"""
The pretty human readable string output for the diff object
regardless of what view was used to generate the diff.
Expand All @@ -310,12 +310,16 @@ def pretty(self):
Item root[1] removed from set.
"""
result = []
if prefix is None:
prefix = ''
keys = sorted(self.tree.keys()) # sorting keys to guarantee constant order across python versions.
for key in keys:
for item_key in self.tree[key]:
result += [pretty_print_diff(item_key)]

return '\n'.join(result)
if callable(prefix):
return "\n".join(f"{prefix(diff=self)}{r}" for r in result)
return "\n".join(f"{prefix}{r}" for r in result)
AaronDMarasco marked this conversation as resolved.
Show resolved Hide resolved


class _RestrictedUnpickler(pickle.Unpickler):
Expand Down
23 changes: 23 additions & 0 deletions docs/view.rst
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,29 @@ Use the pretty method for human readable output. This is regardless of what view
Item root[4] removed from set.
Item root[1] removed from set.

The pretty method has an optional parameter ``prefix`` that allows a prefix string before every output line (*e.g.* for logging):
>>> from deepdiff import DeepDiff
>>> t1={1,2,4}
>>> t2={2,3}
>>> print(DeepDiff(t1, t2).pretty(prefix='Diff: '))
Diff: Item root[3] added to set.
Diff: Item root[4] removed from set.
Diff: Item root[1] removed from set.

The ``prefix`` may also be a callable function. This function must accept ``**kwargs``; as of this version, the only parameter is ``diff`` but the signature allows for future expansion.
The ``diff`` given will be the ``DeepDiff`` that ``pretty`` was called on; this allows interesting capabilities such as:
>>> from deepdiff import DeepDiff
>>> t1={1,2,4}
>>> t2={2,3}
>>> def callback(**kwargs):
... """Helper function using a hidden variable on the diff that tracks which count prints next"""
... kwargs['diff']._diff_count = 1 + getattr(kwargs['diff'], '_diff_count', 0)
... return f"Diff #{kwargs['diff']._diff_count}: "
...
>>> print(DeepDiff(t1, t2).pretty(prefix=callback))
Diff #1: Item root[3] added to set.
Diff #2: Item root[4] removed from set.
Diff #3: Item root[1] removed from set.


Text view vs. Tree view vs. vs. pretty() method
Expand Down
43 changes: 43 additions & 0 deletions tests/test_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,49 @@ def test_pretty_form_method(self, expected, verbose_level):
result = ddiff.pretty()
assert result == expected

@pytest.mark.parametrize("expected, verbose_level",
(
('\t\tItem root[5] added to dictionary.'
'\n\t\tItem root[3] removed from dictionary.'
'\n\t\tType of root[2] changed from int to str and value changed from 2 to "b".'
'\n\t\tValue of root[4] changed from 4 to 5.', 0),
('\t\tItem root[5] (5) added to dictionary.'
'\n\t\tItem root[3] (3) removed from dictionary.'
'\n\t\tType of root[2] changed from int to str and value changed from 2 to "b".'
'\n\t\tValue of root[4] changed from 4 to 5.', 2),
), ids=("verbose=0", "verbose=2")
)
def test_pretty_form_method_prefixed_simple(self, expected, verbose_level):
t1 = {2: 2, 3: 3, 4: 4}
t2 = {2: 'b', 4: 5, 5: 5}
ddiff = DeepDiff(t1, t2, verbose_level=verbose_level)
result = ddiff.pretty(prefix="\t\t")
assert result == expected

@pytest.mark.parametrize("expected, verbose_level",
(
('Diff #1: Item root[5] added to dictionary.'
'\nDiff #2: Item root[3] removed from dictionary.'
'\nDiff #3: Type of root[2] changed from int to str and value changed from 2 to "b".'
'\nDiff #4: Value of root[4] changed from 4 to 5.', 0),
('Diff #1: Item root[5] (5) added to dictionary.'
'\nDiff #2: Item root[3] (3) removed from dictionary.'
'\nDiff #3: Type of root[2] changed from int to str and value changed from 2 to "b".'
'\nDiff #4: Value of root[4] changed from 4 to 5.', 2),
), ids=("verbose=0", "verbose=2")
)
def test_pretty_form_method_prefixed_callback(self, expected, verbose_level):
def prefix_callback(**kwargs):
"""Helper function using a hidden variable on the diff that tracks which count prints next"""
kwargs['diff']._diff_count = 1 + getattr(kwargs['diff'], '_diff_count', 0)
return f"Diff #{kwargs['diff']._diff_count}: "

t1 = {2: 2, 3: 3, 4: 4}
t2 = {2: 'b', 4: 5, 5: 5}
ddiff = DeepDiff(t1, t2, verbose_level=verbose_level)
result = ddiff.pretty(prefix=prefix_callback)
assert result == expected

@pytest.mark.parametrize('test_num, value, func_to_convert_back', [
(1, {'10': None}, None),
(2, {"type_changes": {"root": {"old_type": None, "new_type": list, "new_value": ["你好", 2, 3, 5]}}}, None),
Expand Down
Loading