From 6c8c2d838153f0eaf9f2d74056bab60f63e38acc Mon Sep 17 00:00:00 2001 From: Wirawan Purwanto Date: Thu, 5 Jun 2014 11:30:47 -0400 Subject: [PATCH] * Added: dict_update_nested() for nested dict member copy-update into the destination. * Added most basic test harnesses for that routine. --- sugar.py | 19 +++++++ test_sugar.py | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 test_sugar.py diff --git a/sugar.py b/sugar.py index cc5ee4e..2f54b01 100644 --- a/sugar.py +++ b/sugar.py @@ -97,6 +97,25 @@ def dict_defvals(p, q): for qk in q: dict_defval(p, qk, q[qk]) +def dict_update_nested(p, q, max_nest=100000): + """Recursively copy-update dict p with the contents of q. + This is similar to dict.update() but will copy-update dict members instead of + only updating the dict refs. + Once a maximum nesting level is reached, simple ref updating is done, + as usual. + """ + if max_nest <= 0: + dict.update(p, q) + else: + for (k,v) in dict.iteritems(q): + if isinstance(v, dict): + if (k not in p) or not isinstance(p[k], dict): + p[k] = {} + dict_update_nested(p[k], q[k], max_nest-1) + else: + p[k] = v + + def list_join(*L): r = [] for i in L: diff --git a/test_sugar.py b/test_sugar.py new file mode 100644 index 0000000..e468cfd --- /dev/null +++ b/test_sugar.py @@ -0,0 +1,135 @@ + +from copy import copy, deepcopy +from pprint import pprint +import wpylib.sugar + +def def_dict_data1(): + """[20140605] + """ + global DN1, DN2 + global DN1_orig, DN2_orig + DN1 = { + 'A': 'executive', + 'B': { + 'member': 1, + 'properties': dict( + names = ['Abe'], + keys = ['0xfc133'], + ), + }, + 'C': { + 'member': 3, + 'properties': dict( + names = ['Connor', 'Dewey', 'Elaine'], + keys = ['0x91', 42, -3.241], + nest1 = { + 0: 91, 1: 32, 2: 41, + }, + ), + }, + } + DN1_orig = deepcopy(DN1) + + DN2 = { + 'A': 'slave', + 'B': { + 'member': -1, + 'properties': dict( + bother = 'pooh', + ), + }, + 'C': { + }, + } + DN2_orig = deepcopy(DN2) + + + +def test_dict_update_nested1(): + """[20140605] + """ + from wpylib.sugar import dict_update_nested + def_dict_data1() + DN1 = deepcopy(DN1_orig) + DN2 = deepcopy(DN2_orig) + + print "test_dict_update_nested1():" + print "DN1:" + pprint(DN1) + + print + print "DN2:" + pprint(DN2) + + print + print "Update DN1 with DN2, nested:..." + dict_update_nested(DN1, DN2) + pprint(DN1) + + print + print "# bother DN2:" + DN2['B']['properties']['roo'] = 'kanga' + pprint(DN1) + + print + print "Update DN1 with DN2, nested: max nest = 0..." + DN1 = deepcopy(DN1_orig) + DN2 = deepcopy(DN2_orig) + dict_update_nested(DN1, DN2, max_nest=0) + print "DN1:" + pprint(DN1) + + print + print "# bother DN2: properties should now have 'roo = kanga' mapping" + DN2['B']['properties']['roo'] = 'kanga' + print "DN1:" + pprint(DN1) + + print + print "Update DN1 with DN2, nested: max nest = 1..." + DN1 = deepcopy(DN1_orig) + DN2 = deepcopy(DN2_orig) + dict_update_nested(DN1, DN2, max_nest=1) + print "DN1:" + pprint(DN1) + + print + print "# bother DN2: (clear B dict) -- DN1['B'] should not be affected" + DN2['B'].clear() + print "DN1:" + pprint(DN1) + + + +def test_dict_update_nested2(): + """[20140605] + """ + from wpylib.sugar import dict_update_nested + def_dict_data1() + DN1 = deepcopy(DN1_orig) + DN2 = deepcopy(DN2_orig) + + print "test_dict_update_nested2():" + print "DN1:" + pprint(DN1) + + print + print "DN2:" + pprint(DN2) + + print + print "Update DN2 with DN1, nested:..." + dict_update_nested(DN2, DN1) + pprint(DN2) + + print + print "Update DN2 with DN1, nested: max nest = 0..." + DN1 = deepcopy(DN1_orig) + DN2 = deepcopy(DN2_orig) + dict_update_nested(DN2, DN1, max_nest=0) + pprint(DN2) + + +if __name__ == "__main__": + test_dict_update_nested1() +