From 9ebe6c6b5a99365f839d856291ee9000c95fbc5e Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 8 Oct 2025 14:33:19 +0200 Subject: [PATCH 1/9] Use chain.from_iterable --- easybuild/framework/easyblock.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index c6fade8006..209b2b3ed3 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -594,7 +594,7 @@ def fetch_patches(self, patch_specs=None, extension=False, checksums=None): if not isinstance(patch_specs, tuple) or len(patch_specs) != 2: raise EasyBuildError('Patch specs must be a tuple of (patches, post-install patches) or a list') post_install_patches = patch_specs[1] - patch_specs = itertools.chain(*patch_specs) + patch_specs = itertools.chain.from_iterable(patch_specs) patches = [] for index, patch_spec in enumerate(patch_specs): @@ -796,7 +796,7 @@ def collect_exts_file_info(self, fetch_files=True, verify_checksums=True): if fetch_files: ext_patches = self.fetch_patches(patch_specs=ext_patch_specs, extension=True) else: - ext_patches = [create_patch_info(p) for p in itertools.chain(*ext_patch_specs)] + ext_patches = [create_patch_info(p) for p in itertools.chain.from_iterable(ext_patch_specs)] if ext_patches: self.log.debug('Found patches for extension %s: %s', ext_name, ext_patches) From ad714a0238f9537ee797a93d7a54a190a877754c Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 8 Oct 2025 16:13:53 +0200 Subject: [PATCH 2/9] Use template-disable decorator instead of repeated `get_ref` --- easybuild/framework/easyblock.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 209b2b3ed3..0f1c835a96 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -2765,10 +2765,11 @@ def check_checksums_for(self, ent, sub='', source_cnt=None): checksums = ent.get('checksums', []) except EasyBuildError: if isinstance(ent, EasyConfig): - sources = ent.get_ref('sources') - data_sources = ent.get_ref('data_sources') - patches = ent.get_ref('patches') + ent.get_ref('postinstallpatches') - checksums = ent.get_ref('checksums') + with ent.disable_templating(): + sources = ent['sources'] + data_sources = ent['data_sources'] + patches = ent['patches'] + ent['postinstallpatches'] + checksums = ent['checksums'] # Single source should be re-wrapped as a list, and checksums with it if isinstance(sources, dict): From 6d41e373f73441436efe0239f0c7f3b9864d3256 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 8 Oct 2025 12:16:18 +0200 Subject: [PATCH 3/9] Fix `check_checksums` to handle patches specified as dicts In `sources` the keyname is "filename" while in `patches` it is "name". --- easybuild/framework/easyblock.py | 35 +++++++++++++++---------- test/framework/easyblock.py | 45 +++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 0f1c835a96..4db60a39ec 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -43,8 +43,10 @@ * Jan Andre Reuter (Juelich Supercomputing Centre) * Jasper Grimm (UoY) * Alex Domingo (Vrije Universiteit Brussel) +* Alexander Grund (TU Dresden) """ import concurrent +import contextlib import copy import functools import glob @@ -2779,25 +2781,30 @@ def check_checksums_for(self, ent, sub='', source_cnt=None): if isinstance(checksums, str): checksums = [checksums] - sources = sources + data_sources + def get_name(fn, key): + # if the filename is a tuple, the actual source file name is the first element + if isinstance(fn, tuple): + fn = fn[0] + # if the filename is a dict, the actual source file name is inside + if isinstance(fn, dict): + fn = fn[key] + return fn - if not checksums: + sources = [get_name(src, 'filename') for src in itertools.chain(sources, data_sources)] + patches = [get_name(patch, 'name') for patch in patches] + + if source_cnt is None: + source_cnt = len(sources) + patch_cnt = len(patches) + + if not checksums and (source_cnt + patch_cnt) > 0: checksums_from_json = self.get_checksums_from_json() # recreate a list of checksums. If each filename is found, the generated list of checksums should match # what is expected in list format - for fn in sources + patches: - # if the filename is a tuple, the actual source file name is the first element - if isinstance(fn, tuple): - fn = fn[0] - # if the filename is a dict, the actual source file name is the "filename" element - if isinstance(fn, dict): - fn = fn["filename"] - if fn in checksums_from_json.keys(): - checksums += [checksums_from_json[fn]] + with contextlib.suppress(KeyError): + checksums.extend(checksums_from_json[fn] for fn in sources + patches) - if source_cnt is None: - source_cnt = len(sources) - patch_cnt, checksum_cnt = len(patches), len(checksums) + checksum_cnt = len(checksums) if (source_cnt + patch_cnt) != checksum_cnt: if sub: diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index 601b21b7f8..cf8a058cbc 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -3427,9 +3427,52 @@ def run_checks(): eb.json_checksums = None self.assertEqual(eb.check_checksums(), []) + self.contents = textwrap.dedent(""" + easyblock = "ConfigureMake" + name = "Uniq_1" + version = "3" + homepage = "http://example.com" + description = "test" + toolchain = SYSTEM + # Different ways of specifying sources, patches, template usages to make sure they are resolved correctly + exts_list = [ + 'ulimit', # extension that is part of "standard library" + ('ext1', '0.0'), # Default source filename + ('ext2', '1.2', { + 'source_tmpl': "%(name)s.zip", + 'patches': ['%(name)s.patch'], + }), + ('ext3', '1.2', { + 'sources': "%(name)s.zip", + 'postinstallpatches': ['%(name)s.patch'], + }), + ('ext-%(namelower)s', version + '.14', { + 'sources': {'filename': '%(name)s-%(version)s.zip', 'download_filename': 'foo.tar'}, + 'patches': [{'name': '%(name)s.patch'}], + }), + ('ext-ok1', version, { + 'checksums': '44332000aa33b99ad1e00cbd1a7da769220d74647060a10e807b916d73ea27bc' + }), + ('ext-ok2', version, { + 'data_sources': {'filename': '%(name)s-%(version)s.zip', 'download_filename': 'bar.tar'}, + 'checksums': '44332000aa33b99ad1e00cbd1a7da769220d74647060a10e807b916d73ea27bc' + }), + ('ext-ok3', version, { + 'nosource': True + }), + ] + """) + self.writeEC() + eb = EasyBlock(EasyConfig(self.eb_file)) + res = eb.check_checksums() + self.assertEqual(len(res), 4) + extensions = ['ext1', 'ext2', 'ext3', 'ext-uniq_1'] + for ext, line in zip(extensions, res): + self.assertIn(ext_error_tmpl % ext, line) + # more checks for check_checksums_for method, which also takes regular dict as input self.assertEqual(eb.check_checksums_for({}), []) - expected = "Checksums missing for one or more sources/patches in test.eb: " + expected = f"Checksums missing for one or more sources/patches in {os.path.basename(self.eb_file)}: " expected += "found 1 sources + 0 patches vs 0 checksums" self.assertEqual(eb.check_checksums_for({'sources': ['test.tar.gz']}), [expected]) From 2398273f4041bee76b1887022a8da6a2d3c90876 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 8 Oct 2025 10:22:36 +0200 Subject: [PATCH 4/9] Add test for `check_checksums` using template in extension --- test/framework/easyblock.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index cf8a058cbc..a0501bd76b 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -3333,6 +3333,8 @@ def run_checks(): self.assertEqual(res[0], expected) self.assertTrue(res[1].startswith("Non-SHA256 checksum(s) found for toy-0.0.tar.gz:")) + ext_error_tmpl = "Checksums missing for one or more sources/patches of extension %s in " + # check for main sources/patches should reveal two issues with checksums res = eb.check_checksums_for(eb.cfg) self.assertEqual(len(res), 2) @@ -3343,11 +3345,8 @@ def run_checks(): self.assertEqual(len(res), 4) run_checks() - idx = 2 - for ext in ['bar', 'barbar']: - expected = "Checksums missing for one or more sources/patches of extension %s in " % ext - self.assertTrue(res[idx].startswith(expected)) - idx += 1 + for ext, line in zip(('bar', 'barbar'), res[2:]): + self.assertIn(ext_error_tmpl % ext, line) # check whether tuple of alternative SHA256 checksums is correctly recognized toy_ec = os.path.join(testdir, 'easyconfigs', 'test_ecs', 't', 'toy', 'toy-0.0.eb') @@ -3410,6 +3409,24 @@ def run_checks(): )] self.assertEqual(eb.check_checksums(), []) + self.contents = textwrap.dedent(""" + easyblock = "ConfigureMake" + name = "Uniq_1" + version = "3.14" + homepage = "http://example.com" + description = "test" + toolchain = SYSTEM + # Templates of parent used in extensions + exts_list = [ + ('%(namelower)s', version), + ] + """) + self.writeEC() + eb = EasyBlock(EasyConfig(self.eb_file)) + res = eb.check_checksums() + self.assertEqual(len(res), 1) + self.assertIn(ext_error_tmpl % 'uniq_1', res[0]) + # no checksums in easyconfig, then picked up from checksums.json next to easyconfig file test_ec = os.path.join(self.test_prefix, 'test.eb') copy_file(toy_ec, test_ec) @@ -3422,7 +3439,7 @@ def run_checks(): expected += "found 1 sources + 2 patches vs 0 checksums" self.assertEqual(res[0], expected) - # all is fine is checksums.json is also copied + # all is fine if checksums.json is also copied copy_file(os.path.join(os.path.dirname(toy_ec), 'checksums.json'), self.test_prefix) eb.json_checksums = None self.assertEqual(eb.check_checksums(), []) From c68e1402b53b66dec2607069930e6d0930202463 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 8 Oct 2025 10:23:10 +0200 Subject: [PATCH 5/9] Revert "don't require that all templates can be resolved for 'exts_list' easyconfig parameter value in EasyBlock.check_checksums" This reverts commit 7112e406dc8ee75fd3d5257648d23d801d77e813. --- easybuild/framework/easyblock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 4db60a39ec..927d250a53 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -2860,7 +2860,7 @@ def check_checksums(self): checksum_issues.extend(self.check_checksums_for(self.cfg)) # also check checksums for extensions - for ext in self.cfg.get_ref('exts_list'): + for ext in self.cfg['exts_list']: # just skip extensions for which only a name is specified # those are just there to check for things that are in the "standard library" if not isinstance(ext, str): From 3d45657e595a9d5c965f2a4d68e8e61e8735304c Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 8 Oct 2025 10:28:53 +0200 Subject: [PATCH 6/9] Fix `check_checksums` when using templates in extensions --- easybuild/framework/easyblock.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 927d250a53..386e4d5203 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -2860,7 +2860,9 @@ def check_checksums(self): checksum_issues.extend(self.check_checksums_for(self.cfg)) # also check checksums for extensions - for ext in self.cfg['exts_list']: + with self.cfg.allow_unresolved_templates(): + exts_list = self.cfg['exts_list'] + for ext in exts_list: # just skip extensions for which only a name is specified # those are just there to check for things that are in the "standard library" if not isinstance(ext, str): From d77a88947731eaae1bca932db5decdb305abe305 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 8 Oct 2025 13:36:43 +0200 Subject: [PATCH 7/9] Fix `check_checksums` when checksums are specified in JSON file This requires correctly resolving the templates in `exts_list` sources/patches to be able to fetch them from the JSON file. --- easybuild/framework/easyblock.py | 16 +++------------- test/framework/easyblock.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 386e4d5203..aa5451264b 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -2860,19 +2860,9 @@ def check_checksums(self): checksum_issues.extend(self.check_checksums_for(self.cfg)) # also check checksums for extensions - with self.cfg.allow_unresolved_templates(): - exts_list = self.cfg['exts_list'] - for ext in exts_list: - # just skip extensions for which only a name is specified - # those are just there to check for things that are in the "standard library" - if not isinstance(ext, str): - ext_name = ext[0] - # take into account that extension may be a 2-tuple with just name/version - ext_opts = ext[2] if len(ext) == 3 else {} - # only a single source per extension is supported (see source_tmpl) - source_cnt = 1 if not ext_opts.get('nosource') else 0 - res = self.check_checksums_for(ext_opts, sub="of extension %s" % ext_name, source_cnt=source_cnt) - checksum_issues.extend(res) + for ext in self.collect_exts_file_info(fetch_files=False, verify_checksums=False): + res = self.check_checksums_for(ext, sub=f"of extension {ext['name']}") + checksum_issues.extend(res) return checksum_issues diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index a0501bd76b..820634aa72 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -29,8 +29,10 @@ @author: Kenneth Hoste (Ghent University) @author: Maxime Boissonneault (Compute Canada) @author: Jan Andre Reuter (Juelich Supercomputing Centre) +@author: Alexander Grund (TU Dresden) """ import fileinput +import itertools import os import re import shutil @@ -3341,6 +3343,7 @@ def run_checks(): run_checks() # full check also catches checksum issues with extensions + eb.json_checksums = {} # Avoid picking up checksums from JSON file res = eb.check_checksums() self.assertEqual(len(res), 4) run_checks() @@ -3477,6 +3480,12 @@ def run_checks(): ('ext-ok3', version, { 'nosource': True }), + ('ext-ok1', version, { + 'checksums': ['44332000aa33b99ad1e00cbd1a7da769220d74647060a10e807b916d73ea27bc'] + }), + ('ext-ok2', version, { + 'nosource': True + }), ] """) self.writeEC() @@ -3487,6 +3496,27 @@ def run_checks(): for ext, line in zip(extensions, res): self.assertIn(ext_error_tmpl % ext, line) + # Gradually add checksums to JSON dict and test that the associated extension checksums are now fine + sha256_cs = '81a3accc894592152f81814fbf133d39afad52885ab52c25018722c7bda92487' # Valid format only + eb.json_checksums = {'ext1-0.0.tar.gz': sha256_cs} + for ext, line in itertools.zip_longest(extensions[1:], eb.check_checksums(), fillvalue=''): + self.assertIn(ext_error_tmpl % ext, line) + eb.json_checksums['ext2.zip'] = sha256_cs + for ext, line in itertools.zip_longest(extensions[1:], eb.check_checksums(), fillvalue=''): + self.assertIn(ext_error_tmpl % ext, line) + eb.json_checksums['ext2.patch'] = sha256_cs + for ext, line in itertools.zip_longest(extensions[2:], eb.check_checksums(), fillvalue=''): + self.assertIn(ext_error_tmpl % ext, line) + eb.json_checksums['ext3.zip'] = sha256_cs + for ext, line in itertools.zip_longest(extensions[2:], eb.check_checksums(), fillvalue=''): + self.assertIn(ext_error_tmpl % ext, line) + eb.json_checksums['ext3.patch'] = sha256_cs + for ext, line in itertools.zip_longest(extensions[3:], eb.check_checksums(), fillvalue=''): + self.assertIn(ext_error_tmpl % ext, line) + eb.json_checksums['ext-uniq_1-3.14.zip'] = sha256_cs + eb.json_checksums['ext-uniq_1.patch'] = sha256_cs + self.assertEqual(eb.check_checksums(), []) + # more checks for check_checksums_for method, which also takes regular dict as input self.assertEqual(eb.check_checksums_for({}), []) expected = f"Checksums missing for one or more sources/patches in {os.path.basename(self.eb_file)}: " From 344803f9cb5e049a833144dd2b284e7f92e61107 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 8 Oct 2025 14:32:49 +0200 Subject: [PATCH 8/9] Store checksums in extension_info --- easybuild/framework/easyblock.py | 1 + test/framework/easyblock.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index aa5451264b..e506de4cf3 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -686,6 +686,7 @@ def collect_exts_file_info(self, fetch_files=True, verify_checksums=True): source_urls = resolve_template(ext_options.get('source_urls', []), template_values) checksums = resolve_template(ext_options.get('checksums', []), template_values) + ext_src['checksums'] = checksums download_instructions = resolve_template(ext_options.get('download_instructions'), template_values) diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index 820634aa72..bd0796dd92 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -2368,14 +2368,17 @@ def test_collect_exts_file_info(self): bar_patch2 = 'bar-0.0_fix-very-silly-typo-in-printf-statement.patch' self.assertEqual(exts_file_info[1]['patches'][1]['name'], bar_patch2) self.assertEqual(exts_file_info[1]['patches'][1]['path'], os.path.join(toy_ext_sources, bar_patch2)) + self.assertEqual(len(exts_file_info[1]['checksums']), 1) self.assertEqual(exts_file_info[2]['name'], 'barbar') self.assertEqual(exts_file_info[2]['src'], os.path.join(toy_ext_sources, 'barbar-1.2.tar.gz')) self.assertNotIn('patches', exts_file_info[2]) + self.assertEqual(len(exts_file_info[2]['checksums']), 0) self.assertEqual(exts_file_info[3]['name'], 'toy') self.assertEqual(exts_file_info[3]['src'], os.path.join(toy_sources, 'toy-0.0.tar.gz')) self.assertNotIn('patches', exts_file_info[3]) + self.assertEqual(len(exts_file_info[3]['checksums']), 0) # location of files is missing when fetch_files is set to False exts_file_info = toy_eb.collect_exts_file_info(fetch_files=False, verify_checksums=False) From eef8d6a3f231d079620deb475edd9cb2546038f1 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 5 Aug 2022 12:40:19 +0200 Subject: [PATCH 9/9] Include 'sources' key to entries in list returned by `collect_exts_file_info` The returned dict per extension has a 'patches' key but no 'sources'. Add this incoorporating `source_tmpl` or the default value. Add test for that and also for `nosource: True` and `sources` being a list. --- easybuild/framework/easyblock.py | 6 ++++ test/framework/easyblock.py | 47 ++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index e506de4cf3..96720fe2ab 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -729,6 +729,11 @@ def collect_exts_file_info(self, fetch_files=True, verify_checksums=True): # copy 'path' entry to 'src' for use with extensions 'src': src['path'], }) + filename = src['name'] + else: + filename = source.get('filename') + if filename is not None: + ext_src['sources'] = [filename] else: @@ -746,6 +751,7 @@ def collect_exts_file_info(self, fetch_files=True, verify_checksums=True): raise EasyBuildError(error_msg, type(src_fn).__name__, src_fn) src_fn = resolve_template(src_fn, template_values) + ext_src['sources'] = [src_fn] if fetch_files: src_path = self.obtain_file(src_fn, extension=True, urls=source_urls, diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index bd0796dd92..cdbba9056f 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -2350,17 +2350,25 @@ def test_collect_exts_file_info(self): toy_sources = os.path.join(testdir, 'sandbox', 'sources', 'toy') toy_ext_sources = os.path.join(toy_sources, 'extensions') toy_ec_file = os.path.join(testdir, 'easyconfigs', 'test_ecs', 't', 'toy', 'toy-0.0-gompi-2018a-test.eb') - toy_ec = process_easyconfig(toy_ec_file)[0] + + test_ec = os.path.join(self.test_prefix, 'test.eb') + new_ext_txt = "('baz', '0.0', {'nosource': True})," # With nosource option + new_ext_txt += "('barbar', '0.0', {'sources': [SOURCE_TAR_GZ]})," # With sources containing a list + test_ectxt = re.sub(r'\(name, version', new_ext_txt+r"\g<0>", read_file(toy_ec_file)) + write_file(test_ec, test_ectxt) + + toy_ec = process_easyconfig(test_ec)[0] toy_eb = EasyBlock(toy_ec['ec']) exts_file_info = toy_eb.collect_exts_file_info() self.assertIsInstance(exts_file_info, list) - self.assertEqual(len(exts_file_info), 4) + self.assertEqual(len(exts_file_info), 6) self.assertEqual(exts_file_info[0], {'name': 'ulimit'}) self.assertEqual(exts_file_info[1]['name'], 'bar') + self.assertEqual(exts_file_info[1]['sources'], ['bar-0.0.tar.gz']) self.assertEqual(exts_file_info[1]['src'], os.path.join(toy_ext_sources, 'bar-0.0.tar.gz')) bar_patch1 = 'bar-0.0_fix-silly-typo-in-printf-statement.patch' self.assertEqual(exts_file_info[1]['patches'][0]['name'], bar_patch1) @@ -2371,24 +2379,38 @@ def test_collect_exts_file_info(self): self.assertEqual(len(exts_file_info[1]['checksums']), 1) self.assertEqual(exts_file_info[2]['name'], 'barbar') + self.assertEqual(exts_file_info[2]['sources'], ['barbar-1.2.tar.gz']) self.assertEqual(exts_file_info[2]['src'], os.path.join(toy_ext_sources, 'barbar-1.2.tar.gz')) self.assertNotIn('patches', exts_file_info[2]) self.assertEqual(len(exts_file_info[2]['checksums']), 0) - self.assertEqual(exts_file_info[3]['name'], 'toy') - self.assertEqual(exts_file_info[3]['src'], os.path.join(toy_sources, 'toy-0.0.tar.gz')) + self.assertEqual(exts_file_info[3]['name'], 'baz') + self.assertNotIn('sources', exts_file_info[3]) + self.assertNotIn('sources', exts_file_info[3]['options']) + self.assertNotIn('src', exts_file_info[3]) self.assertNotIn('patches', exts_file_info[3]) self.assertEqual(len(exts_file_info[3]['checksums']), 0) + self.assertEqual(exts_file_info[4]['name'], 'barbar') + self.assertEqual(exts_file_info[4]['sources'], ['barbar-0.0.tar.gz']) + self.assertEqual(exts_file_info[4]['src'], os.path.join(toy_ext_sources, 'barbar-0.0.tar.gz')) + self.assertNotIn('patches', exts_file_info[4]) + + self.assertEqual(exts_file_info[5]['name'], 'toy') + self.assertEqual(exts_file_info[5]['sources'], ['toy-0.0.tar.gz']) + self.assertEqual(exts_file_info[5]['src'], os.path.join(toy_sources, 'toy-0.0.tar.gz')) + self.assertNotIn('patches', exts_file_info[5]) + # location of files is missing when fetch_files is set to False exts_file_info = toy_eb.collect_exts_file_info(fetch_files=False, verify_checksums=False) self.assertIsInstance(exts_file_info, list) - self.assertEqual(len(exts_file_info), 4) + self.assertEqual(len(exts_file_info), 6) self.assertEqual(exts_file_info[0], {'name': 'ulimit'}) self.assertEqual(exts_file_info[1]['name'], 'bar') + self.assertEqual(exts_file_info[1]['sources'], ['bar-0.0.tar.gz']) self.assertNotIn('src', exts_file_info[1]) self.assertEqual(exts_file_info[1]['patches'][0]['name'], bar_patch1) self.assertNotIn('path', exts_file_info[1]['patches'][0]) @@ -2396,13 +2418,26 @@ def test_collect_exts_file_info(self): self.assertNotIn('path', exts_file_info[1]['patches'][1]) self.assertEqual(exts_file_info[2]['name'], 'barbar') + self.assertEqual(exts_file_info[2]['sources'], ['barbar-1.2.tar.gz']) self.assertNotIn('src', exts_file_info[2]) self.assertNotIn('patches', exts_file_info[2]) - self.assertEqual(exts_file_info[3]['name'], 'toy') + self.assertEqual(exts_file_info[3]['name'], 'baz') + self.assertNotIn('sources', exts_file_info[3]) + self.assertNotIn('sources', exts_file_info[3]['options']) self.assertNotIn('src', exts_file_info[3]) self.assertNotIn('patches', exts_file_info[3]) + self.assertEqual(exts_file_info[4]['name'], 'barbar') + self.assertEqual(exts_file_info[4]['sources'], ['barbar-0.0.tar.gz']) + self.assertNotIn('src', exts_file_info[4]) + self.assertNotIn('patches', exts_file_info[4]) + + self.assertEqual(exts_file_info[5]['name'], 'toy') + self.assertEqual(exts_file_info[5]['sources'], ['toy-0.0.tar.gz']) + self.assertNotIn('src', exts_file_info[5]) + self.assertNotIn('patches', exts_file_info[5]) + error_msg = "Can't verify checksums for extension files if they are not being fetched" self.assertErrorRegex(EasyBuildError, error_msg, toy_eb.collect_exts_file_info, fetch_files=False)