Skip to content

Commit 3670013

Browse files
committed
[feature] Add possibility to change list handling behaviour #153
Closes #153
1 parent 571af14 commit 3670013

File tree

3 files changed

+32
-12
lines changed

3 files changed

+32
-12
lines changed

netjsonconfig/backends/base/backend.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class BaseBackend(object):
2626
FILE_SECTION_DELIMITER = '# ---------- files ---------- #'
2727
list_identifiers = []
2828

29-
def __init__(self, config=None, native=None, templates=None, context=None):
29+
def __init__(self, config=None, native=None, templates=None,
30+
templates_list_handling=None, context=None):
3031
"""
3132
:param config: ``dict`` containing a valid **NetJSON** configuration dictionary
3233
:param native: ``str`` or file object representing a native configuration that will
@@ -44,7 +45,8 @@ def __init__(self, config=None, native=None, templates=None, context=None):
4445
if config is not None:
4546
# perform deepcopy to avoid modifying the original config argument
4647
config = deepcopy(self._load(config))
47-
self.config = self._merge_config(config, templates)
48+
self.config = self._merge_config(config, templates,
49+
templates_list_handling)
4850
self.config = self._evaluate_vars(self.config, context)
4951
# backward conversion (native configuration > NetJSON)
5052
elif native is not None:
@@ -70,7 +72,7 @@ def _load(self, config):
7072
)
7173
return config
7274

73-
def _merge_config(self, config, templates):
75+
def _merge_config(self, config, templates, templates_list_handling):
7476
"""
7577
Merges config with templates
7678
"""
@@ -82,8 +84,14 @@ def _merge_config(self, config, templates):
8284
# merge templates with main configuration
8385
result = {}
8486
config_list = templates + [config]
85-
for merging in config_list:
86-
result = merge_config(result, self._load(merging), self.list_identifiers)
87+
for i, merging in enumerate(config_list):
88+
if i < len(templates):
89+
result = merge_config(result, self._load(merging),
90+
self.list_identifiers,
91+
templates_list_handling[i])
92+
else:
93+
result = merge_config(result, self._load(merging),
94+
self.list_identifiers)
8795
return result
8896

8997
def _evaluate_vars(self, config, context):

netjsonconfig/backends/openwrt/openwrt.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ class OpenWrt(BaseBackend):
3636
list_identifiers = ['name', 'config_value', 'id']
3737

3838
def __init__(
39-
self, config=None, native=None, templates=None, context=None, dsa=True
39+
self, config=None, native=None, templates=None,
40+
templates_list_handling=None, context=None, dsa=True
4041
):
4142
"""
4243
:param config: ``dict`` containing a valid **NetJSON** configuration dictionary
@@ -52,7 +53,8 @@ def __init__(
5253
``templates`` is not of type ``list``
5354
"""
5455
self.dsa = dsa
55-
super().__init__(config, native, templates, context)
56+
super().__init__(config, native, templates,
57+
templates_list_handling, context)
5658

5759
def _generate_contents(self, tar):
5860
"""

netjsonconfig/utils.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
from copy import deepcopy
44

55

6-
def merge_config(template, config, list_identifiers=None):
6+
def merge_config(template, config, list_identifiers=None,
7+
list_handling='append_at_end'):
78
"""
89
Merges ``config`` on top of ``template``.
910
@@ -24,15 +25,17 @@ def merge_config(template, config, list_identifiers=None):
2425
for key, value in config.items():
2526
if isinstance(value, dict):
2627
node = result.get(key, OrderedDict())
27-
result[key] = merge_config(node, value)
28+
result[key] = merge_config(node, value,
29+
list_handling=list_handling)
2830
elif isinstance(value, list) and isinstance(result.get(key), list):
29-
result[key] = merge_list(result[key], value, list_identifiers)
31+
result[key] = merge_list(result[key], value, list_identifiers,
32+
list_handling)
3033
else:
3134
result[key] = value
3235
return result
3336

3437

35-
def merge_list(list1, list2, identifiers=None):
38+
def merge_list(list1, list2, identifiers=None, list_handling='append_at_end'):
3639
"""
3740
Merges ``list2`` on top of ``list1``.
3841
@@ -47,6 +50,8 @@ def merge_list(list1, list2, identifiers=None):
4750
:param identifiers: ``list`` or ``None``
4851
:returns: merged ``list``
4952
"""
53+
if list_handling == 'override':
54+
return list2
5055
identifiers = identifiers or []
5156
dict_map = {'list1': OrderedDict(), 'list2': OrderedDict()}
5257
counter = 1
@@ -74,7 +79,12 @@ def merge_list(list1, list2, identifiers=None):
7479
key = tuple(key)
7580
container[key] = deepcopy(el)
7681
counter += 1
77-
merged = merge_config(dict_map['list1'], dict_map['list2'])
82+
if list_handling == 'insert_at_beginning':
83+
merged = merge_config(dict_map['list2'], dict_map['list1'],
84+
list_handling=list_handling)
85+
else:
86+
merged = merge_config(dict_map['list1'], dict_map['list2'],
87+
list_handling=list_handling)
7888
return list(merged.values())
7989

8090

0 commit comments

Comments
 (0)