Skip to content

Commit d18b6f0

Browse files
authored
Merge pull request #3916 from easybuilders/4.5.x
release EasyBuild v4.5.1
2 parents abf0c8c + 9ea450b commit d18b6f0

File tree

15 files changed

+418
-82
lines changed

15 files changed

+418
-82
lines changed

RELEASE_NOTES

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@ For more detailed information, please see the git log.
44
These release notes can also be consulted at https://easybuild.readthedocs.io/en/latest/Release_notes.html.
55

66

7+
v4.5.1 (December 13th 2021)
8+
---------------------------
9+
10+
update/bugfix release
11+
12+
- various enhancements, including:
13+
- also dump environment to reprod directory (#3374)
14+
- determine which extensions can be skipped in parallel (if --parallel-extensions-install is enabled) (#3890)
15+
- fall back to sequential installation for extensions with unknown dependencies when using --parallel-extensions-install (#3906)
16+
- allow oversubscription in sanity check for OpenMPI-based toolchains (#3909)
17+
- various bug fixes, including:
18+
- don't try to ensure absolute path for path part of repositorypath (#3893, #3899)
19+
- fix typo in EULA agreement error message (#3894)
20+
- only remove lock if it was created in the same EasyBuild session (not if it existed already) (#3889)
21+
- introduce EasyBlock.post_init method to correctly define builddir variable when build-in-installdir mode is enabled in easyconfig or easyblock (#3900)
22+
- also show download progress bar when using --inject-checksums (#3905)
23+
- pick up custom extract_cmd specified for extension (#3907)
24+
- make test_run_cmd_async more robust against fluke failures (#3908)
25+
26+
727
v4.5.0 (October 29th 2021)
828
--------------------------
929

easybuild/framework/easyblock.py

Lines changed: 141 additions & 24 deletions
Large diffs are not rendered by default.

easybuild/framework/easyconfig/tools.py

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,45 @@ def review_pr(paths=None, pr=None, colored=True, branch='develop', testing=False
557557
return '\n'.join(lines)
558558

559559

560+
def dump_env_easyblock(app, orig_env=None, ec_path=None, script_path=None, silent=False):
561+
if orig_env is None:
562+
orig_env = copy.deepcopy(os.environ)
563+
if ec_path is None:
564+
raise EasyBuildError("The path to the easyconfig relevant to this environment dump is required")
565+
if script_path is None:
566+
# Assume we are placing it alongside the easyconfig path
567+
script_path = '%s.env' % os.path.splitext(ec_path)[0]
568+
# Compose script
569+
ecfile = os.path.basename(ec_path)
570+
script_lines = [
571+
"#!/bin/bash",
572+
"# script to set up build environment as defined by EasyBuild v%s for %s" % (EASYBUILD_VERSION, ecfile),
573+
"# usage: source %s" % os.path.basename(script_path),
574+
]
575+
576+
script_lines.extend(['', "# toolchain & dependency modules"])
577+
if app.toolchain.modules:
578+
script_lines.extend(["module load %s" % mod for mod in app.toolchain.modules])
579+
else:
580+
script_lines.append("# (no modules loaded)")
581+
582+
script_lines.extend(['', "# build environment"])
583+
if app.toolchain.vars:
584+
env_vars = sorted(app.toolchain.vars.items())
585+
script_lines.extend(["export %s='%s'" % (var, val.replace("'", "\\'")) for (var, val) in env_vars])
586+
else:
587+
script_lines.append("# (no build environment defined)")
588+
589+
write_file(script_path, '\n'.join(script_lines))
590+
msg = "Script to set up build environment for %s dumped to %s" % (ecfile, script_path)
591+
if silent:
592+
_log.info(msg)
593+
else:
594+
print_msg(msg, prefix=False)
595+
596+
restore_env(orig_env)
597+
598+
560599
def dump_env_script(easyconfigs):
561600
"""
562601
Dump source scripts that set up build environment for specified easyconfigs.
@@ -591,31 +630,8 @@ def dump_env_script(easyconfigs):
591630
app.check_readiness_step()
592631
app.prepare_step(start_dir=False)
593632

594-
# compose script
595-
ecfile = os.path.basename(ec.path)
596-
script_lines = [
597-
"#!/bin/bash",
598-
"# script to set up build environment as defined by EasyBuild v%s for %s" % (EASYBUILD_VERSION, ecfile),
599-
"# usage: source %s" % os.path.basename(script_path),
600-
]
601-
602-
script_lines.extend(['', "# toolchain & dependency modules"])
603-
if app.toolchain.modules:
604-
script_lines.extend(["module load %s" % mod for mod in app.toolchain.modules])
605-
else:
606-
script_lines.append("# (no modules loaded)")
607-
608-
script_lines.extend(['', "# build environment"])
609-
if app.toolchain.vars:
610-
env_vars = sorted(app.toolchain.vars.items())
611-
script_lines.extend(["export %s='%s'" % (var, val.replace("'", "\\'")) for (var, val) in env_vars])
612-
else:
613-
script_lines.append("# (no build environment defined)")
614-
615-
write_file(script_path, '\n'.join(script_lines))
616-
print_msg("Script to set up build environment for %s dumped to %s" % (ecfile, script_path), prefix=False)
617-
618-
restore_env(orig_env)
633+
# create the environment dump
634+
dump_env_easyblock(app, orig_env=orig_env, ec_path=ec.path, script_path=script_path)
619635

620636

621637
def categorize_files_by_type(paths):

easybuild/framework/extension.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def __init__(self, mself, ext, extra_params=None):
119119

120120
# list of source/patch files: we use an empty list as default value like in EasyBlock
121121
self.src = resolve_template(self.ext.get('src', []), self.cfg.template_values)
122+
self.src_extract_cmd = self.ext.get('extract_cmd', None)
122123
self.patches = resolve_template(self.ext.get('patches', []), self.cfg.template_values)
123124
self.options = resolve_template(copy.deepcopy(self.ext.get('options', {})), self.cfg.template_values)
124125

@@ -225,7 +226,8 @@ def async_cmd_check(self):
225226
@property
226227
def required_deps(self):
227228
"""Return list of required dependencies for this extension."""
228-
raise NotImplementedError("Don't know how to determine required dependencies for extension '%s'" % self.name)
229+
self.log.info("Don't know how to determine required dependencies for extension '%s'", self.name)
230+
return None
229231

230232
@property
231233
def toolchain(self):

easybuild/framework/extensioneasyblock.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def run(self, unpack_src=False):
118118
if unpack_src:
119119
targetdir = os.path.join(self.master.builddir, remove_unwanted_chars(self.name))
120120
self.ext_dir = extract_file(self.src, targetdir, extra_options=self.unpack_options,
121-
change_into_dir=False)
121+
change_into_dir=False, cmd=self.src_extract_cmd)
122122

123123
# setting start dir must be done from unpacked source directory for extension,
124124
# because start_dir value is usually a relative path (if it is set)

easybuild/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,8 @@ def main(args=None, logfile=None, do_build=None, testing=False, modtool=None):
531531
dump_env_script(easyconfigs)
532532

533533
elif options.inject_checksums:
534-
inject_checksums(ordered_ecs, options.inject_checksums)
534+
with rich_live_cm():
535+
inject_checksums(ordered_ecs, options.inject_checksums)
535536

536537
# cleanup and exit after dry run, searching easyconfigs or submitting regression test
537538
stop_options = [options.check_conflicts, dry_run_mode, options.dump_env_script, options.inject_checksums]

easybuild/tools/filetools.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -456,11 +456,14 @@ def extract_file(fn, dest, cmd=None, extra_options=None, overwrite=False, forced
456456
_log.debug("Unpacking %s in directory %s", fn, abs_dest)
457457
cwd = change_dir(abs_dest)
458458

459-
if not cmd:
460-
cmd = extract_cmd(fn, overwrite=overwrite)
461-
else:
459+
if cmd:
462460
# complete command template with filename
463461
cmd = cmd % fn
462+
_log.debug("Using specified command to unpack %s: %s", fn, cmd)
463+
else:
464+
cmd = extract_cmd(fn, overwrite=overwrite)
465+
_log.debug("Using command derived from file extension to unpack %s: %s", fn, cmd)
466+
464467
if not cmd:
465468
raise EasyBuildError("Can't extract file %s with unknown filetype", fn)
466469

@@ -1366,7 +1369,7 @@ def find_extension(filename):
13661369
if res:
13671370
ext = res.group('ext')
13681371
else:
1369-
raise EasyBuildError('Unknown file type for file %s', filename)
1372+
raise EasyBuildError("%s has unknown file extension", filename)
13701373

13711374
return ext
13721375

@@ -1379,7 +1382,9 @@ def extract_cmd(filepath, overwrite=False):
13791382
ext = find_extension(filename)
13801383
target = filename[:-len(ext)]
13811384

1385+
# find_extension will either return an extension listed in EXTRACT_CMDS, or raise an error
13821386
cmd_tmpl = EXTRACT_CMDS[ext.lower()]
1387+
13831388
if overwrite:
13841389
if 'unzip -qq' in cmd_tmpl:
13851390
cmd_tmpl = cmd_tmpl.replace('unzip -qq', 'unzip -qq -o')

easybuild/tools/options.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,7 @@ def _postprocess_checks(self):
10671067

10681068
def get_cfg_opt_abs_path(self, opt_name, path):
10691069
"""Get path value of configuration option as absolute path."""
1070-
if os.path.isabs(path):
1070+
if os.path.isabs(path) or path.startswith('git@'):
10711071
abs_path = path
10721072
else:
10731073
abs_path = os.path.abspath(path)
@@ -1092,22 +1092,20 @@ def _ensure_abs_path(self, opt_name):
10921092
def _postprocess_config(self):
10931093
"""Postprocessing of configuration options"""
10941094

1095-
# resolve relative paths for configuration options that specify a location;
1095+
# resolve relative paths for configuration options that specify a location,
1096+
# to avoid incorrect paths being used when EasyBuild changes the current working directory
1097+
# (see https://github.com/easybuilders/easybuild-framework/issues/3619);
10961098
# ensuring absolute paths for 'robot' is handled separately below,
1097-
# because we need to be careful with the argument pass to --robot
1099+
# because we need to be careful with the argument pass to --robot;
1100+
# note: repositorypath is purposely not listed here, because it's a special case:
1101+
# - the value could consist of a 2-tuple (<path>, <relative_subdir>);
1102+
# - the <path> could also specify the location of a *remote* (Git( repository,
1103+
# which can be done in variety of formats (git@<url>:<org>/<repo>), https://<url>, etc.)
1104+
# (see also https://github.com/easybuilders/easybuild-framework/issues/3892);
10981105
path_opt_names = ['buildpath', 'containerpath', 'git_working_dirs_path', 'installpath',
10991106
'installpath_modules', 'installpath_software', 'prefix', 'packagepath',
11001107
'robot_paths', 'sourcepath']
11011108

1102-
# repositorypath is a special case: only first part is a path;
1103-
# 2nd (optional) part is a relative subdir and should not be resolved to an absolute path!
1104-
repositorypath = self.options.repositorypath
1105-
if isinstance(repositorypath, (list, tuple)) and len(repositorypath) == 2:
1106-
abs_path = self.get_cfg_opt_abs_path('repositorypath', repositorypath[0])
1107-
self.options.repositorypath = (abs_path, repositorypath[1])
1108-
else:
1109-
path_opt_names.append('repositorypath')
1110-
11111109
for opt_name in path_opt_names:
11121110
self._ensure_abs_path(opt_name)
11131111

easybuild/tools/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
# recent setuptools versions will *TRANSFORM* something like 'X.Y.Zdev' into 'X.Y.Z.dev0', with a warning like
4444
# UserWarning: Normalizing '2.4.0dev' to '2.4.0.dev0'
4545
# This causes problems further up the dependency chain...
46-
VERSION = LooseVersion('4.5.0')
46+
VERSION = LooseVersion('4.5.1')
4747
UNKNOWN = 'UNKNOWN'
4848

4949

test/framework/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ def test_generaloption_config_file(self):
302302
self.assertEqual(install_path('mod'), installpath_modules), # via config file
303303
self.assertEqual(source_paths(), [testpath2]) # via command line
304304
self.assertEqual(build_path(), testpath1) # via config file
305-
self.assertEqual(get_repositorypath(), (os.path.join(topdir, 'ebfiles_repo'), 'somesubdir')) # via config file
305+
self.assertEqual(get_repositorypath(), [os.path.join(topdir, 'ebfiles_repo'), 'somesubdir']) # via config file
306306

307307
# hardcoded first entry
308308
self.assertEqual(options.robot_paths[0], '/tmp/foo')

0 commit comments

Comments
 (0)