Skip to content

Commit 40101f1

Browse files
authored
Merge pull request #3356 from kelseymh/3348_allow_update_dict
Add support for updating dictionary or tuple keys in self.cfg
2 parents c89945d + 8bcc08e commit 40101f1

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

easybuild/framework/easyconfig/easyconfig.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -574,30 +574,50 @@ def copy(self, validate=None):
574574

575575
def update(self, key, value, allow_duplicate=True):
576576
"""
577-
Update a string configuration value with a value (i.e. append to it).
577+
Update an easyconfig parameter with the specified value (i.e. append to it).
578+
Note: For dictionary easyconfig parameters, 'allow_duplicate' is ignored (since it's meaningless).
578579
"""
579580
if isinstance(value, string_type):
580-
lval = [value]
581-
elif isinstance(value, list):
582-
lval = value
581+
inval = [value]
582+
elif isinstance(value, (list, dict, tuple)):
583+
inval = value
583584
else:
584-
msg = "Can't update configuration value for %s, because the "
585-
msg += "attempted update value, '%s', is not a string or list."
585+
msg = "Can't update configuration value for %s, because the attempted"
586+
msg += " update value, '%s', is not a string, list, tuple or dictionary."
586587
raise EasyBuildError(msg, key, value)
587588

588-
param_value = self[key]
589+
# For easyconfig parameters that are dictionaries, input value must also be a dictionary
590+
if isinstance(self[key], dict) and not isinstance(value, dict):
591+
msg = "Can't update configuration value for %s, because the attempted"
592+
msg += "update value (%s), is not a dictionary (type: %s)."
593+
raise EasyBuildError(msg, key, value, type(value))
594+
595+
# Grab current parameter value so we can modify it
596+
param_value = copy.deepcopy(self[key])
597+
589598
if isinstance(param_value, string_type):
590-
for item in lval:
599+
for item in inval:
591600
# re.search: only add value to string if it's not there yet (surrounded by whitespace)
592601
if allow_duplicate or (not re.search(r'(^|\s+)%s(\s+|$)' % re.escape(item), param_value)):
593602
param_value = param_value + ' %s ' % item
594-
elif isinstance(param_value, list):
595-
for item in lval:
603+
604+
elif isinstance(param_value, (list, tuple)):
605+
# make sure we have a list value so we can just append to it
606+
param_value = list(param_value)
607+
for item in inval:
596608
if allow_duplicate or item not in param_value:
597-
param_value = param_value + [item]
609+
param_value.append(item)
610+
# cast back to tuple if original value was a tuple
611+
if isinstance(self[key], tuple):
612+
param_value = tuple(param_value)
613+
614+
elif isinstance(param_value, dict):
615+
param_value.update(inval)
598616
else:
599-
raise EasyBuildError("Can't update configuration value for %s, because it's not a string or list.", key)
617+
msg = "Can't update configuration value for %s, because it's not a string, list, tuple or dictionary."
618+
raise EasyBuildError(msg, key)
600619

620+
# Overwrite easyconfig parameter value with updated value, preserving type
601621
self[key] = param_value
602622

603623
def set_keys(self, params):

test/framework/easyconfig.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,10 @@ def test_update(self):
17441744
ec.update('patches', ['foo2.patch', 'bar2.patch'], allow_duplicate=False)
17451745
self.assertEqual(ec['patches'], patches_tmp)
17461746

1747+
# for dictionary values: extend, test for existence (not ordering)
1748+
ec.update('sanity_check_paths', {'key1': 'value1'})
1749+
self.assertTrue(ec['sanity_check_paths']['key1'] == 'value1')
1750+
17471751
def test_hide_hidden_deps(self):
17481752
"""Test use of --hide-deps on hiddendependencies."""
17491753
test_dir = os.path.dirname(os.path.abspath(__file__))

0 commit comments

Comments
 (0)