diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index b0fc9ff51c..1e92e9fb5f 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -340,6 +340,7 @@ def post_init(self): # but needs to be correct if the build is performed in the installation directory self.log.info("Changing build dir to %s", self.installdir) self.builddir = self.installdir + self.set_parallel() # INIT/CLOSE LOG def _init_log(self): @@ -1978,7 +1979,7 @@ def skip_extensions_parallel(self, exts_filter): exts_cnt = len(self.ext_instances) cmds = [resolve_exts_filter_template(exts_filter, ext) for ext in self.ext_instances] - with ThreadPoolExecutor(max_workers=self.cfg['parallel']) as thread_pool: + with ThreadPoolExecutor(max_workers=self.cfg.parallel) as thread_pool: # list of command to run asynchronously async_cmds = [thread_pool.submit(run_shell_cmd, cmd, stdin=stdin, hidden=True, fail_on_error=False, @@ -2108,7 +2109,7 @@ def install_extensions_parallel(self, install=True): """ self.log.info("Installing extensions in parallel...") - thread_pool = ThreadPoolExecutor(max_workers=self.cfg['parallel']) + thread_pool = ThreadPoolExecutor(max_workers=self.cfg.parallel) running_exts = [] installed_ext_names = [] @@ -2170,7 +2171,7 @@ def update_exts_progress_bar_helper(running_exts, progress_size): for _ in range(max_iter): - if not (exts_queue and len(running_exts) < self.cfg['parallel']): + if not (exts_queue and len(running_exts) < self.cfg.parallel): break # check whether extension at top of the queue is ready to install @@ -2409,19 +2410,21 @@ def set_parallel(self): """Set 'parallel' easyconfig parameter to determine how many cores can/should be used for parallel builds.""" # set level of parallelism for build par = build_option('parallel') - cfg_par = self.cfg['parallel'] - if cfg_par is None: + if par is not None: self.log.debug("Desired parallelism specified via 'parallel' build option: %s", par) - elif par is None: - par = cfg_par - self.log.debug("Desired parallelism specified via 'parallel' easyconfig parameter: %s", par) - else: - par = min(int(par), int(cfg_par)) - self.log.debug("Desired parallelism: minimum of 'parallel' build option/easyconfig parameter: %s", par) - par = det_parallelism(par, maxpar=self.cfg['maxparallel']) + # Transitional only in case some easyblocks still set/change cfg['parallel'] + # Use _parallelLegacy to avoid deprecation warnings + cfg_par = self.cfg['_parallelLegacy'] + if cfg_par is not None: + if par is None: + par = cfg_par + else: + par = min(int(par), int(cfg_par)) + + par = det_parallelism(par, maxpar=self.cfg['max_parallel']) self.log.info("Setting parallelism: %s" % par) - self.cfg['parallel'] = par + self.cfg.parallel = par def remove_module_file(self): """Remove module file (if it exists), and check for ghost installation directory (and deal with it).""" @@ -2467,8 +2470,6 @@ def check_readiness_step(self): """ Verify if all is ok to start build. """ - self.set_parallel() - # check whether modules are loaded loadedmods = self.modules_tool.loaded_modules() if len(loadedmods) > 0: diff --git a/easybuild/framework/easyconfig/default.py b/easybuild/framework/easyconfig/default.py index bca46c3856..aaed4a6891 100644 --- a/easybuild/framework/easyconfig/default.py +++ b/easybuild/framework/easyconfig/default.py @@ -110,8 +110,6 @@ 'installopts': ['', 'Extra options for installation', BUILD], 'maxparallel': [16, 'Max degree of parallelism', BUILD], 'module_only': [False, 'Only generate module file', BUILD], - 'parallel': [None, ('Degree of parallelism for e.g. make (default: based on the number of ' - 'cores, active cpuset and restrictions in ulimit)'), BUILD], 'patches': [[], "List of patches to apply", BUILD], 'prebuildopts': ['', 'Extra options pre-passed to build command.', BUILD], 'preconfigopts': ['', 'Extra options pre-passed to configure.', BUILD], diff --git a/easybuild/framework/easyconfig/easyconfig.py b/easybuild/framework/easyconfig/easyconfig.py index fe3e3bd82c..560efb8a41 100644 --- a/easybuild/framework/easyconfig/easyconfig.py +++ b/easybuild/framework/easyconfig/easyconfig.py @@ -120,7 +120,18 @@ def handle_deprecated_or_replaced_easyconfig_parameters(ec_method): def new_ec_method(self, key, *args, **kwargs): """Check whether any replace easyconfig parameters are still used""" # map deprecated parameters to their replacements, issue deprecation warning(/error) - if key in ALTERNATIVE_EASYCONFIG_PARAMETERS: + if key == 'parallel': + _log.deprecated("Easyconfig parameter 'parallel' is deprecated, " + "use 'max_parallel' or the parallel property instead.", '6.0') + # This hidden parameter allows easyblocks to continue using self.cfg['parallel'] which contains + # the computed parallelism after the ready step but the easyconfig parameter before that step. + + # Easyblocks using `max_parallel` always get the value from the easyconfig unmodified. + # Easyblocks should use either the parallel property or `max_parallel` such that the semantic is clear. + # In particular writes to self.cfg['parallel'] do NOT update the %(parallel)s template. + # It can be removed when the deprecation expires. + key = '_parallelLegacy' + elif key in ALTERNATIVE_EASYCONFIG_PARAMETERS: key = ALTERNATIVE_EASYCONFIG_PARAMETERS[key] elif key in DEPRECATED_EASYCONFIG_PARAMETERS: depr_key = key @@ -144,7 +155,10 @@ def is_local_var_name(name): """ res = False if name.startswith(LOCAL_VAR_PREFIX) or name.startswith('_'): - res = True + # make exception for '_parallelLegacy' hidden easyconfig parameter, + # which is used to deprecate use of 'paralell' easyconfig parameter + if name != '_parallelLegacy': + res = True # __builtins__ is always defined as a 'local' variables # single-letter local variable names are allowed (mainly for use in list comprehensions) # in Python 2, variables defined in list comprehensions leak to the outside (no longer the case in Python 3) @@ -502,6 +516,12 @@ def __init__(self, path, extra_options=None, build_specs=None, validate=True, hi self.iterate_options = [] self.iterating = False + # Storage for parallel property. Mark as unset initially + self._parallel = None + # introduce hidden '_parallelLegacy' easyconfig parameter, + # used to deprecate use of 'parallel' easyconfig parameter + self._config['_parallelLegacy'] = [None, '', ('', )] + # parse easyconfig file self.build_specs = build_specs self.parse() @@ -598,6 +618,7 @@ def copy(self, validate=None): ec = EasyConfig(self.path, validate=validate, hidden=self.hidden, rawtxt=self.rawtxt) # take a copy of the actual config dictionary (which already contains the extra options) ec._config = copy.deepcopy(self._config) + ec._parallel = self._parallel # Might be already set, e.g. for extensions # since rawtxt is defined, self.path may not get inherited, make sure it does if self.path: ec.path = self.path @@ -702,6 +723,12 @@ def parse(self): if missing_mandatory_keys: raise EasyBuildError("mandatory parameters not provided in %s: %s", self.path, missing_mandatory_keys) + if 'parallel' in ec_vars: + # Replace value and issue better warning for easyconfig parameters, + # as opposed to warnings meant for easyblocks) + self.log.deprecated("Easyconfig parameter 'parallel' is deprecated, use 'max_parallel' instead.", '6.0') + ec_vars['_parallelLegacy'] = ec_vars.pop('parallel') + # provide suggestions for typos. Local variable names are excluded from this check possible_typos = [(key, difflib.get_close_matches(key.lower(), self._config.keys(), 1, 0.85)) for key in ec_vars if not is_local_var_name(key) and key not in self] @@ -1235,6 +1262,32 @@ def all_dependencies(self): return self._all_dependencies + @property + def is_parallel_set(self): + """Return if the desired parallelism has been determined yet""" + return self._parallel is not None + + @property + def parallel(self): + """Degree of parallellism (number of cores) to be used for building, etc.""" + if not self.is_parallel_set: + raise ValueError("Parallelism not set yet, 'set_parallel' method of easyblock must be called first") + + # This gets set when an easyblock changes ec['parallel']. + # It also gets set/updated in set_parallel to mirror the old behavior during the deprecation phase + parallelLegacy = self._config['_parallelLegacy'][0] + if parallelLegacy is not None: + return max(1, parallelLegacy) + return self._parallel + + @parallel.setter + def parallel(self, value): + # Update backstorage and template value + self._parallel = max(1, value) # Also handles False + self.template_values['parallel'] = self._parallel + # Backwards compatibility, only for easyblocks still reading self.cfg['parallel'] + self._config['_parallelLegacy'][0] = self._parallel + def dump(self, fp, always_overwrite=True, backup=False, explicit_toolchains=False): """ Dump this easyconfig to file, with the given filename. diff --git a/easybuild/framework/easyconfig/format/format.py b/easybuild/framework/easyconfig/format/format.py index 0839f5bced..39a66bb54d 100644 --- a/easybuild/framework/easyconfig/format/format.py +++ b/easybuild/framework/easyconfig/format/format.py @@ -68,7 +68,7 @@ ['preconfigopts', 'configopts'], ['prebuildopts', 'buildopts'], ['preinstallopts', 'installopts'], - ['parallel', 'maxparallel'], + ['maxparallel'], ] LAST_PARAMS = ['exts_default_options', 'exts_list', 'sanity_check_paths', 'sanity_check_commands', diff --git a/easybuild/framework/easyconfig/templates.py b/easybuild/framework/easyconfig/templates.py index 631006d4de..46fe4c5970 100644 --- a/easybuild/framework/easyconfig/templates.py +++ b/easybuild/framework/easyconfig/templates.py @@ -59,7 +59,6 @@ 'bitbucket_account', 'github_account', 'name', - 'parallel', 'version', 'versionsuffix', 'versionprefix', @@ -103,12 +102,12 @@ 'cuda_sm_comma_sep': 'Comma-separated list of sm_* values that correspond with CUDA compute capabilities', 'cuda_sm_space_sep': 'Space-separated list of sm_* values that correspond with CUDA compute capabilities', 'mpi_cmd_prefix': 'Prefix command for running MPI programs (with default number of ranks)', + 'parallel': "Degree of parallelism for e.g. make", # can't be a boolean (True/False), must be a string value since it's a string template 'rpath_enabled': "String value indicating whether or not RPATH linking is used ('true' or 'false')", 'software_commit': "Git commit id to use for the software as specified by --software-commit command line option", 'sysroot': "Location root directory of system, prefix for standard paths like /usr/lib and /usr/include" "as specify by the --sysroot configuration option", - } # constant templates that can be used in easyconfigs diff --git a/easybuild/framework/extension.py b/easybuild/framework/extension.py index c3025ebab3..51a40bbe15 100644 --- a/easybuild/framework/extension.py +++ b/easybuild/framework/extension.py @@ -132,6 +132,11 @@ def __init__(self, mself, ext, extra_params=None): self.options = resolve_template(copy.deepcopy(self.ext.get('options', {})), self.cfg.template_values, expect_resolved=False) + if 'parallel' in self.options: + # Replace value and issue better warning for easyconfig parameters, + # as opposed to warnings meant for easyblocks + self.log.deprecated("Easyconfig parameter 'parallel' is deprecated, use 'max_parallel' instead.", '6.0') + self.options['max_parallel'] = self.options.pop('parallel') if extra_params: self.cfg.extend_params(extra_params, overwrite=False) @@ -149,6 +154,12 @@ def __init__(self, mself, ext, extra_params=None): self.log.debug("Skipping unknown custom easyconfig parameter '%s' for extension %s/%s: %s", key, name, version, value) + # If parallelism has been set already take potentially new limitation into account + if self.cfg.is_parallel_set: + max_par = self.cfg['max_parallel'] + if max_par is not None and max_par < self.cfg.parallel: + self.cfg.parallel = max_par + self.sanity_check_fail_msgs = [] self.sanity_check_module_loaded = False self.fake_mod_data = None diff --git a/easybuild/scripts/mk_tmpl_easyblock_for.py b/easybuild/scripts/mk_tmpl_easyblock_for.py index b4abadfb76..2a5e8871c5 100755 --- a/easybuild/scripts/mk_tmpl_easyblock_for.py +++ b/easybuild/scripts/mk_tmpl_easyblock_for.py @@ -165,7 +165,7 @@ def build_step(self): comp_fam = comp_map[self.toolchain.comp_family()] # enable parallel build - par = self.cfg['parallel'] + par = self.cfg.parallel cmd = "build command --parallel %%d --compiler-family %%s" %% (par, comp_fam) run_shell_cmd(cmd) diff --git a/easybuild/tools/systemtools.py b/easybuild/tools/systemtools.py index 8a66f5d848..682f777b9c 100644 --- a/easybuild/tools/systemtools.py +++ b/easybuild/tools/systemtools.py @@ -1214,6 +1214,8 @@ def get_default_parallelism(): raise EasyBuildError("Specified level of parallelism '%s' is not an integer value: %s", par, err) if maxpar is not None and maxpar < par: + if maxpar is False: + maxpar = 1 _log.info("Limiting parallelism from %s to %s", par, maxpar) par = maxpar diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index 97d8f31b93..c6f6a858bc 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -2493,52 +2493,122 @@ def test_parallel(self): handle, toy_ec2 = tempfile.mkstemp(prefix='easyblock_test_file_', suffix='.eb') os.close(handle) - write_file(toy_ec2, toytxt + "\nparallel = 123\nmaxparallel = 67") + write_file(toy_ec2, toytxt + "\nparallel = 12\nmaxparallel = 6") handle, toy_ec3 = tempfile.mkstemp(prefix='easyblock_test_file_', suffix='.eb') os.close(handle) write_file(toy_ec3, toytxt + "\nparallel = False") + handle, toy_ec4 = tempfile.mkstemp(prefix='easyblock_test_file_', suffix='.eb') + os.close(handle) + write_file(toy_ec4, toytxt + "\nmaxparallel = 6") + + handle, toy_ec5 = tempfile.mkstemp(prefix='easyblock_test_file_', suffix='.eb') + os.close(handle) + write_file(toy_ec5, toytxt + "\nmaxparallel = False") + # default: parallelism is derived from # available cores + ulimit - test_eb = EasyBlock(EasyConfig(toy_ec)) - test_eb.check_readiness_step() - self.assertTrue(isinstance(test_eb.cfg['parallel'], int) and test_eb.cfg['parallel'] > 0) - - # only 'parallel' easyconfig parameter specified (no 'parallel' build option) - test_eb = EasyBlock(EasyConfig(toy_ec1)) - test_eb.check_readiness_step() - self.assertEqual(test_eb.cfg['parallel'], 13) - - # both 'parallel' and 'maxparallel' easyconfig parameters specified (no 'parallel' build option) - test_eb = EasyBlock(EasyConfig(toy_ec2)) - test_eb.check_readiness_step() - self.assertEqual(test_eb.cfg['parallel'], 67) - - # make sure 'parallel = False' is not overriden (no 'parallel' build option) - test_eb = EasyBlock(EasyConfig(toy_ec3)) - test_eb.check_readiness_step() - self.assertEqual(test_eb.cfg['parallel'], False) - - # only 'parallel' build option specified - init_config(build_options={'parallel': '9', 'validate': False}) - test_eb = EasyBlock(EasyConfig(toy_ec)) - test_eb.check_readiness_step() - self.assertEqual(test_eb.cfg['parallel'], 9) - - # both 'parallel' build option and easyconfig parameter specified (no 'maxparallel') - test_eb = EasyBlock(EasyConfig(toy_ec1)) - test_eb.check_readiness_step() - self.assertEqual(test_eb.cfg['parallel'], 9) - - # both 'parallel' and 'maxparallel' easyconfig parameters specified + 'parallel' build option - test_eb = EasyBlock(EasyConfig(toy_ec2)) - test_eb.check_readiness_step() - self.assertEqual(test_eb.cfg['parallel'], 9) - - # make sure 'parallel = False' is not overriden (with 'parallel' build option) - test_eb = EasyBlock(EasyConfig(toy_ec3)) - test_eb.check_readiness_step() - self.assertEqual(test_eb.cfg['parallel'], 0) + # Note that maxparallel has a default of 16, so we need a lower auto_parallel value here + auto_parallel = 16 - 4 # Using + 3 below which must still be less + st.det_parallelism._default_parallelism = auto_parallel + + # 'parallel' build option NOT specified + test_cases = { + '': auto_parallel, + 'parallel = False': 1, + 'parallel = 1': 1, + 'parallel = 6': 6, + f'parallel = {auto_parallel + 3}': auto_parallel + 3, # Setting parallel disables auto-detection + 'maxparallel = False': 1, + 'maxparallel = 1': 1, + 'maxparallel = 6': 6, + f'maxparallel = {auto_parallel + 3}': auto_parallel, + 'parallel = 8\nmaxparallel = 6': 6, + 'parallel = 8\nmaxparallel = 9': 8, + 'parallel = False\nmaxparallel = 6': 1, + 'parallel = 8\nmaxparallel = False': 1, + } + + for txt, expected in test_cases.items(): + with self.subTest(ec_params=txt): + self.contents = toytxt + '\n' + txt + self.writeEC() + with self.temporarily_allow_deprecated_behaviour(), self.mocked_stdout_stderr(): + test_eb = EasyBlock(EasyConfig(self.eb_file)) + test_eb.post_init() + self.assertEqual(test_eb.cfg.parallel, expected) + with self.temporarily_allow_deprecated_behaviour(), self.mocked_stdout_stderr(): + self.assertEqual(test_eb.cfg['parallel'], expected) + + # 'parallel' build option specified + buildopt_parallel = 11 + # When build option is given the auto-parallelism is ignored. Verify by setting it very low + st.det_parallelism._default_parallelism = 2 + init_config(build_options={'parallel': str(buildopt_parallel), 'validate': False}) + + test_cases = { + '': buildopt_parallel, + 'parallel = False': 1, + 'parallel = 1': 1, + 'parallel = 6': 6, + f'parallel = {buildopt_parallel + 2}': buildopt_parallel, + 'maxparallel = False': 1, + 'maxparallel = 1': 1, + 'maxparallel = 6': 6, + f'maxparallel = {buildopt_parallel + 2}': buildopt_parallel, + 'parallel = 8\nmaxparallel = 6': 6, + 'parallel = 8\nmaxparallel = 9': 8, + 'parallel = False\nmaxparallel = 6': 1, + 'parallel = 8\nmaxparallel = False': 1, + } + + for txt, expected in test_cases.items(): + with self.subTest(ec_params=txt): + self.contents = toytxt + '\n' + txt + self.writeEC() + with self.temporarily_allow_deprecated_behaviour(), self.mocked_stdout_stderr(): + test_eb = EasyBlock(EasyConfig(self.eb_file)) + test_eb.post_init() + self.assertEqual(test_eb.cfg.parallel, expected) + with self.temporarily_allow_deprecated_behaviour(), self.mocked_stdout_stderr(): + self.assertEqual(test_eb.cfg['parallel'], expected) + + # Template updated correctly + self.contents = toytxt + '\nmaxparallel=2' + self.writeEC() + test_eb = EasyBlock(EasyConfig(self.eb_file)) + test_eb.post_init() + + test_eb.cfg['buildopts'] = '-j %(parallel)s' + self.assertEqual(test_eb.cfg['buildopts'], '-j 2') + # Might be done in an easyblock step + test_eb.cfg.parallel = 42 + self.assertEqual(test_eb.cfg['buildopts'], '-j 42') + # Unaffected by build settings + test_eb.cfg.parallel = 421337 + self.assertEqual(test_eb.cfg['buildopts'], '-j 421337') + # False is equal to 1 + test_eb.cfg.parallel = False + self.assertEqual(test_eb.cfg['buildopts'], '-j 1') + + # Legacy behavior. To be removed after deprecation of the parallel EC parameter + self.contents = toytxt + '\nmaxparallel=99' + self.writeEC() + with self.temporarily_allow_deprecated_behaviour(), self.mocked_stdout_stderr(): + test_eb = EasyBlock(EasyConfig(self.eb_file)) + parallel = buildopt_parallel - 2 + test_eb.cfg['parallel'] = parallel # Old Easyblocks might change that before the ready step + test_eb.post_init() + self.assertEqual(test_eb.cfg.parallel, parallel) + self.assertEqual(test_eb.cfg['parallel'], parallel) + # Afterwards it also gets reflected directly ignoring maxparallel + parallel = buildopt_parallel * 3 + test_eb.cfg['parallel'] = parallel + self.assertEqual(test_eb.cfg.parallel, parallel) + self.assertEqual(test_eb.cfg['parallel'], parallel) + + # Reset mocked value + del st.det_parallelism._default_parallelism def test_guess_start_dir(self): """Test guessing the start dir.""" diff --git a/test/framework/easyconfig.py b/test/framework/easyconfig.py index 3b453cdff8..0f10ba486d 100644 --- a/test/framework/easyconfig.py +++ b/test/framework/easyconfig.py @@ -675,7 +675,7 @@ def test_tweaking(self): 'version = "3.14"', 'toolchain = {"name": "GCC", "version": "4.6.3"}', 'patches = %s', - 'parallel = 1', + 'maxparallel = 1', 'keepsymlinks = True', ]) % str(patches) self.prep() @@ -698,7 +698,7 @@ def test_tweaking(self): # It should be possible to overwrite values with True/False/None as they often have special meaning 'runtest': 'False', 'hidden': 'True', - 'parallel': 'None', # Good example: parallel=None means "Auto detect" + 'maxparallel': 'None', # Good example: maxparallel=None means "unlimitted" # Adding new options (added only by easyblock) should also be possible # and in case the string "True/False/None" is really wanted it is possible to quote it first 'test_none': '"False"', @@ -715,7 +715,7 @@ def test_tweaking(self): self.assertEqual(eb['patches'], new_patches) self.assertIs(eb['runtest'], False) self.assertIs(eb['hidden'], True) - self.assertIsNone(eb['parallel']) + self.assertIsNone(eb['maxparallel']) self.assertEqual(eb['test_none'], 'False') self.assertEqual(eb['test_bool'], 'True') self.assertEqual(eb['test_123'], 'None') @@ -1976,8 +1976,7 @@ def test_alternative_easyconfig_parameters(self): def test_deprecated_easyconfig_parameters(self): """Test handling of deprecated easyconfig parameters.""" - os.environ.pop('EASYBUILD_DEPRECATED') - easybuild.tools.build_log.CURRENT_VERSION = self.orig_current_version + self.allow_deprecated_behaviour() init_config() test_ecs_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'easyconfigs', 'test_ecs') @@ -3562,7 +3561,6 @@ def test_template_constant_dict(self): 'namelower': 'gzip', 'nameletter': 'g', 'nameletterlower': 'g', - 'parallel': None, 'rpath_enabled': rpath, 'software_commit': '', 'sysroot': '', @@ -3601,7 +3599,6 @@ def test_template_constant_dict(self): res = template_constant_dict(ec) res.pop('arch') - expected['parallel'] = 12 self.assertEqual(res, expected) toy_ec = os.path.join(test_ecs_dir, 't', 'toy', 'toy-0.0-deps.eb') @@ -3643,7 +3640,6 @@ def test_template_constant_dict(self): 'toolchain_name': 'system', 'toolchain_version': 'system', 'nameletterlower': 't', - 'parallel': None, 'pymajver': '3', 'pyminver': '7', 'pyshortver': '3.7', @@ -3679,7 +3675,7 @@ def test_template_constant_dict(self): ec = EasyConfigParser(filename=test_ec).get_config_dict() expected['module_name'] = None - for key in ('bitbucket_account', 'github_account', 'parallel', 'versionprefix'): + for key in ('bitbucket_account', 'github_account', 'versionprefix'): del expected[key] dep_names = [x[0] for x in ec['dependencies']] diff --git a/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-GCC-6.4.0-2.28.eb b/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-GCC-6.4.0-2.28.eb index c272f8dbbd..c6df4d42c6 100644 --- a/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-GCC-6.4.0-2.28.eb +++ b/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-GCC-6.4.0-2.28.eb @@ -31,7 +31,7 @@ dependencies = [ # ('Tcl', '8.6.4'), ] -parallel = 1 +maxparallel = 1 sanity_check_paths = { 'files': ['bin/sqlite3', 'include/sqlite3ext.h', 'include/sqlite3.h', 'lib/libsqlite3.a', 'lib/libsqlite3.so'], diff --git a/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-foss-2018a.eb b/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-foss-2018a.eb index 593ca3018a..937553eaf3 100644 --- a/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-foss-2018a.eb +++ b/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-foss-2018a.eb @@ -31,7 +31,7 @@ dependencies = [ # ('Tcl', '8.6.4'), ] -parallel = 1 +maxparallel = 1 sanity_check_paths = { 'files': ['bin/sqlite3', 'include/sqlite3ext.h', 'include/sqlite3.h', 'lib/libsqlite3.a', 'lib/libsqlite3.so'], diff --git a/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-gompi-2018a.eb b/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-gompi-2018a.eb index 5463f54352..b0be557296 100644 --- a/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-gompi-2018a.eb +++ b/test/framework/easyconfigs/test_ecs/s/SQLite/SQLite-3.8.10.2-gompi-2018a.eb @@ -31,7 +31,7 @@ dependencies = [ # ('Tcl', '8.6.4'), ] -parallel = 1 +maxparallel = 1 sanity_check_paths = { 'files': ['bin/sqlite3', 'include/sqlite3ext.h', 'include/sqlite3.h', 'lib/libsqlite3.a', 'lib/libsqlite3.so'], diff --git a/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompi-2018a-OpenBLAS-0.2.20-broken.eb b/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompi-2018a-OpenBLAS-0.2.20-broken.eb index 6b3ce0d492..e85f325169 100644 --- a/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompi-2018a-OpenBLAS-0.2.20-broken.eb +++ b/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompi-2018a-OpenBLAS-0.2.20-broken.eb @@ -23,6 +23,6 @@ builddependencies = [('CMake','2.8.10')] dependencies = [(local_blaslib, local_blasver, '')] # parallel build tends to fail, so disabling it -parallel = 1 +maxparallel = 1 moduleclass = 'numlib' diff --git a/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompi-2018a-OpenBLAS-0.2.20.eb b/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompi-2018a-OpenBLAS-0.2.20.eb index bb6a33480d..4a2c2bcaf2 100644 --- a/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompi-2018a-OpenBLAS-0.2.20.eb +++ b/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompi-2018a-OpenBLAS-0.2.20.eb @@ -22,6 +22,6 @@ versionsuffix = "-%s-%s" % (local_blaslib, local_blasver) dependencies = [(local_blaslib, local_blasver, '')] # parallel build tends to fail, so disabling it -parallel = 1 +maxparallel = 1 moduleclass = 'numlib' diff --git a/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompic-2018a-OpenBLAS-0.2.20.eb b/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompic-2018a-OpenBLAS-0.2.20.eb index d8c8855873..b3db5dbbf0 100644 --- a/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompic-2018a-OpenBLAS-0.2.20.eb +++ b/test/framework/easyconfigs/test_ecs/s/ScaLAPACK/ScaLAPACK-2.0.2-gompic-2018a-OpenBLAS-0.2.20.eb @@ -22,6 +22,6 @@ versionsuffix = "-%s-%s" % (local_blaslib, local_blasver) dependencies = [(local_blaslib, local_blasver)] # parallel build tends to fail, so disabling it -parallel = 1 +maxparallel = 1 moduleclass = 'numlib' diff --git a/test/framework/utilities.py b/test/framework/utilities.py index fc3afddb40..de08022454 100644 --- a/test/framework/utilities.py +++ b/test/framework/utilities.py @@ -212,6 +212,14 @@ def allow_deprecated_behaviour(self): os.environ.pop('EASYBUILD_DEPRECATED', None) eb_build_log.CURRENT_VERSION = self.orig_current_version + @contextmanager + def temporarily_allow_deprecated_behaviour(self): + self.allow_deprecated_behaviour() + try: + yield + finally: + self.disallow_deprecated_behaviour() + @contextmanager def log_to_testlogfile(self): """Context manager class to capture log output in self.logfile for the scope used. Clears the file first"""