Last active
March 5, 2022 02:46
-
-
Save euccas/273764b6ec57142655ef6ff01bc8d83b to your computer and use it in GitHub Desktop.
compare yaml files, report diff in tags, recursively
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def rdiff(yamla, yamlb, path='', key=getkey): | |
if isinstance(yamla, list) and isinstance(yamlb, list): | |
for d in listdiff(yamla, yamlb, path=path, key=key): | |
yield d | |
elif isinstance(yamla, dict) and isinstance(yamlb, dict): | |
for d in dictdiff(yamla, yamlb, path=path, key=key): | |
yield d | |
else: | |
if yamla != yamlb: | |
yield (path, 'value_difference', yamla, '-->', yamlb) | |
def listdiff(yamla, yamlb, path, key): | |
""" compute the differences between two lists, as a generator | |
:param list yamla: list of python objects | |
:param list yamlb: list of python objects | |
:param str path: path of current node (same idea as XPath) | |
:param callable key: key lambda used for sorting | |
""" | |
yamla = {key(v, i): v for i, v in enumerate(yamla)} | |
yamlb = {key(v, i): v for i, v in enumerate(yamlb)} | |
keysa = set(yamla.keys()) | |
keysb = set(yamlb.keys()) | |
for a in [k for k in keysb.difference(keysa)]: | |
yield (path + '/' + a, 'added') | |
for m in [k for k in keysa.difference(keysb)]: | |
yield (path + '/' + m, 'missing') | |
common = [k for k in keysa.intersection(keysb) if k] | |
for k in common: | |
if (isinstance(yamla[k], list) and isinstance(yamlb, list)) \ | |
or (isinstance(yamla[k], dict) and isinstance(yamlb, dict)): | |
for d in rdiff(yamla[k], yamlb[k], path + '/' + k): | |
yield d | |
else: | |
for d in rdiff(yamla[k], yamlb[k], path + '/' + k, key): | |
yield d | |
def dictdiff(yamla, yamlb, path, key): | |
"""compute the difference between two dictionaries, as a generator | |
:param dict yamla: first dictionary | |
:param dict yamlb: second dictionary to compare with first one | |
:param str path: path of current node (same idea as XPath) | |
:param callable key: key lambda used for sorting | |
""" | |
keysa = set(yamla.keys()) | |
keysb = set(yamlb.keys()) | |
for a in [k for k in keysb.difference(keysa)]: | |
yield (path + '/' + a, 'added') | |
for m in [k for k in keysa.difference(keysb)]: | |
yield (path + '/' + m, 'missing') | |
common = [k for k in keysa.intersection(keysb) if k] | |
for k in common: | |
if (isinstance(yamla[k], list) and isinstance(yamlb[k], list)) \ | |
or (isinstance(yamla[k], dict) and isinstance(yamlb[k], dict)): | |
for d in rdiff(yamla[k], yamlb[k], path + '/' + k, key): | |
yield d | |
else: | |
for d in rdiff(yamla[k], yamlb[k], path + '/' + k, key): | |
yield d | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
i am using your code to help learn python. Can you let me know what the getkey function looks like. This way i can run it to see how it works and what it does