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
9 changes: 9 additions & 0 deletions dictdiffer/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,19 @@ def are_different(first, second, tolerance):
return False

first_is_nan, second_is_nan = bool(first != first), bool(second != second)
first_is_inf, second_is_inf = first == float('inf'), second == float('inf')
first_is_ninf = first == float('-inf')
second_is_ninf = second == float('-inf')

if first_is_nan or second_is_nan:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on a more mathematical level, should two nan or two inf or two -inf be considered the same? It is improbable that two inf are the same when you are running a diff. If we agree that they should be considered the same, then this all looks great!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I asked myself the same question while doing this PR and I found links like this stating that inf==inf and -inf==-inf .

On the contrary, it seems that they agree that Nan!=Nan , but that's outside the scope of this PR.

Let me know if you prefer not considering two inf the same, I can easily adapt tests and code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think following convention is preferred over mathematical precision, so this sounds good to me 👍

# two 'NaN' values are not different (see issue #114)
return not (first_is_nan and second_is_nan)
if first_is_inf or second_is_inf:
# two 'inf' values are not different
return not (first_is_inf and second_is_inf)
if first_is_ninf or second_is_ninf:
# two '-inf' values are not different
return not (first_is_ninf and second_is_ninf)
elif isinstance(first, num_types) and isinstance(second, num_types):
# two numerical values are compared with tolerance
return abs(first-second) > tolerance * max(abs(first), abs(second))
Expand Down
29 changes: 29 additions & 0 deletions tests/test_dictdiffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,35 @@ def test_numpy_nan(self):
result = list(diff(first, second))
assert result == []

def test_inf(self):
first = {'a': [1.0, 2.0, 3.0, 4.0]}
second = {'a': [1.0, 2.0, 3.0, float('inf')]}
diffed = next(diff(first, second))
assert ('change', ['a', 3], (4, float('inf'))) == diffed

first = {'a': [1.0, 2.0, 3.0, 4.0]}
second = {'a': [1.0, 2.0, 3.0, float('-inf')]}
diffed = next(diff(first, second))
assert ('change', ['a', 3], (4, float('-inf'))) == diffed

first = {'a': [1.0, 2.0, 3.0, float('inf')]}
second = {'a': [1.0, 2.0, 3.0, float('inf')]}
result = list(diff(first, second))
assert result == []

first = {'a': [1.0, 2.0, 3.0, float('inf')]}
second = {'a': [1.0, 2.0, 3.0, float('-inf')]}
diffed = next(diff(first, second))
assert ('change', ['a', 3], (float('inf'), float('-inf'))) == diffed

@unittest.skipIf(not HAS_NUMPY, 'NumPy is not installed')
def test_numpy_inf(self):
import numpy as np
first = {'a': [1.0, 2.0, 3.0, 4.0]}
second = {'a': [1.0, 2.0, 3.0, np.float64('inf')]}
diffed = next(diff(first, second))
assert ('change', ['a', 3], (4, np.float64('inf'))) == diffed

def test_unicode_keys(self):
first = {u'привет': 1}
second = {'hello': 1}
Expand Down