Skip to content

Commit 2a05ab4

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

3 files changed

Lines changed: 48 additions & 12 deletions

File tree

netjsonconfig/backends/base/backend.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@ 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__(
30+
self,
31+
config=None,
32+
native=None,
33+
templates=None,
34+
templates_list_handling=None,
35+
context=None,
36+
):
3037
"""
3138
:param config: ``dict`` containing a valid **NetJSON** configuration dictionary
3239
:param native: ``str`` or file object representing a native configuration that will
@@ -44,7 +51,7 @@ def __init__(self, config=None, native=None, templates=None, context=None):
4451
if config is not None:
4552
# perform deepcopy to avoid modifying the original config argument
4653
config = deepcopy(self._load(config))
47-
self.config = self._merge_config(config, templates)
54+
self.config = self._merge_config(config, templates, templates_list_handling)
4855
self.config = self._evaluate_vars(self.config, context)
4956
# backward conversion (native configuration > NetJSON)
5057
elif native is not None:
@@ -70,7 +77,7 @@ def _load(self, config):
7077
)
7178
return config
7279

73-
def _merge_config(self, config, templates):
80+
def _merge_config(self, config, templates, templates_list_handling):
7481
"""
7582
Merges config with templates
7683
"""
@@ -82,8 +89,18 @@ def _merge_config(self, config, templates):
8289
# merge templates with main configuration
8390
result = {}
8491
config_list = templates + [config]
85-
for merging in config_list:
86-
result = merge_config(result, self._load(merging), self.list_identifiers)
92+
for i, merging in enumerate(config_list):
93+
if i < len(templates):
94+
result = merge_config(
95+
result,
96+
self._load(merging),
97+
self.list_identifiers,
98+
templates_list_handling[i],
99+
)
100+
else:
101+
result = merge_config(
102+
result, self._load(merging), self.list_identifiers
103+
)
87104
return result
88105

89106
def _evaluate_vars(self, config, context):

netjsonconfig/backends/openwrt/openwrt.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ 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,
40+
config=None,
41+
native=None,
42+
templates=None,
43+
templates_list_handling=None,
44+
context=None,
45+
dsa=True,
4046
):
4147
"""
4248
:param config: ``dict`` containing a valid **NetJSON** configuration dictionary
@@ -52,7 +58,7 @@ def __init__(
5258
``templates`` is not of type ``list``
5359
"""
5460
self.dsa = dsa
55-
super().__init__(config, native, templates, context)
61+
super().__init__(config, native, templates, templates_list_handling, context)
5662

5763
def _generate_contents(self, tar):
5864
"""

netjsonconfig/utils.py

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

55

6-
def merge_config(template, config, list_identifiers=None):
6+
def merge_config(
7+
template, config, list_identifiers=None, list_handling='append_at_end'
8+
):
79
"""
810
Merges ``config`` on top of ``template``.
911
@@ -24,15 +26,17 @@ def merge_config(template, config, list_identifiers=None):
2426
for key, value in config.items():
2527
if isinstance(value, dict):
2628
node = result.get(key, OrderedDict())
27-
result[key] = merge_config(node, value)
29+
result[key] = merge_config(node, value, 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(
32+
result[key], value, list_identifiers, list_handling
33+
)
3034
else:
3135
result[key] = value
3236
return result
3337

3438

35-
def merge_list(list1, list2, identifiers=None):
39+
def merge_list(list1, list2, identifiers=None, list_handling='append_at_end'):
3640
"""
3741
Merges ``list2`` on top of ``list1``.
3842
@@ -47,6 +51,8 @@ def merge_list(list1, list2, identifiers=None):
4751
:param identifiers: ``list`` or ``None``
4852
:returns: merged ``list``
4953
"""
54+
if list_handling == 'override':
55+
return list2
5056
identifiers = identifiers or []
5157
dict_map = {'list1': OrderedDict(), 'list2': OrderedDict()}
5258
counter = 1
@@ -74,7 +80,14 @@ def merge_list(list1, list2, identifiers=None):
7480
key = tuple(key)
7581
container[key] = deepcopy(el)
7682
counter += 1
77-
merged = merge_config(dict_map['list1'], dict_map['list2'])
83+
if list_handling == 'insert_at_beginning':
84+
merged = merge_config(
85+
dict_map['list2'], dict_map['list1'], list_handling=list_handling
86+
)
87+
else:
88+
merged = merge_config(
89+
dict_map['list1'], dict_map['list2'], list_handling=list_handling
90+
)
7891
return list(merged.values())
7992

8093

0 commit comments

Comments
 (0)