~smoser/ubuntu/xenial/cloud-init/lp1506187

« back to all changes in this revision

Viewing changes to cloudinit/mergers/m_dict.py

  • Committer: Package Import Robot
  • Author(s): Scott Moser
  • Date: 2013-04-11 12:55:51 UTC
  • mfrom: (245.3.9 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20130411125551-8k60jsoot7t21z4b
* New upstream snapshot.
  * make apt-get invoke 'dist-upgrade' rather than 'upgrade' for
    package_upgrade. (LP: #1164147)
  * workaround 2.6 kernel issue that stopped blkid from showing /dev/sr0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# vi: ts=4 expandtab
2
 
#
3
 
#    Copyright (C) 2012 Yahoo! Inc.
4
 
#
5
 
#    Author: Joshua Harlow <harlowja@yahoo-inc.com>
6
 
#
7
 
#    This program is free software: you can redistribute it and/or modify
8
 
#    it under the terms of the GNU General Public License version 3, as
9
 
#    published by the Free Software Foundation.
10
 
#
11
 
#    This program is distributed in the hope that it will be useful,
12
 
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
#    GNU General Public License for more details.
15
 
#
16
 
#    You should have received a copy of the GNU General Public License
17
 
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 
 
19
 
DEF_MERGE_TYPE = 'no_replace'
20
 
MERGE_TYPES = ('replace', DEF_MERGE_TYPE,)
21
 
 
22
 
 
23
 
def _has_any(what, *keys):
24
 
    for k in keys:
25
 
        if k in what:
26
 
            return True
27
 
    return False
28
 
 
29
 
 
30
 
class Merger(object):
31
 
    def __init__(self, merger, opts):
32
 
        self._merger = merger
33
 
        # Affects merging behavior...
34
 
        self._method = DEF_MERGE_TYPE
35
 
        for m in MERGE_TYPES:
36
 
            if m in opts:
37
 
                self._method = m
38
 
                break
39
 
        # Affect how recursive merging is done on other primitives.
40
 
        self._recurse_str = 'recurse_str' in opts
41
 
        self._recurse_array = _has_any(opts, 'recurse_array', 'recurse_list')
42
 
        self._allow_delete = 'allow_delete' in opts
43
 
        # Backwards compat require this to be on.
44
 
        self._recurse_dict = True
45
 
 
46
 
    def __str__(self):
47
 
        s = ('DictMerger: (method=%s,recurse_str=%s,'
48
 
             'recurse_dict=%s,recurse_array=%s,allow_delete=%s)')
49
 
        s = s % (self._method, self._recurse_str,
50
 
                 self._recurse_dict, self._recurse_array, self._allow_delete)
51
 
        return s
52
 
 
53
 
    def _do_dict_replace(self, value, merge_with, do_replace):
54
 
 
55
 
        def merge_same_key(old_v, new_v):
56
 
            if do_replace:
57
 
                return new_v
58
 
            if isinstance(new_v, (list, tuple)) and self._recurse_array:
59
 
                return self._merger.merge(old_v, new_v)
60
 
            if isinstance(new_v, (basestring)) and self._recurse_str:
61
 
                return self._merger.merge(old_v, new_v)
62
 
            if isinstance(new_v, (dict)) and self._recurse_dict:
63
 
                return self._merger.merge(old_v, new_v)
64
 
            # Otherwise leave it be...
65
 
            return old_v
66
 
 
67
 
        for (k, v) in merge_with.items():
68
 
            if k in value:
69
 
                if v is None and self._allow_delete:
70
 
                    value.pop(k)
71
 
                else:
72
 
                    value[k] = merge_same_key(value[k], v)
73
 
            else:
74
 
                value[k] = v
75
 
        return value
76
 
 
77
 
    def _on_dict(self, value, merge_with):
78
 
        if not isinstance(merge_with, (dict)):
79
 
            return value
80
 
        if self._method == 'replace':
81
 
            merged = self._do_dict_replace(dict(value), merge_with, True)
82
 
        elif self._method == 'no_replace':
83
 
            merged = self._do_dict_replace(dict(value), merge_with, False)
84
 
        else:
85
 
            raise NotImplementedError("Unknown merge type %s" % (self._method))
86
 
        return merged