Created
May 12, 2017 16:34
-
-
Save brianrusso/a70b1384bf878d407df9d84b6a48f3a9 to your computer and use it in GitHub Desktop.
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
# If add is True (default, it will add them, else it merges. | |
def deepdictmerge(a, b, path=None, add=True): | |
if path is None: path = [] | |
for key in b: # for every key in b.. | |
if key not in a: # handle simple case where it's new | |
a[key] = b[key] | |
else: # key must be in a and b | |
# both dictionaries. | |
if isinstance(a[key], dict) and isinstance(b[key], dict): | |
deepdictmerge(a[key], b[key], path + [str(key)]) # recurse down | |
# if one is a dict and the other has a key.. | |
elif isinstance(a[key], dict) and key in b: | |
raise Exception("a is a dict, but b has key set and is not a dict") | |
# same deal.. switched | |
elif key in a and isinstance(b[key], dict): | |
raise Exception("b is a dict, but a has key set and is not a dict") | |
else: # key is in a and b.. neither are dictionaries | |
if add: # if we're adding.. it's all good | |
a[key] += b[key] | |
else: # we are doing a regular merge | |
if a[key] != b[key]: # they are both set.. and don't match | |
raise Exception('Conflict at %s' % '.'.join(path + [str(key)])) | |
else: # they are both set.. but match | |
pass | |
return a |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment