Mercurial > hgrepos > Python > libs > ConfigMix
diff configmix/__init__.py @ 276:af371f9c016d
Allow deletion of key-value pairs when merging is done.
When encountering the "{{::DEL::}}" special value the corresponding key-value
pair is deleted.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sat, 03 Oct 2020 17:11:41 +0200 |
| parents | e2fd8fea1a4c |
| children | 57fca7448740 |
line wrap: on
line diff
--- a/configmix/__init__.py Sat Oct 03 15:52:30 2020 +0200 +++ b/configmix/__init__.py Sat Oct 03 17:11:41 2020 +0200 @@ -13,7 +13,7 @@ from __future__ import division, print_function, absolute_import -__version__ = "0.10.1.dev1" +__version__ = "0.11.0.dev1" __revision__ = "|VCSRevision|" __date__ = "|VCSJustDate|" @@ -50,6 +50,12 @@ """ +DEL_VALUE = u("{{::DEL::}}") +"""Value for configuration items to signal that the corresponding +key-value is to be deleted when configurations are merged + +""" + def load(*files, **kwargs): """Load the given configuration files, merge them in the given order @@ -418,12 +424,17 @@ The configuration in `default` will be changed **inplace** when filtering out comments (which is the default). + If a value in `user` is equal to :data:`.DEL_VALUE` + (``{{::DEL::}}``) the corresponding key will be deleted from the + merged output. + From http://stackoverflow.com/questions/823196/yaml-merge-in-python """ if user is None: if filter_comments: _filter_comments(default) + _filter_deletions(default) return default if filter_comments: _filter_comments(user) @@ -431,10 +442,15 @@ for k, v in default.items(): if filter_comments and _is_comment(k): continue - if k not in user: + if k in user: + if user[k] == DEL_VALUE: + # do not copy + del user[k] + else: + user[k] = _merge(user[k], v, filter_comments) + else: user[k] = v - else: - user[k] = _merge(user[k], v, filter_comments) + _filter_deletions(user) return user @@ -446,10 +462,14 @@ for k, v in default.items(): if filter_comments and _is_comment(k): continue - if k not in user: + if k in user: + if user[k] == DEL_VALUE: + # do not copy + del user[k] + else: + user[k] = _merge(user[k], v, filter_comments) + else: user[k] = v - else: - user[k] = _merge(user[k], v, filter_comments) return user @@ -466,6 +486,7 @@ if user is None: if filter_comments: _filter_comments(default) + _filter_deletions(default) return copy.deepcopy(default) user = copy.deepcopy(user) if filter_comments: @@ -474,10 +495,15 @@ for k, v in default.items(): if filter_comments and _is_comment(k): continue - if k not in user: + if k in user: + if user[k] == DEL_VALUE: + # do not copy + del user[k] + else: + user[k] = _safe_merge(user[k], v, filter_comments) + else: user[k] = copy.deepcopy(v) - else: - user[k] = _safe_merge(user[k], v, filter_comments) + _filter_deletions(user) return user @@ -489,10 +515,14 @@ for k, v in default.items(): if filter_comments and _is_comment(k): continue - if k not in user: + if k in user: + if user[k] == DEL_VALUE: + # do not copy + del user[k] + else: + user[k] = _safe_merge(user[k], v, filter_comments) + else: user[k] = copy.deepcopy(v) - else: - user[k] = _safe_merge(user[k], v, filter_comments) return user @@ -525,6 +555,23 @@ return False +def _filter_deletions(d): + """Recursively filter deletions in the dict `d`. + + Deletions have values that equal :data:`.DEL_VALUE`. + + """ + if not isinstance(d, dict): + return + # use a copy of the items because we change `d` while iterating + for k, v in list(d.items()): + if v == DEL_VALUE: + del d[k] + else: + if isinstance(d[k], dict): + _filter_deletions(d[k]) + + # # Init loader defaults: mode->loader and extension->mode #
