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
30 changes: 19 additions & 11 deletions easybuild/tools/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -1471,14 +1471,25 @@ def parse_external_modules_metadata(cfgs):
"""
Parse metadata for external modules.

:param cfgs: list of config files providing metadata for external modules
:param cfgs: list of (glob patterns for) paths to config files providing metadata for external modules
:return: parsed metadata for external modules
"""
if cfgs is None:
cfgs = []

# expand glob patterns, and report error for faulty paths
paths = []
for cfg in cfgs:
res = glob.glob(cfg)
if res:
paths.extend(res)
else:
# if there are no matches, we report an error to avoid silently ignores faulty paths
raise EasyBuildError("Specified path for file with external modules metadata does not exist: %s", cfg)
cfgs = paths

# use external modules metadata configuration files that are available by default, unless others are specified
if not cfgs:
cfgs = []

# we expect to find *external_modules_metadata.cfg files in etc/ on same level as easybuild/framework
topdirs = [os.path.dirname(os.path.dirname(os.path.dirname(__file__)))]

Expand All @@ -1502,14 +1513,11 @@ def parse_external_modules_metadata(cfgs):

parsed_metadata = ConfigObj()
for cfg in cfgs:
if os.path.isfile(cfg):
_log.debug("Parsing %s with external modules metadata", cfg)
try:
parsed_metadata.merge(ConfigObj(cfg))
except ConfigObjError as err:
raise EasyBuildError("Failed to parse %s with external modules metadata: %s", cfg, err)
else:
raise EasyBuildError("Specified path for file with external modules metadata does not exist: %s", cfg)
_log.debug("Parsing %s with external modules metadata", cfg)
try:
parsed_metadata.merge(ConfigObj(cfg))
except ConfigObjError as err:
raise EasyBuildError("Failed to parse %s with external modules metadata: %s", cfg, err)

# make sure name/version values are always lists, make sure they're equal length
for mod, entry in parsed_metadata.items():
Expand Down
27 changes: 27 additions & 0 deletions test/framework/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -3544,6 +3544,33 @@ def test_parse_external_modules_metadata(self):
err_msg = "Different length for lists of names/versions in metadata for external module"
self.assertErrorRegex(EasyBuildError, err_msg, parse_external_modules_metadata, [testcfg])

# if path to non-existing file is used, an error is reported
doesnotexist = os.path.join(self.test_prefix, 'doesnotexist')
error_pattern = "Specified path for file with external modules metadata does not exist"
self.assertErrorRegex(EasyBuildError, error_pattern, parse_external_modules_metadata, [doesnotexist])

# glob pattern can be used to specify file locations to parse_external_modules_metadata
cfg1 = os.path.join(self.test_prefix, 'cfg_one.ini')
write_file(cfg1, '\n'.join(['[one/1.0]', 'name = one', 'version = 1.0']))
cfg2 = os.path.join(self.test_prefix, 'cfg_two.ini')
write_file(cfg2, '\n'.join([
'[two/2.0]', 'name = two', 'version = 2.0',
'[two/2.1]', 'name = two', 'version = 2.1',
]))
cfg3 = os.path.join(self.test_prefix, 'cfg3.ini')
write_file(cfg3, '\n'.join(['[three/3.0]', 'name = three', 'version = 3.0']))
cfg4 = os.path.join(self.test_prefix, 'cfg_more.ini')
write_file(cfg4, '\n'.join(['[one/1.2.3]', 'name = one', 'version = 1.2.3', 'prefix = /one/1.2.3/']))

metadata = parse_external_modules_metadata([os.path.join(self.test_prefix, 'cfg*.ini')])

self.assertEqual(sorted(metadata.keys()), ['one/1.0', 'one/1.2.3', 'three/3.0', 'two/2.0', 'two/2.1'])
self.assertEqual(metadata['one/1.0'], {'name': ['one'], 'version': ['1.0']})
self.assertEqual(metadata['one/1.2.3'], {'name': ['one'], 'version': ['1.2.3'], 'prefix': '/one/1.2.3/'})
self.assertEqual(metadata['two/2.0'], {'name': ['two'], 'version': ['2.0']})
self.assertEqual(metadata['two/2.1'], {'name': ['two'], 'version': ['2.1']})
self.assertEqual(metadata['three/3.0'], {'name': ['three'], 'version': ['3.0']})

def test_zip_logs(self):
"""Test use of --zip-logs"""

Expand Down