Skip to content

Commit

Permalink
Keep merge suffix for nested dictionaries
Browse files Browse the repository at this point in the history
This is necessary to make possible merging dictionaries
in adjust rules. Otherwise they would be always set (instead of update).

Fix: #276
Reopen: #190
  • Loading branch information
lukaszachy committed Jan 14, 2025
1 parent 95c9745 commit 29c5767
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 9 deletions.
22 changes: 22 additions & 0 deletions docs/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ or when merging a dictionary with a list.
Exception ``MergeError`` is raised if types are not compatible. When
the ``+`` suffix is applied on dictionaries ``update()`` method is
used to merge content of given dictionary instead of replacing it.
When such parent dictionary doesn't exist, but the suffix ``+`` is used
at the top level, the dictionary is created and named without the suffix.
However, for dictionaries at deeper levels, the suffix remains in their name.

Example: Merging dictionary with a list::

Expand Down Expand Up @@ -159,6 +162,25 @@ results in::
url: https://github.com/project2
filter: "tier:2"

Example: Merging with not yet defined dictionaries::

environment+:
CLEAR: "1"
adjust+:
when: distro == fedora
environment+:
FEDORA: "1"

results in (no ``+`` suffix in ``adjust`` and top ``environment`` keys)::

adjust:
when: distro == fedora
environment+:
FEDORA: "1"
environment:
CLEAR: "1"


The special suffix ``+<`` can be used to prepend values instead of
appending them. This might be handy when adjusting lists::

Expand Down
1 change: 1 addition & 0 deletions examples/deep/main.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ hardware:
model: e1000

# A deep dictionary extending non-existent values
# should keep '+' (important for adjust)
/single:
undefined+:
deeper+:
Expand Down
8 changes: 1 addition & 7 deletions fmf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,7 @@ def _merge_plus(self, data, key, value, prepend=False):

# Set the value if key is not present
if key not in data:
# Special handling for dictionaries as their keys might
# contain suffixes which should be removed
if isinstance(value, dict):
data[key] = {}
self._merge_special(data[key], value)
else:
data[key] = value
data[key] = value
return

# Parent is a list of dict and child is a dict
Expand Down
20 changes: 18 additions & 2 deletions tests/unit/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import threading
import time
from shutil import rmtree
from textwrap import dedent

import pytest
from ruamel.yaml import YAML
Expand Down Expand Up @@ -137,6 +138,21 @@ def test_adjust_strips_control_keys(self):
assert 'because' not in child.data
assert 'foo' in child.data

def test_adjust_can_extend(self):
""" It is possible to extend dictionary with adjust """
tree = Tree(YAML(typ='safe').load(dedent("""
/a:
environment+:
FOO: bar
adjust+:
environment+:
BAR: baz
""")))
tree.adjust(context=Context())
child = tree.find('/a')
assert child.data['environment']['FOO'] == "bar"
assert child.data['environment']['BAR'] == "baz"

def test_deep_hierarchy(self):
""" Deep hierarchy on one line """
deep = Tree(EXAMPLES + "deep")
Expand All @@ -154,12 +170,12 @@ def test_deep_dictionary_undefined_keys(self):
""" Extending undefined keys using '+' should work """
deep = Tree(EXAMPLES + "deep")
single = deep.find("/single")
assert single.get(["undefined", "deeper", "key"]) == "value"
assert single.get(["undefined", "deeper+", "key"]) == "value"
child = deep.find("/parent/child")
assert child.get("one") == 2
assert child.get("two") == 4
assert child.get("three") == 3
assert child.get(["undefined", "deeper", "key"]) == "value"
assert child.get(["undefined", "deeper+", "key"]) == "value"

def test_merge_plus(self):
""" Extending attributes using the '+' suffix """
Expand Down

0 comments on commit 29c5767

Please sign in to comment.