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:
@@ -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
|
||||||
|
@@ -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},
|
||||||
|
Reference in New Issue
Block a user