def mixed_branch_levels_merges_ok(self): d1 = {"foo": {"bar": {"biz": "baz"}}, "meh": 17, "myown": "ok"} d2 = {"foo": {"bar": {"biz": "notbaz"}}, "meh": 25} merge_dicts(d1, d2) expected = { "foo": {"bar": {"biz": "notbaz"}}, "meh": 25, "myown": "ok", } assert d1 == expected
def dict_value_merges_are_not_references(self): core = {} coll = {"foo": {"bar": {"biz": "coll value"}}} proj = {"foo": {"bar": {"biz": "proj value"}}} # Initial merge - when bug present, this sets core['foo'] to the entire # 'foo' dict in 'proj' as a reference - meaning it 'links' back to the # 'proj' dict whenever other things are merged into it merge_dicts(core, proj) assert core == {"foo": {"bar": {"biz": "proj value"}}} assert proj["foo"]["bar"]["biz"] == "proj value" # Identity tests can also prove the bug early assert ( core["foo"] is not proj["foo"] ), "Core foo is literally proj foo!" # noqa # Subsequent merge - just overwrites leaf values this time (thus no # real change, but this is what real config merge code does, so why # not) merge_dicts(core, proj) assert core == {"foo": {"bar": {"biz": "proj value"}}} assert proj["foo"]["bar"]["biz"] == "proj value" # The problem merge - when bug present, core['foo'] references 'foo' # inside 'proj', so this ends up tweaking "core" but it actually # affects "proj" as well! merge_dicts(core, coll) # Expect that the core dict got the update from 'coll'... assert core == {"foo": {"bar": {"biz": "coll value"}}} # BUT that 'proj' remains UNTOUCHED assert proj["foo"]["bar"]["biz"] == "proj value"
def nested_leaf_values_merge_ok(self): d1 = {"foo": {"bar": {"biz": "baz"}}} d2 = {"foo": {"bar": {"biz": "notbaz"}}} merge_dicts(d1, d2) assert d1 == {"foo": {"bar": {"biz": "notbaz"}}}
def non_dict_type_mismatch_overwrites_ok(self): d1 = {"foo": "bar"} d2 = {"foo": [1, 2, 3]} merge_dicts(d1, d2) assert d1 == {"foo": [1, 2, 3]}
def merging_nondict_into_dict_raises_error(self): d1 = {"foo": {"uh": "oh"}} d2 = {"foo": "bar"} with raises(AmbiguousMergeError): merge_dicts(d1, d2)
def updates_arg_values_win(self): d1 = {"foo": "bar"} d2 = {"foo": "notbar"} merge_dicts(d1, d2) assert d1 == {"foo": "notbar"}
def orthogonal_data_merges(self): d1 = {"foo": "bar"} d2 = {"biz": "baz"} merge_dicts(d1, d2) assert d1 == {"foo": "bar", "biz": "baz"}
def updating_with_None_acts_like_merging_empty_dict(self): # When bug present, AttributeError is raised on a None.items() d1 = {"my": "data"} d2 = None merge_dicts(d1, d2) assert d1 == {"my": "data"}
def merge_file_types_by_reference(self): with open(__file__) as fd: d1 = {} d2 = {"foo": fd} merge_dicts(d1, d2) assert d1["foo"].closed is False
def merging_data_onto_empty_dict(self): d1 = {} d2 = {"foo": "bar"} merge_dicts(d1, d2) assert d1 == d2