Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion easybuild/framework/easyconfig/tweak.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ def __repr__(self):
for (key, val) in tweaks.items():

if isinstance(val, list):
regexp = re.compile(r"^(?P<key>\s*%s)\s*=\s*(?P<val>\[(.|\n)*\])\s*$" % key, re.M)
# use non-greedy matching for list value using '*?' to avoid including other parameters in match,
# and a lookahead assertion (?=...) so next line is either another parameter definition or a blank line
regexp = re.compile(r"^(?P<key>\s*%s)\s*=\s*(?P<val>\[(.|\n)*?\])\s*$(?=\n^(\w+\s*=.*|\s*)$)" % key, re.M)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the last |?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't \s also match \n in multiline mode?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last | in the lookahead assertion is there to check that the next line is either a parameter definition or a blank line (or the end of the file, see last commit).

Where is it relevant that \s also matches \n?

res = regexp.search(ectxt)
if res:
fval = [x for x in val if x != ''] # filter out empty strings
Expand Down
24 changes: 23 additions & 1 deletion test/framework/tweak.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
from test.framework.utilities import EnhancedTestCase, TestLoaderFiltered
from unittest import TextTestRunner

from easybuild.framework.easyconfig.tweak import find_matching_easyconfigs, obtain_ec_for, pick_version
from easybuild.framework.easyconfig.parser import EasyConfigParser
from easybuild.framework.easyconfig.tweak import find_matching_easyconfigs, obtain_ec_for, pick_version, tweak_one


class TweakTest(EnhancedTestCase):
Expand Down Expand Up @@ -109,6 +110,27 @@ def test_obtain_ec_for(self):
self.assertTrue(generated)
self.assertEqual(os.path.basename(ec_file), 'GCC-5.4.3.eb')

def test_tweak_one_version(self):
"""Test tweak_one function"""
test_easyconfigs_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs')
toy_ec = os.path.join(test_easyconfigs_path, 't', 'toy', 'toy-0.0.eb')

# test tweaking of software version (--try-software-version)
tweaked_toy_ec = os.path.join(self.test_prefix, 'toy-tweaked.eb')
tweak_one(toy_ec, tweaked_toy_ec, {'version': '1.2.3'})

toy_ec_parsed = EasyConfigParser(toy_ec).get_config_dict()
tweaked_toy_ec_parsed = EasyConfigParser(tweaked_toy_ec).get_config_dict()

# checksums should be reset to empty list, only version should be changed, nothing else
self.assertEqual(tweaked_toy_ec_parsed['checksums'], [])
self.assertEqual(tweaked_toy_ec_parsed['version'], '1.2.3')
for key in [k for k in toy_ec_parsed.keys() if k not in ['checksums', 'version']]:
val = toy_ec_parsed[key]
self.assertTrue(key in tweaked_toy_ec_parsed, "Parameter '%s' not defined in tweaked easyconfig file" % key)
tweaked_val = tweaked_toy_ec_parsed.get(key)
self.assertEqual(val, tweaked_val, "Different value for %s parameter: %s vs %s" % (key, val, tweaked_val))


def suite():
""" return all the tests in this file """
Expand Down