From: Peter Otten on
Douglas Garstang wrote:

> I have the two dictionaries below. How can I merge them, such that:
>
> 1. The cluster dictionary contains the additional elements from the
> default dictionary.
> 2. Nothing is removed from the cluster dictionary.

def inplace_merge(default, cluster):
assert isinstance(default, dict)
assert isinstance(cluster, dict)

d = set(default)
c = set(cluster)
default_only = d - c
both = d & c
for key in both:
dv = default[key]
cv = cluster[key]
if isinstance(cv, dict):
inplace_merge(dv, cv)
cluster.update((dk, default[dk]) for dk in default_only)

should work once you've fixed your example dicts.

Peter
From: Douglas Garstang on
On Mon, Aug 2, 2010 at 12:47 AM, Paul Rubin <no.email(a)nospam.invalid> wrote:
> Douglas Garstang <doug.garstang(a)gmail.com> writes:
>> default = {...
>>                 'data_sources': { ...
>> cluster = {...
>>                 'data_source': { ...
>
> Did you want both of those to say the same thing instead of one
> of them being 'data_source' and the other 'data_sources' ?
>
> If yes, then the following works for me:
>
>    def merge(cluster, default):
>        # destructively merge default into cluster
>        for k,v in cluster.iteritems():
>            if k in default and type(v)==dict:
>                assert type(default(k))==dict
>                merge(v,default[k])
>        for k,v in default.iteritems():
>            if k not in cluster:
>                cluster[k] = v
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Hmmm, using that gives me:

Traceback (most recent call last):
File "./test4.py", line 48, in ?
merge(cluster, default)
File "./test4.py", line 42, in merge
assert type(default(k))==dict
TypeError: 'dict' object is not callable

where line 42 is 'assert type(default(k))==dict', and the inputs are:

default = {
'cluster': {
'platform': {
'elements': {
'data_sources': {
'elements': {
'db_min_pool_size': 10
},
},
},
},
}
}

cluster = {
'cluster': {
'name': 'Customer 1',
'description': 'Customer Production',
'environment': 'production',
'platform': {
'elements': {
'data_source': {
'elements': {
'username': 'username',
'password': 'password'
},
},
},
},
}
}

and it's called with:

merge(cluster, default)

Doug.
From: Peter Otten on
Douglas Garstang wrote:

> On Mon, Aug 2, 2010 at 12:47 AM, Paul Rubin <no.email(a)nospam.invalid>
wrote:

>> If yes, then the following works for me:
>>
>> def merge(cluster, default):
>> # destructively merge default into cluster
>> for k,v in cluster.iteritems():
>> if k in default and type(v)==dict:
>> assert type(default(k))==dict
>> merge(v,default[k])
>> for k,v in default.iteritems():
>> if k not in cluster:
>> cluster[k] = v
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>
> Hmmm, using that gives me:
>
> Traceback (most recent call last):
> File "./test4.py", line 48, in ?
> merge(cluster, default)
> File "./test4.py", line 42, in merge
> assert type(default(k))==dict
> TypeError: 'dict' object is not callable
>
> where line 42 is 'assert type(default(k))==dict', and the inputs are:

Not making an attempt to understand the code that you are about to use?

default(k)

should be

default[k]

Peter

From: Douglas Garstang on
On Mon, Aug 2, 2010 at 1:09 AM, Peter Otten <__peter__(a)web.de> wrote:
> Douglas Garstang wrote:
>
>> I have the two dictionaries below. How can I merge them, such that:
>>
>> 1. The cluster dictionary contains the additional elements from the
>> default dictionary.
>> 2. Nothing is removed from the cluster dictionary.
>
> def inplace_merge(default, cluster):
>    assert isinstance(default, dict)
>    assert isinstance(cluster, dict)
>
>    d = set(default)
>    c = set(cluster)
>    default_only = d - c
>    both = d & c
>    for key in both:
>        dv = default[key]
>        cv = cluster[key]
>        if isinstance(cv, dict):
>            inplace_merge(dv, cv)
>    cluster.update((dk, default[dk]) for dk in default_only)
>
> should work once you've fixed your example dicts.
>
> Peter
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Wooo! I think that did it!
From: Paul Rubin on
Douglas Garstang <doug.garstang(a)gmail.com> writes:
> where line 42 is 'assert type(default(k))==dict', and the inputs are:

Woops, cut and paste error. default(k) should say default[k]. Or you
could remove the assertion altogether.