doc_diff() optionally no longer reports differences between falsey values.

If falsey_is_equal=True, all Falsey values compare as equal, i.e. this
function won't report differences between DoesNotExist, False, '', and 0.
This commit is contained in:
2016-10-12 17:09:48 +02:00
parent 7c310e12ef
commit 96c9e12f7f
2 changed files with 35 additions and 1 deletions

View File

@@ -115,11 +115,19 @@ def gravatar(email, size=64):
"?" + urllib.urlencode(parameters) "?" + urllib.urlencode(parameters)
class MetaFalsey(type):
def __nonzero__(cls):
return False
__bool__ = __nonzero__ # for Python 3
class DoesNotExist(object): class DoesNotExist(object):
"""Returned as value by doc_diff if a value does not exist.""" """Returned as value by doc_diff if a value does not exist."""
__metaclass__ = MetaFalsey
def doc_diff(doc1, doc2): def doc_diff(doc1, doc2, falsey_is_equal=True):
"""Generator, yields differences between documents. """Generator, yields differences between documents.
Yields changes as (key, value in doc1, value in doc2) tuples, where Yields changes as (key, value in doc1, value in doc2) tuples, where
@@ -128,6 +136,9 @@ def doc_diff(doc1, doc2):
Sub-documents (i.e. dicts) are recursed, and dot notation is used Sub-documents (i.e. dicts) are recursed, and dot notation is used
for the keys if changes are found. for the keys if changes are found.
If falsey_is_equal=True, all Falsey values compare as equal, i.e. this
function won't report differences between DoesNotExist, False, '', and 0.
""" """
for key in set(doc1.keys()).union(set(doc2.keys())): for key in set(doc1.keys()).union(set(doc2.keys())):
@@ -145,5 +156,7 @@ def doc_diff(doc1, doc2):
if val1 == val2: if val1 == val2:
continue continue
if falsey_is_equal and bool(val1) == bool(val2) == False:
continue
yield key, val1, val2 yield key, val1, val2

View File

@@ -54,6 +54,27 @@ class DocDiffTest(unittest.TestCase):
self.assertEqual([(3, 42, 513)], list(diff)) self.assertEqual([(3, 42, 513)], list(diff))
def test_diff_values_falsey(self):
from pillar.api.utils import doc_diff, DoesNotExist
# DoesNotExist vs. empty string
diff = doc_diff({'a': 'b', 3: ''},
{'a': 'b'})
self.assertEqual([], list(diff))
diff = doc_diff({'a': 'b', 3: ''},
{'a': 'b'}, falsey_is_equal=False)
self.assertEqual([(3, '', DoesNotExist)], list(diff))
# Empty string vs. None
diff = doc_diff({'a': 'b', 3: ''},
{'a': 'b', 3: None})
self.assertEqual([], list(diff))
diff = doc_diff({'a': 'b', 3: ''},
{'a': 'b', 3: None}, falsey_is_equal=False)
self.assertEqual([(3, '', None)], list(diff))
def test_diff_keys_simple(self): def test_diff_keys_simple(self):
from pillar.api.utils import doc_diff, DoesNotExist from pillar.api.utils import doc_diff, DoesNotExist
diff = doc_diff({'a': 'b', 3: 42}, diff = doc_diff({'a': 'b', 3: 42},