diff --git a/.github/workflows/container_tests_apptainer.yml b/.github/workflows/container_tests_apptainer.yml index 35c26c26c9..77d2a4a395 100644 --- a/.github/workflows/container_tests_apptainer.yml +++ b/.github/workflows/container_tests_apptainer.yml @@ -29,10 +29,18 @@ jobs: - name: install OS & Python packages run: | # for building CentOS 7 container images - sudo apt-get install rpm - sudo apt-get install dnf + APT_PKGS="rpm dnf" # for modules tool - sudo apt-get install lua5.2 liblua5.2-dev lua-filesystem lua-posix tcl tcl-dev + APT_PKGS+=" lua5.2 liblua5.2-dev lua-filesystem lua-posix tcl tcl-dev" + + # Avoid apt-get update, as we don't really need it, + # and it does more harm than good (it's fairly expensive, and it results in flaky test runs) + if ! sudo apt-get install $APT_PKGS; then + # Try to update cache, then try again to resolve 404s of old packages + sudo apt-get update -yqq || true + sudo apt-get install $APT_PKGS + fi + # fix for lua-posix packaging issue, see https://bugs.launchpad.net/ubuntu/+source/lua-posix/+bug/1752082 # needed for Ubuntu 18.04, but not for Ubuntu 20.04, so skipping symlinking if posix.so already exists if [ ! -e /usr/lib/x86_64-linux-gnu/lua/5.2/posix.so ] ; then diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index ec98f9df03..c79b515e42 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -178,7 +178,7 @@ jobs: echo "Not testing with '${module_syntax}' as module syntax with '${EASYBUILD_MODULES_TOOL}' as modules tool" continue fi - printf '\n\n=====================> Using $module_syntax module syntax <=====================\n\n' + printf "\n\n=====================> Using $module_syntax module syntax <=====================\n\n" export EASYBUILD_MODULE_SYNTAX="${module_syntax}" export TEST_EASYBUILD_MODULE_SYNTAX="${EASYBUILD_MODULE_SYNTAX}" diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 94b66db903..07c9756e67 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -4,6 +4,41 @@ For more detailed information, please see the git log. These release notes can also be consulted at https://easybuild.readthedocs.io/en/latest/Release_notes.html. +v4.9.1 (5 April 2024) +--------------------- + +update/bugfix release + +- various enhancements, including: + - make `is_rpath_wrapper` faster by only checking file contents if file is not located in subdirectory of RPATH wrapper subdirectory (#4406) + - add terse support to `--missing-modules` (#4407) + - adapt version pattern for EnvironmentModules to allow using development version (#4416) + - use `--all` option with EnvironmentModules v4.6+ to get available hidden modules (#4417) + - add support for appending to path environment variables via `modextrapaths_append` + add corresponding `allow_append_abs_path` (#4436) + - improve output produced by `--check-github` (#4437) + - add script for updating local git repos with `develop` branch (#4438) + - show error when multiple PR options are passed (#4440) + - improve `findPythonDeps` script to recognize non-canonical package names (#4445) + - add support for `--from-commit` and `--include-easyblocks-from-commit` (#4468) + - improve logging & handling of (empty) `--optarch` values (#4481) + - add `--short` option to `findUpdatedEcs` script (#4488) + - add generic GCC and Clang compiler flags for RISC-V (#4489) +- various bug fixes, including: + - clean up log file of `EasyBlock` instance in `check_sha256_checksums` (#4452) + - fix description of `backup-modules` configuration option (#4456) + - replace `'` with `"` for `printf` in CI workflow for running test suite to have bash replace a variable (#4461) + - use `cp -dR` instead of `cp -a` for shell script "extraction" (#4465) + - fix link to documentation in `close_pr` message (#4466) + - fix `test_github_merge_pr` by using more recent easyconfigs PR (#4470) + - add workaround for 404 error when installing packages in CI workflow for testing Apptainer integration (#4472) +- other changes: + - clean up & speed up environment checks (#4409) + - use more performant and concise dict construction by using dict comprehensions (#4410) + - remove superflous string formatting (#4411) + - clean up uses of `getattr` and `hasattr` (#4412) + - update copyright lines to 2024 (#4494) + + v4.9.0 (30 December 2023) ------------------------- diff --git a/easybuild/__init__.py b/easybuild/__init__.py index 4763af8bc4..3637c9f395 100644 --- a/easybuild/__init__.py +++ b/easybuild/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2011-2023 Ghent University +# Copyright 2011-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/base/exceptions.py b/easybuild/base/exceptions.py index 3bde7cc6a1..eb004ad217 100644 --- a/easybuild/base/exceptions.py +++ b/easybuild/base/exceptions.py @@ -1,5 +1,5 @@ # -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/base/fancylogger.py b/easybuild/base/fancylogger.py index b5a63477c6..cd09a644db 100644 --- a/easybuild/base/fancylogger.py +++ b/easybuild/base/fancylogger.py @@ -1,5 +1,5 @@ # -# Copyright 2011-2023 Ghent University +# Copyright 2011-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -147,10 +147,10 @@ def _env_to_boolean(varname, default=False): >>> _env_to_boolean('NO_FOOBAR') False """ - if varname not in os.environ: + try: + return os.environ[varname].lower() in ('1', 'yes', 'true', 'y') + except KeyError: return default - else: - return os.environ.get(varname).lower() in ('1', 'yes', 'true', 'y') OPTIMIZED_ANSWER = "not available in optimized mode" @@ -286,7 +286,7 @@ def makeRecord(self, name, level, pathname, lineno, msg, args, excinfo, func=Non overwrite make record to use a fancy record (with more options) """ logrecordcls = logging.LogRecord - if hasattr(self, 'fancyrecord') and self.fancyrecord: + if getattr(self, 'fancyrecord', None): logrecordcls = FancyLogRecord try: new_msg = str(msg) @@ -911,16 +911,15 @@ def resetroot(): _default_logTo = None if 'FANCYLOG_SERVER' in os.environ: server = os.environ['FANCYLOG_SERVER'] - port = DEFAULT_UDP_PORT if ':' in server: server, port = server.split(':') + else: + port = DEFAULT_UDP_PORT # maybe the port was specified in the FANCYLOG_SERVER_PORT env var. this takes precedence - if 'FANCYLOG_SERVER_PORT' in os.environ: - port = int(os.environ['FANCYLOG_SERVER_PORT']) - port = int(port) + port = os.environ.get('FANCYLOG_SERVER_PORT', port) - logToUDP(server, port) + logToUDP(server, int(port)) _default_logTo = logToUDP else: # log to screen by default diff --git a/easybuild/base/generaloption.py b/easybuild/base/generaloption.py index 51f7daafe3..90248fb0cd 100644 --- a/easybuild/base/generaloption.py +++ b/easybuild/base/generaloption.py @@ -1,5 +1,5 @@ # -# Copyright 2011-2023 Ghent University +# Copyright 2011-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -90,7 +90,7 @@ def set_columns(cols=None): pass if cols is not None: - os.environ['COLUMNS'] = "%s" % cols + os.environ['COLUMNS'] = str(cols) def what_str_list_tuple(name): @@ -199,7 +199,8 @@ class ExtOption(CompleterOption): ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + EXTOPTION_EXTRA_OPTIONS TYPE_STRLIST = ['%s%s' % (name, klass) for klass in ['list', 'tuple'] for name in ['str', 'path']] - TYPE_CHECKER = dict([(x, check_str_list_tuple) for x in TYPE_STRLIST] + list(Option.TYPE_CHECKER.items())) + TYPE_CHECKER = {x: check_str_list_tuple for x in TYPE_STRLIST} + TYPE_CHECKER.update(Option.TYPE_CHECKER) TYPES = tuple(TYPE_STRLIST + list(Option.TYPES)) BOOLEAN_ACTIONS = ('store_true', 'store_false',) + EXTOPTION_LOG @@ -807,7 +808,7 @@ def get_env_options(self): epilogprefixtxt += "eg. --some-opt is same as setting %(prefix)s_SOME_OPT in the environment." self.epilog.append(epilogprefixtxt % {'prefix': self.envvar_prefix}) - candidates = dict([(k, v) for k, v in os.environ.items() if k.startswith("%s_" % self.envvar_prefix)]) + candidates = {k: v for k, v in os.environ.items() if k.startswith("%s_" % self.envvar_prefix)} for opt in self._get_all_options(): if opt._long_opts is None: @@ -822,8 +823,8 @@ def get_env_options(self): self.environment_arguments.append("%s=%s" % (lo, val)) else: # interpretation of values: 0/no/false means: don't set it - if ("%s" % val).lower() not in ("0", "no", "false",): - self.environment_arguments.append("%s" % lo) + if str(val).lower() not in ("0", "no", "false",): + self.environment_arguments.append(str(lo)) else: self.log.debug("Environment variable %s is not set" % env_opt_name) @@ -1031,7 +1032,7 @@ def main_options(self): # make_init is deprecated if hasattr(self, 'make_init'): self.log.debug('main_options: make_init is deprecated. Rename function to main_options.') - getattr(self, 'make_init')() + self.make_init() else: # function names which end with _options and do not start with main or _ reg_main_options = re.compile("^(?!_|main).*_options$") @@ -1189,7 +1190,7 @@ def add_group_parser(self, opt_dict, description, prefix=None, otherdefaults=Non for extra_detail in details[4:]: if isinstance(extra_detail, (list, tuple,)): # choices - nameds['choices'] = ["%s" % x for x in extra_detail] # force to strings + nameds['choices'] = [str(x) for x in extra_detail] # force to strings hlp += ' (choices: %s)' % ', '.join(nameds['choices']) elif isinstance(extra_detail, string_type) and len(extra_detail) == 1: args.insert(0, "-%s" % extra_detail) diff --git a/easybuild/base/optcomplete.py b/easybuild/base/optcomplete.py index 9a2bc8a127..3fa75a6635 100644 --- a/easybuild/base/optcomplete.py +++ b/easybuild/base/optcomplete.py @@ -513,14 +513,15 @@ def autocomplete(parser, arg_completer=None, opt_completer=None, subcmd_complete if option: if option.nargs > 0: optarg = True - if hasattr(option, 'completer'): + try: completer = option.completer - elif option.choices: - completer = ListCompleter(option.choices) - elif option.type in ('string',): - completer = opt_completer - else: - completer = NoneCompleter() + except AttributeError: + if option.choices: + completer = ListCompleter(option.choices) + elif option.type in ('string',): + completer = opt_completer + else: + completer = NoneCompleter() # Warn user at least, it could help him figure out the problem. elif hasattr(option, 'completer'): msg = "Error: optparse option with a completer does not take arguments: %s" % (option) @@ -616,11 +617,9 @@ class CmdComplete(object): def autocomplete(self, completer=None): parser = OPTIONPARSER_CLASS(self.__doc__.strip()) if hasattr(self, 'addopts'): - fnc = getattr(self, 'addopts') - fnc(parser) + self.addopts(parser) - if hasattr(self, 'completer'): - completer = getattr(self, 'completer') + completer = getattr(self, 'completer', completer) return autocomplete(parser, completer) diff --git a/easybuild/base/testing.py b/easybuild/base/testing.py index 01b64d84ef..4b3df7e563 100644 --- a/easybuild/base/testing.py +++ b/easybuild/base/testing.py @@ -1,5 +1,5 @@ # -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/__init__.py b/easybuild/framework/__init__.py index 019e507d79..f03298abca 100644 --- a/easybuild/framework/__init__.py +++ b/easybuild/framework/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 9f3233c265..d2727d61ee 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -1421,6 +1421,14 @@ def make_module_extra(self, altroot=None, altversion=None): value, type(value)) lines.append(self.module_generator.prepend_paths(key, value, allow_abs=self.cfg['allow_prepend_abs_path'])) + for (key, value) in self.cfg['modextrapaths_append'].items(): + if isinstance(value, string_type): + value = [value] + elif not isinstance(value, (tuple, list)): + raise EasyBuildError("modextrapaths_append dict value %s (type: %s) is not a list or tuple", + value, type(value)) + lines.append(self.module_generator.append_paths(key, value, allow_abs=self.cfg['allow_append_abs_path'])) + modloadmsg = self.cfg['modloadmsg'] if modloadmsg: # add trailing newline to prevent that shell prompt is 'glued' to module load message diff --git a/easybuild/framework/easyconfig/__init__.py b/easybuild/framework/easyconfig/__init__.py index 6d91c028a9..b19017e023 100644 --- a/easybuild/framework/easyconfig/__init__.py +++ b/easybuild/framework/easyconfig/__init__.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/constants.py b/easybuild/framework/easyconfig/constants.py index 2e62580db4..4fe8c9d7b5 100644 --- a/easybuild/framework/easyconfig/constants.py +++ b/easybuild/framework/easyconfig/constants.py @@ -1,5 +1,5 @@ # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/default.py b/easybuild/framework/easyconfig/default.py index dd91229d1e..965e6db037 100644 --- a/easybuild/framework/easyconfig/default.py +++ b/easybuild/framework/easyconfig/default.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -60,7 +60,7 @@ # we use a tuple here so we can sort them based on the numbers CATEGORY_NAMES = ['BUILD', 'CUSTOM', 'DEPENDENCIES', 'EXTENSIONS', 'FILEMANAGEMENT', 'HIDDEN', 'LICENSE', 'MANDATORY', 'MODULES', 'OTHER', 'TOOLCHAIN'] -ALL_CATEGORIES = dict((name, eval(name)) for name in CATEGORY_NAMES) +ALL_CATEGORIES = {name: eval(name) for name in CATEGORY_NAMES} # List of tuples. Each tuple has the following format (key, [default, help text, category]) DEFAULT_CONFIG = { @@ -189,10 +189,12 @@ 'exts_list': [[], 'List with extensions added to the base installation', EXTENSIONS], # MODULES easyconfig parameters + 'allow_append_abs_path': [False, "Allow specifying absolute paths to append in modextrapaths_append", MODULES], 'allow_prepend_abs_path': [False, "Allow specifying absolute paths to prepend in modextrapaths", MODULES], 'include_modpath_extensions': [True, "Include $MODULEPATH extensions specified by module naming scheme.", MODULES], 'modaliases': [{}, "Aliases to be defined in module file", MODULES], 'modextrapaths': [{}, "Extra paths to be prepended in module file", MODULES], + 'modextrapaths_append': [{}, "Extra paths to be appended in module file", MODULES], 'modextravars': [{}, "Extra environment variables to be added to module file", MODULES], 'modloadmsg': [{}, "Message that should be printed when generated module is loaded", MODULES], 'modunloadmsg': [{}, "Message that should be printed when generated module is unloaded", MODULES], diff --git a/easybuild/framework/easyconfig/easyconfig.py b/easybuild/framework/easyconfig/easyconfig.py index ff4ed3562c..73182da7ac 100644 --- a/easybuild/framework/easyconfig/easyconfig.py +++ b/easybuild/framework/easyconfig/easyconfig.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -303,7 +303,7 @@ def get_toolchain_hierarchy(parent_toolchain, incl_capabilities=False): """ # obtain list of all possible subtoolchains _, all_tc_classes = search_toolchain('') - subtoolchains = dict((tc_class.NAME, getattr(tc_class, 'SUBTOOLCHAIN', None)) for tc_class in all_tc_classes) + subtoolchains = {tc_class.NAME: getattr(tc_class, 'SUBTOOLCHAIN', None) for tc_class in all_tc_classes} optional_toolchains = set(tc_class.NAME for tc_class in all_tc_classes if getattr(tc_class, 'OPTIONAL', False)) composite_toolchains = set(tc_class.NAME for tc_class in all_tc_classes if len(tc_class.__bases__) > 1) @@ -985,7 +985,7 @@ def filter_hidden_deps(self): faulty_deps = [] # obtain reference to original lists, so their elements can be changed in place - deps = dict([(key, self.get_ref(key)) for key in ['dependencies', 'builddependencies', 'hiddendependencies']]) + deps = {key: self.get_ref(key) for key in ('dependencies', 'builddependencies', 'hiddendependencies')} if 'builddependencies' in self.iterate_options: deplists = copy.deepcopy(deps['builddependencies']) @@ -1229,11 +1229,11 @@ def dump(self, fp, always_overwrite=True, backup=False, explicit_toolchains=Fals # templated values should be dumped unresolved with self.disable_templating(): # build dict of default values - default_values = dict([(key, DEFAULT_CONFIG[key][0]) for key in DEFAULT_CONFIG]) - default_values.update(dict([(key, self.extra_options[key][0]) for key in self.extra_options])) + default_values = {key: DEFAULT_CONFIG[key][0] for key in DEFAULT_CONFIG} + default_values.update({key: self.extra_options[key][0] for key in self.extra_options}) self.generate_template_values() - templ_const = dict([(quote_py_str(const[1]), const[0]) for const in TEMPLATE_CONSTANTS]) + templ_const = {quote_py_str(const[1]): const[0] for const in TEMPLATE_CONSTANTS} # create reverse map of templates, to inject template values where possible # longer template values are considered first, shorter template keys get preference over longer ones @@ -1520,7 +1520,6 @@ def _parse_dependency(self, dep, hidden=False, build_only=False): # convert tuple to string otherwise python might complain about the formatting self.log.debug("Parsing %s as a dependency" % str(dep)) - attr = ['name', 'version', 'versionsuffix', 'toolchain'] dependency = { # full/short module names 'full_mod_name': None, @@ -1576,6 +1575,7 @@ def _parse_dependency(self, dep, hidden=False, build_only=False): raise EasyBuildError("Incorrect external dependency specification: %s", dep) else: # non-external dependency: tuple (or list) that specifies name/version(/versionsuffix(/toolchain)) + attr = ('name', 'version', 'versionsuffix', 'toolchain') dependency.update(dict(zip(attr, dep))) else: @@ -2049,7 +2049,7 @@ def resolve_template(value, tmpl_dict): elif isinstance(value, tuple): value = tuple(resolve_template(list(value), tmpl_dict)) elif isinstance(value, dict): - value = dict((resolve_template(k, tmpl_dict), resolve_template(v, tmpl_dict)) for k, v in value.items()) + value = {resolve_template(k, tmpl_dict): resolve_template(v, tmpl_dict) for k, v in value.items()} return value @@ -2256,7 +2256,7 @@ def verify_easyconfig_filename(path, specs, parsed_ec=None): for ec in ecs: found_fullver = det_full_ec_version(ec['ec']) if ec['ec']['name'] != specs['name'] or found_fullver != fullver: - subspec = dict((key, specs[key]) for key in ['name', 'toolchain', 'version', 'versionsuffix']) + subspec = {key: specs[key] for key in ('name', 'toolchain', 'version', 'versionsuffix')} error_msg = "Contents of %s does not match with filename" % path error_msg += "; expected filename based on contents: %s-%s.eb" % (ec['ec']['name'], found_fullver) error_msg += "; expected (relevant) parameters based on filename %s: %s" % (os.path.basename(path), subspec) diff --git a/easybuild/framework/easyconfig/format/__init__.py b/easybuild/framework/easyconfig/format/__init__.py index b2c084e273..c2a81766ad 100644 --- a/easybuild/framework/easyconfig/format/__init__.py +++ b/easybuild/framework/easyconfig/format/__init__.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/format/convert.py b/easybuild/framework/easyconfig/format/convert.py index 726acd3e6c..82613d42e0 100644 --- a/easybuild/framework/easyconfig/format/convert.py +++ b/easybuild/framework/easyconfig/format/convert.py @@ -1,5 +1,5 @@ # # -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/format/format.py b/easybuild/framework/easyconfig/format/format.py index 8abb697ece..3aeae419a2 100644 --- a/easybuild/framework/easyconfig/format/format.py +++ b/easybuild/framework/easyconfig/format/format.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -73,7 +73,7 @@ ] LAST_PARAMS = ['exts_default_options', 'exts_list', 'sanity_check_paths', 'sanity_check_commands', - 'modextrapaths', 'modextravars', + 'modextrapaths', 'modextrapaths_append', 'modextravars', 'moduleclass'] SANITY_CHECK_PATHS_DIRS = 'dirs' @@ -370,7 +370,7 @@ def parse(self, configobj): for key, value in self.supported.items(): if key not in self.VERSION_OPERATOR_VALUE_TYPES: raise EasyBuildError('Unsupported key %s in %s section', key, self.SECTION_MARKER_SUPPORTED) - self.sections['%s' % key] = value + self.sections[key] = value for key, supported_key, fn_name in [('version', 'versions', 'get_version_str'), ('toolchain', 'toolchains', 'as_dict')]: diff --git a/easybuild/framework/easyconfig/format/one.py b/easybuild/framework/easyconfig/format/one.py index 680e4ee77b..868e218925 100644 --- a/easybuild/framework/easyconfig/format/one.py +++ b/easybuild/framework/easyconfig/format/one.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/format/pyheaderconfigobj.py b/easybuild/framework/easyconfig/format/pyheaderconfigobj.py index b9fd31bf92..8227a40958 100644 --- a/easybuild/framework/easyconfig/format/pyheaderconfigobj.py +++ b/easybuild/framework/easyconfig/format/pyheaderconfigobj.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -51,9 +51,9 @@ def build_easyconfig_constants_dict(): """Make a dictionary with all constants that can be used""" all_consts = [ - ('TEMPLATE_CONSTANTS', dict([(x[0], x[1]) for x in TEMPLATE_CONSTANTS])), - ('EASYCONFIG_CONSTANTS', dict([(key, val[0]) for key, val in EASYCONFIG_CONSTANTS.items()])), - ('EASYCONFIG_LICENSES', dict([(klass().name, name) for name, klass in EASYCONFIG_LICENSES_DICT.items()])), + ('TEMPLATE_CONSTANTS', {x[0]: x[1] for x in TEMPLATE_CONSTANTS}), + ('EASYCONFIG_CONSTANTS', {key: val[0] for key, val in EASYCONFIG_CONSTANTS.items()}), + ('EASYCONFIG_LICENSES', {klass().name: name for name, klass in EASYCONFIG_LICENSES_DICT.items()}), ] err = [] const_dict = {} @@ -233,12 +233,13 @@ def pyheader_env(self): current_builtins = globals()['__builtins__'] builtins = {} for name in self.PYHEADER_ALLOWED_BUILTINS: - if hasattr(current_builtins, name): + try: builtins[name] = getattr(current_builtins, name) - elif isinstance(current_builtins, dict) and name in current_builtins: - builtins[name] = current_builtins[name] - else: - self.log.warning('No builtin %s found.' % name) + except AttributeError: + if isinstance(current_builtins, dict) and name in current_builtins: + builtins[name] = current_builtins[name] + else: + self.log.warning('No builtin %s found.' % name) global_vars['__builtins__'] = builtins self.log.debug("Available builtins: %s" % global_vars['__builtins__']) diff --git a/easybuild/framework/easyconfig/format/two.py b/easybuild/framework/easyconfig/format/two.py index cec3df3636..652b1c9b80 100644 --- a/easybuild/framework/easyconfig/format/two.py +++ b/easybuild/framework/easyconfig/format/two.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/format/version.py b/easybuild/framework/easyconfig/format/version.py index fe3b1a2316..b8f181e5aa 100644 --- a/easybuild/framework/easyconfig/format/version.py +++ b/easybuild/framework/easyconfig/format/version.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -69,7 +69,7 @@ class VersionOperator(object): '<': op.lt, '<=': op.le, } - REVERSE_OPERATOR_MAP = dict([(v, k) for k, v in OPERATOR_MAP.items()]) + REVERSE_OPERATOR_MAP = {v: k for k, v in OPERATOR_MAP.items()} INCLUDE_OPERATORS = ['==', '>=', '<='] # these operators *include* the (version) boundary ORDERED_OPERATORS = ['==', '>', '>=', '<', '<='] # ordering by strictness OPERATOR_FAMILIES = [['>', '>='], ['<', '<=']] # similar operators diff --git a/easybuild/framework/easyconfig/format/yeb.py b/easybuild/framework/easyconfig/format/yeb.py index acfab3fb22..675d0f0a86 100644 --- a/easybuild/framework/easyconfig/format/yeb.py +++ b/easybuild/framework/easyconfig/format/yeb.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/licenses.py b/easybuild/framework/easyconfig/licenses.py index e8eb1ee3bc..e6286d54e3 100644 --- a/easybuild/framework/easyconfig/licenses.py +++ b/easybuild/framework/easyconfig/licenses.py @@ -1,5 +1,5 @@ # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/parser.py b/easybuild/framework/easyconfig/parser.py index fa01d1b297..d6521b17dc 100644 --- a/easybuild/framework/easyconfig/parser.py +++ b/easybuild/framework/easyconfig/parser.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/style.py b/easybuild/framework/easyconfig/style.py index 0015b0c9b9..bad6ab5bda 100644 --- a/easybuild/framework/easyconfig/style.py +++ b/easybuild/framework/easyconfig/style.py @@ -1,5 +1,5 @@ ## -# Copyright 2016-2023 Ghent University +# Copyright 2016-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easyconfig/templates.py b/easybuild/framework/easyconfig/templates.py index aed8db6af4..9da6e9a2b9 100644 --- a/easybuild/framework/easyconfig/templates.py +++ b/easybuild/framework/easyconfig/templates.py @@ -1,5 +1,5 @@ # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -258,7 +258,7 @@ def template_constant_dict(config, ignore=None, skip_lower=None, toolchain=None) # step 2: define *ver and *shortver templates if TEMPLATE_SOFTWARE_VERSIONS: - name_to_prefix = dict((name.lower(), pref) for name, pref in TEMPLATE_SOFTWARE_VERSIONS) + name_to_prefix = {name.lower(): pref for name, pref in TEMPLATE_SOFTWARE_VERSIONS} deps = config.get('dependencies', []) # also consider build dependencies for *ver and *shortver templates; diff --git a/easybuild/framework/easyconfig/tools.py b/easybuild/framework/easyconfig/tools.py index c6649c383b..6f2a2741ad 100644 --- a/easybuild/framework/easyconfig/tools.py +++ b/easybuild/framework/easyconfig/tools.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -60,8 +60,9 @@ from easybuild.tools.filetools import find_easyconfigs, is_patch_file, locate_files from easybuild.tools.filetools import read_file, resolve_path, which, write_file from easybuild.tools.github import GITHUB_EASYCONFIGS_REPO -from easybuild.tools.github import det_pr_labels, det_pr_title, download_repo, fetch_easyconfigs_from_pr, fetch_pr_data -from easybuild.tools.github import fetch_files_from_pr +from easybuild.tools.github import det_pr_labels, det_pr_title, download_repo, fetch_easyconfigs_from_commit +from easybuild.tools.github import fetch_easyconfigs_from_pr, fetch_pr_data +from easybuild.tools.github import fetch_files_from_commit, fetch_files_from_pr from easybuild.tools.multidiff import multidiff from easybuild.tools.py2vs3 import OrderedDict from easybuild.tools.toolchain.toolchain import is_system_toolchain @@ -310,7 +311,7 @@ def get_paths_for(subdir=EASYCONFIGS_PKG_SUBDIR, robot_path=None): return paths -def alt_easyconfig_paths(tmpdir, tweaked_ecs=False, from_prs=None, review_pr=None): +def alt_easyconfig_paths(tmpdir, tweaked_ecs=False, from_prs=None, from_commit=None, review_pr=None): """Obtain alternative paths for easyconfig files.""" # paths where tweaked easyconfigs will be placed, easyconfigs listed on the command line take priority and will be @@ -321,18 +322,20 @@ def alt_easyconfig_paths(tmpdir, tweaked_ecs=False, from_prs=None, review_pr=Non tweaked_ecs_paths = (os.path.join(tmpdir, 'tweaked_easyconfigs'), os.path.join(tmpdir, 'tweaked_dep_easyconfigs')) - # paths where files touched in PRs will be downloaded to, - # which are picked up via 'pr_paths' build option in fetch_files_from_pr - pr_paths = [] + # paths where files touched in commit/PRs will be downloaded to, + # which are picked up via 'extra_ec_paths' build option in fetch_files_from_pr + extra_ec_paths = [] if from_prs: - pr_paths = from_prs[:] - if review_pr and review_pr not in pr_paths: - pr_paths.append(review_pr) + extra_ec_paths = from_prs[:] + if review_pr and review_pr not in extra_ec_paths: + extra_ec_paths.append(review_pr) + if extra_ec_paths: + extra_ec_paths = [os.path.join(tmpdir, 'files_pr%s' % pr) for pr in extra_ec_paths] - if pr_paths: - pr_paths = [os.path.join(tmpdir, 'files_pr%s' % pr) for pr in pr_paths] + if from_commit: + extra_ec_paths.append(os.path.join(tmpdir, 'files_commit_' + from_commit)) - return tweaked_ecs_paths, pr_paths + return tweaked_ecs_paths, extra_ec_paths def det_easyconfig_paths(orig_paths): @@ -346,27 +349,31 @@ def det_easyconfig_paths(orig_paths): except ValueError: raise EasyBuildError("Argument to --from-pr must be a comma separated list of PR #s.") + from_commit = build_option('from_commit') robot_path = build_option('robot_path') # list of specified easyconfig files ec_files = orig_paths[:] + commit_files, pr_files = [], [] if from_prs: - pr_files = [] for pr in from_prs: - # path to where easyconfig files should be downloaded is determined via 'pr_paths' build option, - # which corresponds to the list of PR paths returned by alt_easyconfig_paths + # path to where easyconfig files should be downloaded is determined + # via 'extra_ec_paths' build options, + # which corresponds to the list of commit/PR paths returned by alt_easyconfig_paths pr_files.extend(fetch_easyconfigs_from_pr(pr)) - - if ec_files: - # replace paths for specified easyconfigs that are touched in PR - for i, ec_file in enumerate(ec_files): - for pr_file in pr_files: - if ec_file == os.path.basename(pr_file): - ec_files[i] = pr_file - else: - # if no easyconfigs are specified, use all the ones touched in the PR - ec_files = [path for path in pr_files if path.endswith('.eb')] + elif from_commit: + commit_files = fetch_easyconfigs_from_commit(from_commit, files=ec_files) + + if ec_files: + # replace paths for specified easyconfigs that are touched in commit/PRs + for i, ec_file in enumerate(ec_files): + for file in commit_files + pr_files: + if ec_file == os.path.basename(file): + ec_files[i] = file + else: + # if no easyconfigs are specified, use all the ones touched in the commit/PRs + ec_files = [path for path in commit_files + pr_files if path.endswith('.eb')] filter_ecs = build_option('filter_ecs') if filter_ecs: @@ -701,7 +708,9 @@ def check_sha256_checksums(ecs, whitelist=None): continue eb_class = get_easyblock_class(ec['easyblock'], name=ec['name']) - checksum_issues.extend(eb_class(ec).check_checksums()) + eb = eb_class(ec) + checksum_issues.extend(eb.check_checksums()) + eb.close_log() return checksum_issues @@ -782,7 +791,7 @@ def avail_easyblocks(): return easyblocks -def det_copy_ec_specs(orig_paths, from_pr): +def det_copy_ec_specs(orig_paths, from_pr=None, from_commit=None): """Determine list of paths + target directory for --copy-ec.""" if from_pr is not None and not isinstance(from_pr, list): @@ -846,4 +855,41 @@ def det_copy_ec_specs(orig_paths, from_pr): elif pr_matches: raise EasyBuildError("Found multiple paths for %s in PR: %s", filename, pr_matches) + # consider --from-commit (only if --from-pr was not used) + elif from_commit: + tmpdir = os.path.join(tempfile.gettempdir(), 'fetch_files_from_commit_%s' % from_commit) + commit_paths = fetch_files_from_commit(from_commit, path=tmpdir) + + # assume that files need to be copied to current working directory for now + target_path = os.getcwd() + + if orig_paths: + last_path = orig_paths[-1] + + # check files touched by commit and see if the target directory for --copy-ec + # corresponds to the name of one of these files; + # if so we should copy the specified file(s) to the current working directory, + # since interpreting the last argument as target location is very unlikely to be correct in this case + commit_filenames = [os.path.basename(p) for p in commit_paths] + if last_path in commit_filenames: + paths = orig_paths[:] + else: + target_path = last_path + # exclude last argument that is used as target location + paths = orig_paths[:-1] + + # if list of files to copy is empty at this point, + # we simply copy *all* files touched by the PR + if not paths: + paths = commit_paths + + # replace path for files touched by commit (no need to worry about others) + for idx, path in enumerate(paths): + filename = os.path.basename(path) + commit_matches = [x for x in commit_paths if os.path.basename(x) == filename] + if len(commit_matches) == 1: + paths[idx] = commit_matches[0] + elif commit_matches: + raise EasyBuildError("Found multiple paths for %s in commit: %s", filename, commit_matches) + return paths, target_path diff --git a/easybuild/framework/easyconfig/tweak.py b/easybuild/framework/easyconfig/tweak.py index c3e26ab868..fb01f3a83e 100644 --- a/easybuild/framework/easyconfig/tweak.py +++ b/easybuild/framework/easyconfig/tweak.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -324,7 +324,7 @@ def __repr__(self): newval = "%s + %s" % (fval, res.group('val')) _log.debug("Prepending %s to %s" % (fval, key)) else: - newval = "%s" % fval + newval = str(fval) _log.debug("Overwriting %s with %s" % (key, fval)) ectxt = regexp.sub("%s = %s" % (res.group('key'), newval), ectxt) _log.info("Tweaked %s list to '%s'" % (key, newval)) diff --git a/easybuild/framework/easyconfig/types.py b/easybuild/framework/easyconfig/types.py index 622479f480..42be1b99e4 100644 --- a/easybuild/framework/easyconfig/types.py +++ b/easybuild/framework/easyconfig/types.py @@ -1,5 +1,5 @@ # # -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/easystack.py b/easybuild/framework/easystack.py index 9296c18827..4a0ec15cdd 100644 --- a/easybuild/framework/easystack.py +++ b/easybuild/framework/easystack.py @@ -1,4 +1,4 @@ -# Copyright 2020-2023 Ghent University +# Copyright 2020-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/extension.py b/easybuild/framework/extension.py index ed90f15e6d..56f242ffce 100644 --- a/easybuild/framework/extension.py +++ b/easybuild/framework/extension.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/framework/extensioneasyblock.py b/easybuild/framework/extensioneasyblock.py index 6ad116b20b..69c824fe7e 100644 --- a/easybuild/framework/extensioneasyblock.py +++ b/easybuild/framework/extensioneasyblock.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of the University of Ghent (http://ugent.be/hpc). diff --git a/easybuild/main.py b/easybuild/main.py index 73550e3998..df5f23a460 100644 --- a/easybuild/main.py +++ b/easybuild/main.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -329,15 +329,27 @@ def process_eb_args(eb_args, eb_go, cfg_settings, modtool, testing, init_session if options.copy_ec: # figure out list of files to copy + target location (taking into account --from-pr) - eb_args, target_path = det_copy_ec_specs(eb_args, from_pr_list) + eb_args, target_path = det_copy_ec_specs(eb_args, from_pr=from_pr_list, from_commit=options.from_commit) categorized_paths = categorize_files_by_type(eb_args) + set_pr_options = [opt for opt in ( + 'new_branch_github', + 'new_pr', + 'new_pr_from_branch', + 'preview_pr', + 'sync_branch_with_develop', + 'sync_pr_with_develop', + 'update_branch_github', + 'update_pr', + ) if getattr(options, opt) + ] + any_pr_option_set = len(set_pr_options) > 0 + if len(set_pr_options) > 1: + raise EasyBuildError("The following options are set but incompatible: %s.\nYou can only use one at a time!", + ', '.join(['--' + opt.replace('_', '-') for opt in set_pr_options])) # command line options that do not require any easyconfigs to be specified - pr_options = options.new_branch_github or options.new_pr or options.new_pr_from_branch or options.preview_pr - pr_options = pr_options or options.sync_branch_with_develop or options.sync_pr_with_develop - pr_options = pr_options or options.update_branch_github or options.update_pr - no_ec_opts = [options.aggregate_regtest, options.regtest, pr_options, search_query] + no_ec_opts = [options.aggregate_regtest, options.regtest, any_pr_option_set, search_query] # determine paths to easyconfigs determined_paths = det_easyconfig_paths(categorized_paths['easyconfigs']) @@ -427,9 +439,10 @@ def process_eb_args(eb_args, eb_go, cfg_settings, modtool, testing, init_session forced = options.force or options.rebuild dry_run_mode = options.dry_run or options.dry_run_short or options.missing_modules - keep_available_modules = forced or dry_run_mode or options.extended_dry_run or pr_options or options.copy_ec - keep_available_modules = keep_available_modules or options.inject_checksums or options.sanity_check_only - keep_available_modules = keep_available_modules or options.inject_checksums_to_json + keep_available_modules = any(( + forced, dry_run_mode, options.extended_dry_run, any_pr_option_set, options.copy_ec, options.inject_checksums, + options.sanity_check_only, options.inject_checksums_to_json) + ) # skip modules that are already installed unless forced, or unless an option is used that warrants not skipping if not keep_available_modules: @@ -448,12 +461,12 @@ def process_eb_args(eb_args, eb_go, cfg_settings, modtool, testing, init_session if len(easyconfigs) > 0: # resolve dependencies if robot is enabled, except in dry run mode # one exception: deps *are* resolved with --new-pr or --update-pr when dry run mode is enabled - if options.robot and (not dry_run_mode or pr_options): + if options.robot and (not dry_run_mode or any_pr_option_set): print_msg("resolving dependencies ...", log=_log, silent=testing) ordered_ecs = resolve_dependencies(easyconfigs, modtool) else: ordered_ecs = easyconfigs - elif pr_options: + elif any_pr_option_set: ordered_ecs = None else: print_msg("No easyconfigs left to be built.", log=_log, silent=testing) @@ -472,7 +485,7 @@ def process_eb_args(eb_args, eb_go, cfg_settings, modtool, testing, init_session return True # creating/updating PRs - if pr_options: + if any_pr_option_set: if options.new_pr: new_pr(categorized_paths, ordered_ecs) elif options.new_branch_github: @@ -495,7 +508,7 @@ def process_eb_args(eb_args, eb_go, cfg_settings, modtool, testing, init_session # dry_run: print all easyconfigs and dependencies, and whether they are already built elif dry_run_mode: if options.missing_modules: - txt = missing_deps(easyconfigs, modtool) + txt = missing_deps(easyconfigs, modtool, terse=options.terse) else: txt = dry_run(easyconfigs, modtool, short=not options.dry_run) print_msg(txt, log=_log, silent=testing, prefix=False) @@ -684,7 +697,9 @@ def main(args=None, logfile=None, do_build=None, testing=False, modtool=None, pr options.list_prs, options.merge_pr, options.review_pr, - options.terse, + # --missing-modules is processed by process_eb_args, + # so we can't exit just yet here if it's used in combination with --terse + options.terse and not options.missing_modules, search_query, ] if any(early_stop_options): @@ -721,7 +736,7 @@ def main(args=None, logfile=None, do_build=None, testing=False, modtool=None, pr # stop logging and cleanup tmp log file, unless one build failed (individual logs are located in eb_tmpdir) stop_logging(logfile, logtostdout=options.logtostdout) if do_cleanup: - cleanup(logfile, eb_tmpdir, testing, silent=False) + cleanup(logfile, eb_tmpdir, testing, silent=options.terse) def prepare_main(args=None, logfile=None, testing=None): @@ -736,8 +751,7 @@ def prepare_main(args=None, logfile=None, testing=None): # if $CDPATH is set, unset it, it'll only cause trouble... # see https://github.com/easybuilders/easybuild-framework/issues/2944 - if 'CDPATH' in os.environ: - del os.environ['CDPATH'] + os.environ.pop('CDPATH', None) # When EB is run via `exec` the special bash variable $_ is not set # So emulate this here to allow (module) scripts depending on that to work @@ -752,8 +766,14 @@ def prepare_main(args=None, logfile=None, testing=None): if __name__ == "__main__": - init_session_state, eb_go, cfg_settings = prepare_main() + # take into account that EasyBuildError may be raised when parsing the EasyBuild configuration + try: + init_session_state, eb_go, cfg_settings = prepare_main() + except EasyBuildError as err: + print_error(err.msg) + hooks = load_hooks(eb_go.options.hooks) + try: main(prepared_cfg_data=(init_session_state, eb_go, cfg_settings)) except EasyBuildError as err: diff --git a/easybuild/scripts/bootstrap_eb.py b/easybuild/scripts/bootstrap_eb.py index a74f4fa55e..ef8c281162 100755 --- a/easybuild/scripts/bootstrap_eb.py +++ b/easybuild/scripts/bootstrap_eb.py @@ -1,6 +1,6 @@ #!/usr/bin/env python ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/scripts/clean_gists.py b/easybuild/scripts/clean_gists.py index cb2d6fed04..ec1213e4b3 100755 --- a/easybuild/scripts/clean_gists.py +++ b/easybuild/scripts/clean_gists.py @@ -1,6 +1,6 @@ #!/usr/bin/env python ## -# Copyright 2014 Ward Poelmans +# Copyright 2014-2024 Ward Poelmans # # https://github.com/easybuilders/easybuild # diff --git a/easybuild/scripts/findPythonDeps.py b/easybuild/scripts/findPythonDeps.py index d6e496a048..c3607e47c7 100755 --- a/easybuild/scripts/findPythonDeps.py +++ b/easybuild/scripts/findPythonDeps.py @@ -96,10 +96,13 @@ def get_dep_tree(package_spec, verbose): def find_deps(pkgs, dep_tree): """Recursively resolve dependencies of the given package(s) and return them""" res = [] - for pkg in pkgs: - pkg = canonicalize_name(pkg) + for orig_pkg in pkgs: + pkg = canonicalize_name(orig_pkg) matching_entries = [entry for entry in dep_tree if pkg in (entry['package']['package_name'], entry['package']['key'])] + if not matching_entries: + matching_entries = [entry for entry in dep_tree + if orig_pkg in (entry['package']['package_name'], entry['package']['key'])] if not matching_entries: raise RuntimeError("Found no installed package for '%s' in %s" % (pkg, dep_tree)) if len(matching_entries) > 1: diff --git a/easybuild/scripts/findUpdatedEcs.sh b/easybuild/scripts/findUpdatedEcs.sh index d6631bfe0b..66b7e34bd8 100755 --- a/easybuild/scripts/findUpdatedEcs.sh +++ b/easybuild/scripts/findUpdatedEcs.sh @@ -33,51 +33,57 @@ function checkModule { first_letter=${ec_filename:0:1} letterPath=$easyconfigFolder/${first_letter,,} if [[ -d "$letterPath" ]]; then - ec_new="$(find "$letterPath" -type f -name "$ec_filename")" + ec_new="$(find "$letterPath" -type f -name "$ec_filename")" else - ec_new= + ec_new= fi # Fallback if not found [[ -n "$ec_new" ]] || ec_new="$(find "$easyconfigFolder" -type f -name "$ec_filename")" if [[ -z "$ec_new" ]]; then - printError "=== Did not find new EC $ec_filename" + printError "=== Did not find new EC $ec_filename" elif [[ ! -e "$ec_new" ]]; then printError "=== Found multiple new ECs: $ec_new" - elif ! out=$(diff "$ec_installed" "$ec_new"); then - echo -e "${YELLOW}=== Needs updating: ${GREEN}${ec_installed}${YELLOW} vs ${GREEN}${ec_new}${NC}" - if ((showDiff == 1)); then - echo "$out" + elif ! out=$(diff -u "$ec_installed" "$ec_new"); then + if ((short == 1)); then + basename "$ec_installed" + else + echo -e "${YELLOW}=== Needs updating: ${GREEN}${ec_installed}${YELLOW} vs ${GREEN}${ec_new}${NC}" + if ((showDiff == 1)); then + echo "$out" + fi fi fi } ecDefaultFolder= if path=$(which eb 2>/dev/null); then - path=$(dirname "$path") - for p in "$path" "$(dirname "$path")"; do - if [ -d "$p/easybuild/easyconfigs" ]; then - ecDefaultFolder=$p - break - fi - done + path=$(dirname "$path") + for p in "$path" "$(dirname "$path")"; do + if [ -d "$p/easybuild/easyconfigs" ]; then + ecDefaultFolder=$p + break + fi + done fi function usage { - echo "Usage: $(basename "$0") [--verbose] [--diff] --loaded|--modules INSTALLPATH --easyconfigs EC-FOLDER" - echo - echo "Check installed modules against the source EasyConfig (EC) files to determine which have changed." - echo "Can either check the currently loaded modules or all modules installed in a specific location" - echo - echo "--verbose Verbose status output while checking" - echo "--loaded Check only currently loaded modules" - echo "--diff Show diff of changed module files" - echo "--modules INSTALLPATH Check all modules in the specified (software) installpath, i.e. the root of module-binaries" - echo "--easyconfigs EC-FOLDER Path to the folder containg the current/updated EasyConfigs. ${ecDefaultFolder:+Defaults to $ecDefaultFolder}" - exit 0 + echo "Usage: $(basename "$0") [--verbose] [--diff] --loaded|--modules INSTALLPATH --easyconfigs EC-FOLDER" + echo + echo "Check installed modules against the source EasyConfig (EC) files to determine which have changed." + echo "Can either check the currently loaded modules or all modules installed in a specific location" + echo + echo "--verbose Verbose status output while checking" + echo "--loaded Check only currently loaded modules" + echo "--short Only show filename of changed ECs" + echo "--diff Show diff of changed module files" + echo "--modules INSTALLPATH Check all modules in the specified (software) installpath, i.e. the root of module-binaries" + echo "--easyconfigs EC-FOLDER Path to the folder containg the current/updated EasyConfigs. ${ecDefaultFolder:+Defaults to $ecDefaultFolder}" + exit 0 } checkLoadedModules=0 showDiff=0 +short=0 modulesFolder="" easyconfigFolder=$ecDefaultFolder @@ -89,6 +95,8 @@ while [[ $# -gt 0 ]]; do verbose=1;; -d|--diff) showDiff=1;; + -s|--short) + short=1;; -l|--loaded) checkLoadedModules=1;; -m|--modules) diff --git a/easybuild/scripts/fix_docs.py b/easybuild/scripts/fix_docs.py index 388fb360d9..a14f18caf8 100755 --- a/easybuild/scripts/fix_docs.py +++ b/easybuild/scripts/fix_docs.py @@ -1,6 +1,6 @@ #!/usr/bin/env python ## -# Copyright 2016-2023 Ghent University +# Copyright 2016-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/scripts/install-EasyBuild-develop.sh b/easybuild/scripts/install-EasyBuild-develop.sh index 4181d8c42a..f88ae280a0 100755 --- a/easybuild/scripts/install-EasyBuild-develop.sh +++ b/easybuild/scripts/install-EasyBuild-develop.sh @@ -14,7 +14,7 @@ print_usage() echo echo " github_username: username on GitHub for which the EasyBuild repositories should be cloned" echo - echo " install_dir: directory were all the EasyBuild files will be installed" + echo " install_dir: directory where all the EasyBuild files will be installed" echo } @@ -79,7 +79,7 @@ EOF # Check for 'help' argument -if [ "$1" = "-h" -o "$1" = "--help" ] ; then +if [ "$1" = "-h" ] || [ "$1" = "--help" ] ; then print_usage exit 0 fi @@ -116,13 +116,14 @@ github_clone_branch "easybuild" "develop" EB_DEVEL_MODULE_NAME="EasyBuild-develop" MODULES_INSTALL_DIR=${INSTALL_DIR}/modules EB_DEVEL_MODULE="${MODULES_INSTALL_DIR}/${EB_DEVEL_MODULE_NAME}" -mkdir -p ${MODULES_INSTALL_DIR} +mkdir -p "${MODULES_INSTALL_DIR}" print_devel_module > "${EB_DEVEL_MODULE}" -echo +echo echo "=== Run 'module use ${MODULES_INSTALL_DIR}' and 'module load ${EB_DEVEL_MODULE_NAME}' to use your development version of EasyBuild." echo "=== (you can append ${MODULES_INSTALL_DIR} to your MODULEPATH to make this module always available for loading)" echo echo "=== To update each repository, run 'git pull origin' in each subdirectory of ${INSTALL_DIR}" +echo "=== Or run $(dirname "$0")/update-EasyBuild-develop.sh '${INSTALL_DIR}'" echo exit 0 diff --git a/easybuild/scripts/mk_tmpl_easyblock_for.py b/easybuild/scripts/mk_tmpl_easyblock_for.py index c5c7c0110a..f6958572fa 100755 --- a/easybuild/scripts/mk_tmpl_easyblock_for.py +++ b/easybuild/scripts/mk_tmpl_easyblock_for.py @@ -1,6 +1,6 @@ #!/usr/bin/env python ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/scripts/rpath_args.py b/easybuild/scripts/rpath_args.py index 1bc87a1679..b477aa63d8 100755 --- a/easybuild/scripts/rpath_args.py +++ b/easybuild/scripts/rpath_args.py @@ -1,6 +1,6 @@ #!/usr/bin/env python ## -# Copyright 2016-2023 Ghent University +# Copyright 2016-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/scripts/rpath_wrapper_template.sh.in b/easybuild/scripts/rpath_wrapper_template.sh.in index 55c3388c5b..44a5aac43a 100644 --- a/easybuild/scripts/rpath_wrapper_template.sh.in +++ b/easybuild/scripts/rpath_wrapper_template.sh.in @@ -1,6 +1,6 @@ #!/bin/bash ## -# Copyright 2016-2023 Ghent University +# Copyright 2016-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/scripts/update-EasyBuild-develop.sh b/easybuild/scripts/update-EasyBuild-develop.sh new file mode 100755 index 0000000000..c80289ad96 --- /dev/null +++ b/easybuild/scripts/update-EasyBuild-develop.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash + +# Stop in case of error +set -e + +# Print script help +print_usage() +{ + echo "Checkout develop branch of all EasyBuild repositories" + echo "and pull changes from the remote repository." + echo "To be used with the EasyBuild-develop module or a set git-working-dirs-path" + echo "Usage: $0 []" + echo + echo " git_dir: directory where all the EasyBuild repositories are installed." + echo " Automatically detected if not specified." + echo +} + +if [[ "$1" = "-h" ]] || [[ "$1" = "--help" ]]; then + print_usage + exit 0 +fi + +if [[ $# -gt 1 ]] ; then + echo "Error: invalid arguments" + echo + print_usage + exit 1 +fi + +if [[ $# -eq 1 ]]; then + git_dir=$1 +else + # Auto detect git_dir + git_dir="" + if ! which eb &> /dev/null; then + module load EasyBuild-develop || module load EasyBuild || true + if ! which eb &> /dev/null; then + echo 'Found neither the `eb` command nor a working module.' + echo 'Please specify the git_dir!' + exit 1 + fi + fi + if out=$(eb --show-config | grep -F 'git-working-dirs-path'); then + path=$(echo "$out" | awk '{print $NF}') + if [[ -n "$path" ]] && [[ -d "$path" ]]; then + git_dir=$path + echo "Using git_dir from git-working-dirs-path: $git_dir" + fi + fi + if [[ -z "$git_dir" ]]; then + eb_dir=$(dirname "$(which eb)") + if [[ "$(basename "$eb_dir")" == "easybuild-framework" ]] && [[ -d "$eb_dir/.git" ]]; then + git_dir=$(dirname "$eb_dir") + echo "Using git_dir from eb command: $git_dir" + else + echo 'Please specify the git_dir as auto-detection failed!' + exit 1 + fi + fi +fi + +cd "$git_dir" + +for folder in easybuild easybuild-framework easybuild-easyblocks easybuild-easyconfigs; do + echo # A newline + if [[ -d "$folder" ]]; then + echo "========= Checking ${folder} =========" + else + echo "========= Skipping non-existent ${folder} =========" + fi + cd "$folder" + git checkout "develop" + if git remote | grep -qF github_easybuilders; then + git pull "github_easybuilders" + else + git pull + fi + cd .. +done + +index_file="$git_dir/easybuild-easyconfigs/easybuild/easyconfigs/.eb-path-index" +if [[ -f "$index_file" ]]; then + echo -n "Trying to remove index from ${index_file}..." + if rm "$index_file"; then + echo "Done!" + echo "Recreate with 'eb --create-index \"$(dirname "$index_file")\"'" + else + echo "Failed!" + fi +fi diff --git a/easybuild/toolchains/__init__.py b/easybuild/toolchains/__init__.py index 309b1808cf..2f468f2812 100644 --- a/easybuild/toolchains/__init__.py +++ b/easybuild/toolchains/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/cgmpich.py b/easybuild/toolchains/cgmpich.py index ea04e20e75..9e25c6ec57 100644 --- a/easybuild/toolchains/cgmpich.py +++ b/easybuild/toolchains/cgmpich.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/cgmpolf.py b/easybuild/toolchains/cgmpolf.py index b335781374..5629ee5be3 100644 --- a/easybuild/toolchains/cgmpolf.py +++ b/easybuild/toolchains/cgmpolf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/cgmvapich2.py b/easybuild/toolchains/cgmvapich2.py index e347cab483..76e306b12d 100644 --- a/easybuild/toolchains/cgmvapich2.py +++ b/easybuild/toolchains/cgmvapich2.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/cgmvolf.py b/easybuild/toolchains/cgmvolf.py index 1b9e122fcd..e68aa90fe1 100644 --- a/easybuild/toolchains/cgmvolf.py +++ b/easybuild/toolchains/cgmvolf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/cgompi.py b/easybuild/toolchains/cgompi.py index 559f91f4ad..9b9267bf78 100644 --- a/easybuild/toolchains/cgompi.py +++ b/easybuild/toolchains/cgompi.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/cgoolf.py b/easybuild/toolchains/cgoolf.py index c26e94b724..8e2ea8503e 100644 --- a/easybuild/toolchains/cgoolf.py +++ b/easybuild/toolchains/cgoolf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/clanggcc.py b/easybuild/toolchains/clanggcc.py index 8537354ebe..c1e09e68ef 100644 --- a/easybuild/toolchains/clanggcc.py +++ b/easybuild/toolchains/clanggcc.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/compiler/__init__.py b/easybuild/toolchains/compiler/__init__.py index 5933777f43..9c1ba469c5 100644 --- a/easybuild/toolchains/compiler/__init__.py +++ b/easybuild/toolchains/compiler/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/compiler/clang.py b/easybuild/toolchains/compiler/clang.py index 303f0ed0e4..8b7b16e8e3 100644 --- a/easybuild/toolchains/compiler/clang.py +++ b/easybuild/toolchains/compiler/clang.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. @@ -98,6 +98,7 @@ class Clang(Compiler): } # used with --optarch=GENERIC COMPILER_GENERIC_OPTION = { + (systemtools.RISCV64, systemtools.RISCV): 'march=rv64gc -mabi=lp64d', # default for -mabi is system-dependent (systemtools.X86_64, systemtools.AMD): 'march=x86-64 -mtune=generic', (systemtools.X86_64, systemtools.INTEL): 'march=x86-64 -mtune=generic', } diff --git a/easybuild/toolchains/compiler/craype.py b/easybuild/toolchains/compiler/craype.py index a0bec9f624..73b6a103e2 100644 --- a/easybuild/toolchains/compiler/craype.py +++ b/easybuild/toolchains/compiler/craype.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/compiler/cuda.py b/easybuild/toolchains/compiler/cuda.py index c87f1b21d1..3fd3d705f1 100644 --- a/easybuild/toolchains/compiler/cuda.py +++ b/easybuild/toolchains/compiler/cuda.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/compiler/dummycompiler.py b/easybuild/toolchains/compiler/dummycompiler.py index 767dcb66c5..d74c2e873e 100644 --- a/easybuild/toolchains/compiler/dummycompiler.py +++ b/easybuild/toolchains/compiler/dummycompiler.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/compiler/fujitsu.py b/easybuild/toolchains/compiler/fujitsu.py index e7a861c1b7..437ec34048 100644 --- a/easybuild/toolchains/compiler/fujitsu.py +++ b/easybuild/toolchains/compiler/fujitsu.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/compiler/gcc.py b/easybuild/toolchains/compiler/gcc.py index 3fba8d3954..548ac41187 100644 --- a/easybuild/toolchains/compiler/gcc.py +++ b/easybuild/toolchains/compiler/gcc.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -94,6 +94,7 @@ class Gcc(Compiler): (systemtools.AARCH64, systemtools.ARM): 'mcpu=generic', # implies -march=armv8-a and -mtune=generic (systemtools.POWER, systemtools.POWER): 'mcpu=powerpc64', # no support for -march on POWER (systemtools.POWER, systemtools.POWER_LE): 'mcpu=powerpc64le', # no support for -march on POWER + (systemtools.RISCV64, systemtools.RISCV): 'march=rv64gc -mabi=lp64d', # default for -mabi is system-dependent (systemtools.X86_64, systemtools.AMD): 'march=x86-64 -mtune=generic', (systemtools.X86_64, systemtools.INTEL): 'march=x86-64 -mtune=generic', } diff --git a/easybuild/toolchains/compiler/intel_compilers.py b/easybuild/toolchains/compiler/intel_compilers.py index ae97dfa87d..1a21b21943 100644 --- a/easybuild/toolchains/compiler/intel_compilers.py +++ b/easybuild/toolchains/compiler/intel_compilers.py @@ -1,5 +1,5 @@ ## -# Copyright 2021-2023 Ghent University +# Copyright 2021-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/compiler/inteliccifort.py b/easybuild/toolchains/compiler/inteliccifort.py index c498f544d7..01015a0d83 100644 --- a/easybuild/toolchains/compiler/inteliccifort.py +++ b/easybuild/toolchains/compiler/inteliccifort.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/compiler/nvhpc.py b/easybuild/toolchains/compiler/nvhpc.py index 549c0e9a70..2011137716 100644 --- a/easybuild/toolchains/compiler/nvhpc.py +++ b/easybuild/toolchains/compiler/nvhpc.py @@ -1,5 +1,5 @@ ## -# Copyright 2015 Bart Oldeman +# Copyright 2015-2024 Bart Oldeman # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/compiler/pgi.py b/easybuild/toolchains/compiler/pgi.py index 77f04fe813..0f55614926 100644 --- a/easybuild/toolchains/compiler/pgi.py +++ b/easybuild/toolchains/compiler/pgi.py @@ -1,5 +1,5 @@ ## -# Copyright 2015 Bart Oldeman +# Copyright 2015-2024 Bart Oldeman # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/compiler/systemcompiler.py b/easybuild/toolchains/compiler/systemcompiler.py index 505f002d57..d1fd06d4d9 100644 --- a/easybuild/toolchains/compiler/systemcompiler.py +++ b/easybuild/toolchains/compiler/systemcompiler.py @@ -1,5 +1,5 @@ ## -# Copyright 2019-2023 Ghent University +# Copyright 2019-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/craycce.py b/easybuild/toolchains/craycce.py index cb9a4ff80e..13b92e55d2 100644 --- a/easybuild/toolchains/craycce.py +++ b/easybuild/toolchains/craycce.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/craygnu.py b/easybuild/toolchains/craygnu.py index 4e42d32f94..8d198362bd 100644 --- a/easybuild/toolchains/craygnu.py +++ b/easybuild/toolchains/craygnu.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/crayintel.py b/easybuild/toolchains/crayintel.py index 76cde0a8bc..5997eb63d6 100644 --- a/easybuild/toolchains/crayintel.py +++ b/easybuild/toolchains/crayintel.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/craypgi.py b/easybuild/toolchains/craypgi.py index 67e2bcec78..49004775a4 100644 --- a/easybuild/toolchains/craypgi.py +++ b/easybuild/toolchains/craypgi.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/dummy.py b/easybuild/toolchains/dummy.py index cb2a988bd0..f29f6736ae 100644 --- a/easybuild/toolchains/dummy.py +++ b/easybuild/toolchains/dummy.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/fcc.py b/easybuild/toolchains/fcc.py index 905835e3cf..bc99335c48 100644 --- a/easybuild/toolchains/fcc.py +++ b/easybuild/toolchains/fcc.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/ffmpi.py b/easybuild/toolchains/ffmpi.py index 34a56d229e..71a49f7913 100644 --- a/easybuild/toolchains/ffmpi.py +++ b/easybuild/toolchains/ffmpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/fft/__init__.py b/easybuild/toolchains/fft/__init__.py index 9915268575..afcf0211dd 100644 --- a/easybuild/toolchains/fft/__init__.py +++ b/easybuild/toolchains/fft/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/fft/fftw.py b/easybuild/toolchains/fft/fftw.py index 63d39cb658..9cb4c4e851 100644 --- a/easybuild/toolchains/fft/fftw.py +++ b/easybuild/toolchains/fft/fftw.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/fft/fujitsufftw.py b/easybuild/toolchains/fft/fujitsufftw.py index 1e2ed28ec6..4de1769528 100644 --- a/easybuild/toolchains/fft/fujitsufftw.py +++ b/easybuild/toolchains/fft/fujitsufftw.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/fft/intelfftw.py b/easybuild/toolchains/fft/intelfftw.py index ad8f08ffd8..7882278a91 100644 --- a/easybuild/toolchains/fft/intelfftw.py +++ b/easybuild/toolchains/fft/intelfftw.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/foss.py b/easybuild/toolchains/foss.py index d5e57956a0..031daa4c9c 100644 --- a/easybuild/toolchains/foss.py +++ b/easybuild/toolchains/foss.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/fosscuda.py b/easybuild/toolchains/fosscuda.py index a35c570781..9465515d36 100644 --- a/easybuild/toolchains/fosscuda.py +++ b/easybuild/toolchains/fosscuda.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/fujitsu.py b/easybuild/toolchains/fujitsu.py index ed858a84c7..707255e03c 100644 --- a/easybuild/toolchains/fujitsu.py +++ b/easybuild/toolchains/fujitsu.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gcc.py b/easybuild/toolchains/gcc.py index e359b8aa01..71091e795c 100644 --- a/easybuild/toolchains/gcc.py +++ b/easybuild/toolchains/gcc.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gcccore.py b/easybuild/toolchains/gcccore.py index 87eaf4d1b6..ce4703e89c 100644 --- a/easybuild/toolchains/gcccore.py +++ b/easybuild/toolchains/gcccore.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gcccuda.py b/easybuild/toolchains/gcccuda.py index fcf0981bac..47ab250824 100644 --- a/easybuild/toolchains/gcccuda.py +++ b/easybuild/toolchains/gcccuda.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gfbf.py b/easybuild/toolchains/gfbf.py index 9a7f279e6d..d41f5b7d06 100644 --- a/easybuild/toolchains/gfbf.py +++ b/easybuild/toolchains/gfbf.py @@ -1,5 +1,5 @@ ## -# Copyright 2021-2023 Ghent University +# Copyright 2021-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gimkl.py b/easybuild/toolchains/gimkl.py index 8505cf5b87..1d7b9704f6 100644 --- a/easybuild/toolchains/gimkl.py +++ b/easybuild/toolchains/gimkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gimpi.py b/easybuild/toolchains/gimpi.py index 6ac9788749..76e6bd638a 100644 --- a/easybuild/toolchains/gimpi.py +++ b/easybuild/toolchains/gimpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gimpic.py b/easybuild/toolchains/gimpic.py index 01a28c78ee..dde1d6c8f8 100644 --- a/easybuild/toolchains/gimpic.py +++ b/easybuild/toolchains/gimpic.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/giolf.py b/easybuild/toolchains/giolf.py index 64b99f2a5c..121c81121b 100644 --- a/easybuild/toolchains/giolf.py +++ b/easybuild/toolchains/giolf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/giolfc.py b/easybuild/toolchains/giolfc.py index 3ca3111542..df798626aa 100644 --- a/easybuild/toolchains/giolfc.py +++ b/easybuild/toolchains/giolfc.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gmacml.py b/easybuild/toolchains/gmacml.py index 5561f85286..ee95c3f7f3 100644 --- a/easybuild/toolchains/gmacml.py +++ b/easybuild/toolchains/gmacml.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gmkl.py b/easybuild/toolchains/gmkl.py index a58a05c488..67e33e1e62 100644 --- a/easybuild/toolchains/gmkl.py +++ b/easybuild/toolchains/gmkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gmklc.py b/easybuild/toolchains/gmklc.py index b7ecd19115..bead896d5e 100644 --- a/easybuild/toolchains/gmklc.py +++ b/easybuild/toolchains/gmklc.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gmpich.py b/easybuild/toolchains/gmpich.py index 941421e50e..66d2b29123 100644 --- a/easybuild/toolchains/gmpich.py +++ b/easybuild/toolchains/gmpich.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gmpich2.py b/easybuild/toolchains/gmpich2.py index bad4e0bbaf..f734d3cb56 100644 --- a/easybuild/toolchains/gmpich2.py +++ b/easybuild/toolchains/gmpich2.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gmpit.py b/easybuild/toolchains/gmpit.py index 395940a639..a39baf934d 100644 --- a/easybuild/toolchains/gmpit.py +++ b/easybuild/toolchains/gmpit.py @@ -1,5 +1,5 @@ ## -# Copyright 2022-2023 Ghent University +# Copyright 2022-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gmpolf.py b/easybuild/toolchains/gmpolf.py index 2bca2b44dd..c5a8be97d9 100644 --- a/easybuild/toolchains/gmpolf.py +++ b/easybuild/toolchains/gmpolf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/gmvapich2.py b/easybuild/toolchains/gmvapich2.py index 46ebb4d489..26aa6ad73e 100644 --- a/easybuild/toolchains/gmvapich2.py +++ b/easybuild/toolchains/gmvapich2.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gmvolf.py b/easybuild/toolchains/gmvolf.py index 50c943cde6..613d8a6ed3 100644 --- a/easybuild/toolchains/gmvolf.py +++ b/easybuild/toolchains/gmvolf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/gnu.py b/easybuild/toolchains/gnu.py index a16eed38bd..84b06af535 100644 --- a/easybuild/toolchains/gnu.py +++ b/easybuild/toolchains/gnu.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/goalf.py b/easybuild/toolchains/goalf.py index d833e3c1c5..db1280907b 100644 --- a/easybuild/toolchains/goalf.py +++ b/easybuild/toolchains/goalf.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gobff.py b/easybuild/toolchains/gobff.py index 2cbb366dfe..9df26ff706 100644 --- a/easybuild/toolchains/gobff.py +++ b/easybuild/toolchains/gobff.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/goblf.py b/easybuild/toolchains/goblf.py index 618d813149..63e7c0c0a4 100644 --- a/easybuild/toolchains/goblf.py +++ b/easybuild/toolchains/goblf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gofbf.py b/easybuild/toolchains/gofbf.py index 71269a57df..3128c87091 100644 --- a/easybuild/toolchains/gofbf.py +++ b/easybuild/toolchains/gofbf.py @@ -1,5 +1,5 @@ ## -# Copyright 2021-2023 Ghent University +# Copyright 2021-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/golf.py b/easybuild/toolchains/golf.py index c318ec9fee..6d046413a8 100644 --- a/easybuild/toolchains/golf.py +++ b/easybuild/toolchains/golf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/golfc.py b/easybuild/toolchains/golfc.py index bdce5ddcec..3b99dce5c0 100644 --- a/easybuild/toolchains/golfc.py +++ b/easybuild/toolchains/golfc.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gomkl.py b/easybuild/toolchains/gomkl.py index 663bc32daa..ba93882a1b 100644 --- a/easybuild/toolchains/gomkl.py +++ b/easybuild/toolchains/gomkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gomklc.py b/easybuild/toolchains/gomklc.py index fa19da4b50..95620d8360 100644 --- a/easybuild/toolchains/gomklc.py +++ b/easybuild/toolchains/gomklc.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gompi.py b/easybuild/toolchains/gompi.py index 35db8a8330..7af87123c9 100644 --- a/easybuild/toolchains/gompi.py +++ b/easybuild/toolchains/gompi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gompic.py b/easybuild/toolchains/gompic.py index a9f08dcf2a..0beb2b4d10 100644 --- a/easybuild/toolchains/gompic.py +++ b/easybuild/toolchains/gompic.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/goolf.py b/easybuild/toolchains/goolf.py index 6577cb31c4..099f7bc11a 100644 --- a/easybuild/toolchains/goolf.py +++ b/easybuild/toolchains/goolf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/goolfc.py b/easybuild/toolchains/goolfc.py index 26cd18ec9b..76cf4db890 100644 --- a/easybuild/toolchains/goolfc.py +++ b/easybuild/toolchains/goolfc.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gpsmpi.py b/easybuild/toolchains/gpsmpi.py index c6a7fd04b8..529d17dc5e 100644 --- a/easybuild/toolchains/gpsmpi.py +++ b/easybuild/toolchains/gpsmpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gpsolf.py b/easybuild/toolchains/gpsolf.py index 1414178019..e87f3a5de7 100644 --- a/easybuild/toolchains/gpsolf.py +++ b/easybuild/toolchains/gpsolf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/gqacml.py b/easybuild/toolchains/gqacml.py index 5533bd1f3a..7456b4011e 100644 --- a/easybuild/toolchains/gqacml.py +++ b/easybuild/toolchains/gqacml.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gsmpi.py b/easybuild/toolchains/gsmpi.py index 865dbc813b..68f1a6d0f0 100644 --- a/easybuild/toolchains/gsmpi.py +++ b/easybuild/toolchains/gsmpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/gsolf.py b/easybuild/toolchains/gsolf.py index 5d30493bb1..cb917ca7d3 100644 --- a/easybuild/toolchains/gsolf.py +++ b/easybuild/toolchains/gsolf.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iccifort.py b/easybuild/toolchains/iccifort.py index d1b6804a93..38ec224a5b 100644 --- a/easybuild/toolchains/iccifort.py +++ b/easybuild/toolchains/iccifort.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iccifortcuda.py b/easybuild/toolchains/iccifortcuda.py index 5f024dc8ce..149cfc8e39 100644 --- a/easybuild/toolchains/iccifortcuda.py +++ b/easybuild/toolchains/iccifortcuda.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/ictce.py b/easybuild/toolchains/ictce.py index 265f249306..2055346b37 100644 --- a/easybuild/toolchains/ictce.py +++ b/easybuild/toolchains/ictce.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/ifbf.py b/easybuild/toolchains/ifbf.py index 3507e1eab9..9f689279cb 100644 --- a/easybuild/toolchains/ifbf.py +++ b/easybuild/toolchains/ifbf.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iibff.py b/easybuild/toolchains/iibff.py index 9fe2b2b0c8..07a6b1e567 100644 --- a/easybuild/toolchains/iibff.py +++ b/easybuild/toolchains/iibff.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iimkl.py b/easybuild/toolchains/iimkl.py index 9d3d6a97f3..605445cc5c 100644 --- a/easybuild/toolchains/iimkl.py +++ b/easybuild/toolchains/iimkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iimklc.py b/easybuild/toolchains/iimklc.py index e9508c95ad..89325c2e67 100644 --- a/easybuild/toolchains/iimklc.py +++ b/easybuild/toolchains/iimklc.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iimpi.py b/easybuild/toolchains/iimpi.py index 00d9745a42..9337365ec6 100644 --- a/easybuild/toolchains/iimpi.py +++ b/easybuild/toolchains/iimpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iimpic.py b/easybuild/toolchains/iimpic.py index 53ca437150..45a8df3804 100644 --- a/easybuild/toolchains/iimpic.py +++ b/easybuild/toolchains/iimpic.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iiqmpi.py b/easybuild/toolchains/iiqmpi.py index aee09bb658..5ff1466ff3 100644 --- a/easybuild/toolchains/iiqmpi.py +++ b/easybuild/toolchains/iiqmpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/impich.py b/easybuild/toolchains/impich.py index 2b7fba07f9..7feda33805 100644 --- a/easybuild/toolchains/impich.py +++ b/easybuild/toolchains/impich.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/impmkl.py b/easybuild/toolchains/impmkl.py index 1653b31d5c..952bff34ce 100644 --- a/easybuild/toolchains/impmkl.py +++ b/easybuild/toolchains/impmkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/intel-para.py b/easybuild/toolchains/intel-para.py index a9d4ca0313..ddfee3aaae 100644 --- a/easybuild/toolchains/intel-para.py +++ b/easybuild/toolchains/intel-para.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/intel.py b/easybuild/toolchains/intel.py index 7dd625588f..659b05faf2 100644 --- a/easybuild/toolchains/intel.py +++ b/easybuild/toolchains/intel.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/intel_compilers.py b/easybuild/toolchains/intel_compilers.py index ab5de03386..27fdfbebfd 100644 --- a/easybuild/toolchains/intel_compilers.py +++ b/easybuild/toolchains/intel_compilers.py @@ -1,5 +1,5 @@ ## -# Copyright 2021-2023 Ghent University +# Copyright 2021-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/intelcuda.py b/easybuild/toolchains/intelcuda.py index 343715e43b..bdd59abaab 100644 --- a/easybuild/toolchains/intelcuda.py +++ b/easybuild/toolchains/intelcuda.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iofbf.py b/easybuild/toolchains/iofbf.py index 3410ffaf9f..cd3313d600 100644 --- a/easybuild/toolchains/iofbf.py +++ b/easybuild/toolchains/iofbf.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iomkl.py b/easybuild/toolchains/iomkl.py index cefe83c3b1..033277919c 100644 --- a/easybuild/toolchains/iomkl.py +++ b/easybuild/toolchains/iomkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iomklc.py b/easybuild/toolchains/iomklc.py index 102fa7a311..f40cd78e16 100644 --- a/easybuild/toolchains/iomklc.py +++ b/easybuild/toolchains/iomklc.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iompi.py b/easybuild/toolchains/iompi.py index 318db78481..b578c45892 100644 --- a/easybuild/toolchains/iompi.py +++ b/easybuild/toolchains/iompi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iompic.py b/easybuild/toolchains/iompic.py index 1bcb2eac71..5b675f5621 100644 --- a/easybuild/toolchains/iompic.py +++ b/easybuild/toolchains/iompic.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/ipsmpi.py b/easybuild/toolchains/ipsmpi.py index 1a381414c3..a8a772adcb 100644 --- a/easybuild/toolchains/ipsmpi.py +++ b/easybuild/toolchains/ipsmpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/iqacml.py b/easybuild/toolchains/iqacml.py index fc63968583..e4c5476cd4 100644 --- a/easybuild/toolchains/iqacml.py +++ b/easybuild/toolchains/iqacml.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/ismkl.py b/easybuild/toolchains/ismkl.py index 90ff100eeb..4ccdc87054 100644 --- a/easybuild/toolchains/ismkl.py +++ b/easybuild/toolchains/ismkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/__init__.py b/easybuild/toolchains/linalg/__init__.py index 152bae1e3d..90cdb068a8 100644 --- a/easybuild/toolchains/linalg/__init__.py +++ b/easybuild/toolchains/linalg/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/acml.py b/easybuild/toolchains/linalg/acml.py index b9e25b311d..268e3b0cc2 100644 --- a/easybuild/toolchains/linalg/acml.py +++ b/easybuild/toolchains/linalg/acml.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/atlas.py b/easybuild/toolchains/linalg/atlas.py index 4d53f5bd32..bc894bb108 100644 --- a/easybuild/toolchains/linalg/atlas.py +++ b/easybuild/toolchains/linalg/atlas.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/blacs.py b/easybuild/toolchains/linalg/blacs.py index a3963e9daa..201681c51f 100644 --- a/easybuild/toolchains/linalg/blacs.py +++ b/easybuild/toolchains/linalg/blacs.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/blis.py b/easybuild/toolchains/linalg/blis.py index fa607d0527..d89f3b8d83 100644 --- a/easybuild/toolchains/linalg/blis.py +++ b/easybuild/toolchains/linalg/blis.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/flame.py b/easybuild/toolchains/linalg/flame.py index 78ac8f1ca4..5f6f5cfe87 100644 --- a/easybuild/toolchains/linalg/flame.py +++ b/easybuild/toolchains/linalg/flame.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/flexiblas.py b/easybuild/toolchains/linalg/flexiblas.py index c266aff248..0e88c1a9b2 100644 --- a/easybuild/toolchains/linalg/flexiblas.py +++ b/easybuild/toolchains/linalg/flexiblas.py @@ -1,5 +1,5 @@ ## -# Copyright 2021-2023 Ghent University +# Copyright 2021-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/fujitsussl.py b/easybuild/toolchains/linalg/fujitsussl.py index ecaff56683..dde792455b 100644 --- a/easybuild/toolchains/linalg/fujitsussl.py +++ b/easybuild/toolchains/linalg/fujitsussl.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/gotoblas.py b/easybuild/toolchains/linalg/gotoblas.py index 17d98413a8..e8a99a651a 100644 --- a/easybuild/toolchains/linalg/gotoblas.py +++ b/easybuild/toolchains/linalg/gotoblas.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/intelmkl.py b/easybuild/toolchains/linalg/intelmkl.py index 201355be46..8a32d684d9 100644 --- a/easybuild/toolchains/linalg/intelmkl.py +++ b/easybuild/toolchains/linalg/intelmkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/lapack.py b/easybuild/toolchains/linalg/lapack.py index e9821a659d..e26c9e2961 100644 --- a/easybuild/toolchains/linalg/lapack.py +++ b/easybuild/toolchains/linalg/lapack.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/libsci.py b/easybuild/toolchains/linalg/libsci.py index 87c42116f5..07ea64ed82 100644 --- a/easybuild/toolchains/linalg/libsci.py +++ b/easybuild/toolchains/linalg/libsci.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/openblas.py b/easybuild/toolchains/linalg/openblas.py index e28d4f7dd2..18118d1f01 100644 --- a/easybuild/toolchains/linalg/openblas.py +++ b/easybuild/toolchains/linalg/openblas.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/linalg/scalapack.py b/easybuild/toolchains/linalg/scalapack.py index ef4d24ef30..980e3bfdab 100644 --- a/easybuild/toolchains/linalg/scalapack.py +++ b/easybuild/toolchains/linalg/scalapack.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/mpi/__init__.py b/easybuild/toolchains/mpi/__init__.py index aea95e9051..c5abd0f595 100644 --- a/easybuild/toolchains/mpi/__init__.py +++ b/easybuild/toolchains/mpi/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/mpi/craympich.py b/easybuild/toolchains/mpi/craympich.py index 4c62c45519..8eab736d82 100644 --- a/easybuild/toolchains/mpi/craympich.py +++ b/easybuild/toolchains/mpi/craympich.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -53,7 +53,7 @@ class CrayMPICH(Mpi): MPI_COMPILER_MPIFC = CrayPECompiler.COMPILER_FC # no MPI wrappers, so no need to specify serial compiler - MPI_SHARED_OPTION_MAP = dict([('_opt_%s' % var, '') for var, _ in MPI_COMPILER_VARIABLES]) + MPI_SHARED_OPTION_MAP = {'_opt_%s' % var: '' for var, _ in MPI_COMPILER_VARIABLES} def _set_mpi_compiler_variables(self): """Set the MPI compiler variables""" diff --git a/easybuild/toolchains/mpi/fujitsumpi.py b/easybuild/toolchains/mpi/fujitsumpi.py index f81e1d66f0..ad65c463cf 100644 --- a/easybuild/toolchains/mpi/fujitsumpi.py +++ b/easybuild/toolchains/mpi/fujitsumpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -45,7 +45,7 @@ class FujitsuMPI(Mpi): MPI_TYPE = TC_CONSTANT_MPI_TYPE_OPENMPI # OpenMPI reads from CC etc env variables - MPI_SHARED_OPTION_MAP = dict([('_opt_%s' % var, '') for var, _ in MPI_COMPILER_VARIABLES]) + MPI_SHARED_OPTION_MAP = {'_opt_%s' % var: '' for var, _ in MPI_COMPILER_VARIABLES} MPI_LINK_INFO_OPTION = '-showme:link' diff --git a/easybuild/toolchains/mpi/intelmpi.py b/easybuild/toolchains/mpi/intelmpi.py index 6b9f86430a..8bc67fe788 100644 --- a/easybuild/toolchains/mpi/intelmpi.py +++ b/easybuild/toolchains/mpi/intelmpi.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/mpi/mpich.py b/easybuild/toolchains/mpi/mpich.py index b0c42e57d8..7a067a0d37 100644 --- a/easybuild/toolchains/mpi/mpich.py +++ b/easybuild/toolchains/mpi/mpich.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -56,7 +56,7 @@ class Mpich(Mpi): MPI_COMPILER_MPIFC = None # clear MPI wrapper command options - MPI_SHARED_OPTION_MAP = dict([('_opt_%s' % var, '') for var, _ in MPI_COMPILER_VARIABLES]) + MPI_SHARED_OPTION_MAP = {'_opt_%s' % var: '' for var, _ in MPI_COMPILER_VARIABLES} def _set_mpi_compiler_variables(self): """Set the MPICH_{CC, CXX, F77, F90, FC} variables.""" diff --git a/easybuild/toolchains/mpi/mpich2.py b/easybuild/toolchains/mpi/mpich2.py index bd85d30532..b6f1f6f082 100644 --- a/easybuild/toolchains/mpi/mpich2.py +++ b/easybuild/toolchains/mpi/mpich2.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/mpi/mpitrampoline.py b/easybuild/toolchains/mpi/mpitrampoline.py index 5af054661c..43202b59d3 100644 --- a/easybuild/toolchains/mpi/mpitrampoline.py +++ b/easybuild/toolchains/mpi/mpitrampoline.py @@ -1,5 +1,5 @@ ## -# Copyright 2022-2023 Ghent University +# Copyright 2022-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -53,7 +53,7 @@ class MPItrampoline(Mpi): MPI_COMPILER_MPIFC = None # MPItrampoline reads from CC etc env variables - MPI_SHARED_OPTION_MAP = dict([('_opt_%s' % var, '') for var, _ in MPI_COMPILER_VARIABLES]) + MPI_SHARED_OPTION_MAP = {'_opt_%s' % var: '' for var, _ in MPI_COMPILER_VARIABLES} MPI_LINK_INFO_OPTION = '-showme:link' diff --git a/easybuild/toolchains/mpi/mvapich2.py b/easybuild/toolchains/mpi/mvapich2.py index afb2602f44..4f69c970f5 100644 --- a/easybuild/toolchains/mpi/mvapich2.py +++ b/easybuild/toolchains/mpi/mvapich2.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/mpi/openmpi.py b/easybuild/toolchains/mpi/openmpi.py index 630262f48b..91d10923e7 100644 --- a/easybuild/toolchains/mpi/openmpi.py +++ b/easybuild/toolchains/mpi/openmpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -61,7 +61,7 @@ class OpenMPI(Mpi): MPI_COMPILER_MPIFC = None # OpenMPI reads from CC etc env variables - MPI_SHARED_OPTION_MAP = dict([('_opt_%s' % var, '') for var, _ in MPI_COMPILER_VARIABLES]) + MPI_SHARED_OPTION_MAP = {'_opt_%s' % var: '' for var, _ in MPI_COMPILER_VARIABLES} MPI_LINK_INFO_OPTION = '-showme:link' diff --git a/easybuild/toolchains/mpi/psmpi.py b/easybuild/toolchains/mpi/psmpi.py index cfbf720a74..07e8c9af78 100644 --- a/easybuild/toolchains/mpi/psmpi.py +++ b/easybuild/toolchains/mpi/psmpi.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/mpi/qlogicmpi.py b/easybuild/toolchains/mpi/qlogicmpi.py index 26c0663756..b7355cd3e1 100644 --- a/easybuild/toolchains/mpi/qlogicmpi.py +++ b/easybuild/toolchains/mpi/qlogicmpi.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/mpi/spectrummpi.py b/easybuild/toolchains/mpi/spectrummpi.py index e0d4b2f530..1fee1d51b7 100644 --- a/easybuild/toolchains/mpi/spectrummpi.py +++ b/easybuild/toolchains/mpi/spectrummpi.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/nvhpc.py b/easybuild/toolchains/nvhpc.py index aca69d386f..b4b871f84f 100644 --- a/easybuild/toolchains/nvhpc.py +++ b/easybuild/toolchains/nvhpc.py @@ -1,5 +1,5 @@ ## -# Copyright 2015 Bart Oldeman +# Copyright 2015-2024 Bart Oldeman # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/nvofbf.py b/easybuild/toolchains/nvofbf.py index 41e89e5a32..62d3cb4d37 100644 --- a/easybuild/toolchains/nvofbf.py +++ b/easybuild/toolchains/nvofbf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/nvompi.py b/easybuild/toolchains/nvompi.py index 5f2e25f03d..3feedaae35 100644 --- a/easybuild/toolchains/nvompi.py +++ b/easybuild/toolchains/nvompi.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2021 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/nvompic.py b/easybuild/toolchains/nvompic.py index e4ac0d6106..b9c5abc298 100644 --- a/easybuild/toolchains/nvompic.py +++ b/easybuild/toolchains/nvompic.py @@ -1,6 +1,6 @@ ## -# Copyright 2016-2023 Ghent University -# Copyright 2016-2023 Forschungszentrum Juelich +# Copyright 2016-2024 Ghent University +# Copyright 2016-2024 Forschungszentrum Juelich # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/nvpsmpi.py b/easybuild/toolchains/nvpsmpi.py index 9e102c9d53..cbaee42bc0 100644 --- a/easybuild/toolchains/nvpsmpi.py +++ b/easybuild/toolchains/nvpsmpi.py @@ -1,6 +1,6 @@ ## -# Copyright 2016-2021 Ghent University -# Copyright 2016-2021 Forschungszentrum Juelich +# Copyright 2016-2024 Ghent University +# Copyright 2016-2024 Forschungszentrum Juelich # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/nvpsmpic.py b/easybuild/toolchains/nvpsmpic.py index 604630ff8e..0b916c30a0 100644 --- a/easybuild/toolchains/nvpsmpic.py +++ b/easybuild/toolchains/nvpsmpic.py @@ -1,6 +1,6 @@ ## -# Copyright 2016-2023 Ghent University -# Copyright 2016-2023 Forschungszentrum Juelich +# Copyright 2016-2024 Ghent University +# Copyright 2016-2024 Forschungszentrum Juelich # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/pgi.py b/easybuild/toolchains/pgi.py index 2ee3dc3839..df2258bda4 100644 --- a/easybuild/toolchains/pgi.py +++ b/easybuild/toolchains/pgi.py @@ -1,5 +1,5 @@ ## -# Copyright 2015 Bart Oldeman +# Copyright 2015-2024 Bart Oldeman # # This file is triple-licensed under GPLv2 (see below), MIT, and # BSD three-clause licenses. diff --git a/easybuild/toolchains/pmkl.py b/easybuild/toolchains/pmkl.py index a4ad73d7cd..8b22d1d35f 100644 --- a/easybuild/toolchains/pmkl.py +++ b/easybuild/toolchains/pmkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/pomkl.py b/easybuild/toolchains/pomkl.py index ea85e2d440..f28f445296 100644 --- a/easybuild/toolchains/pomkl.py +++ b/easybuild/toolchains/pomkl.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/pompi.py b/easybuild/toolchains/pompi.py index f8a9e00039..9de2e52050 100644 --- a/easybuild/toolchains/pompi.py +++ b/easybuild/toolchains/pompi.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/toolchains/system.py b/easybuild/toolchains/system.py index cfb46a93b2..8a8b17cfaa 100644 --- a/easybuild/toolchains/system.py +++ b/easybuild/toolchains/system.py @@ -1,5 +1,5 @@ ## -# Copyright 2019-2023 Ghent University +# Copyright 2019-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/__init__.py b/easybuild/tools/__init__.py index dee4fc0d12..8d34fc25c5 100644 --- a/easybuild/tools/__init__.py +++ b/easybuild/tools/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/asyncprocess.py b/easybuild/tools/asyncprocess.py index b3a7d330ff..0a3c133fc4 100644 --- a/easybuild/tools/asyncprocess.py +++ b/easybuild/tools/asyncprocess.py @@ -1,6 +1,6 @@ ## # Copyright 2005 Josiah Carlson -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # The Asynchronous Python Subprocess recipe was originally created by Josiah Carlson. # and released under the GPL v2 on March 14, 2012 diff --git a/easybuild/tools/build_details.py b/easybuild/tools/build_details.py index e99ddb4af9..487e6372a3 100644 --- a/easybuild/tools/build_details.py +++ b/easybuild/tools/build_details.py @@ -1,4 +1,4 @@ -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/build_log.py b/easybuild/tools/build_log.py index 215b8d38aa..0bbff702a1 100644 --- a/easybuild/tools/build_log.py +++ b/easybuild/tools/build_log.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/config.py b/easybuild/tools/config.py index ee8eb5fc53..3a5cbecb55 100644 --- a/easybuild/tools/config.py +++ b/easybuild/tools/config.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -220,6 +220,7 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX): 'filter_env_vars', 'filter_rpath_sanity_libs', 'force_download', + 'from_commit', 'git_working_dirs_path', 'github_user', 'github_org', @@ -229,6 +230,7 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX): 'http_header_fields_urlpat', 'hooks', 'ignore_dirs', + 'include_easyblocks_from_commit', 'insecure_download', 'job_backend_config', 'job_cores', @@ -307,6 +309,7 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX): 'skip_test_cases', 'skip_test_step', 'sticky_bit', + 'terse', 'trace', 'unit_testing_mode', 'upload_test_report', @@ -403,7 +406,7 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX): 'build_specs', 'command_line', 'external_modules_metadata', - 'pr_paths', + 'extra_ec_paths', 'robot_path', 'valid_module_classes', 'valid_stops', @@ -574,7 +577,7 @@ def init_build_options(build_options=None, cmdline_options=None): cmdline_options.accept_eula_for = cmdline_options.accept_eula cmdline_build_option_names = [k for ks in BUILD_OPTIONS_CMDLINE.values() for k in ks] - active_build_options.update(dict([(key, getattr(cmdline_options, key)) for key in cmdline_build_option_names])) + active_build_options.update({key: getattr(cmdline_options, key) for key in cmdline_build_option_names}) # other options which can be derived but have no perfectly matching cmdline option active_build_options.update({ 'check_osdeps': not cmdline_options.ignore_osdeps, @@ -597,7 +600,7 @@ def init_build_options(build_options=None, cmdline_options=None): for opt in build_options_by_default[default]: bo[opt] = [] else: - bo.update(dict([(opt, default) for opt in build_options_by_default[default]])) + bo.update({opt: default for opt in build_options_by_default[default]}) bo.update(active_build_options) # BuildOptions is a singleton, so any future calls to BuildOptions will yield the same instance diff --git a/easybuild/tools/configobj.py b/easybuild/tools/configobj.py index 48c7dd348d..6ac667b5bd 100644 --- a/easybuild/tools/configobj.py +++ b/easybuild/tools/configobj.py @@ -1254,7 +1254,7 @@ def set_section(in_section, this_section): self.configspec = None return - elif getattr(infile, 'read', MISSING) is not MISSING: + elif hasattr(infile, 'read'): # This supports file like objects infile = infile.read() or [] # needs splitting into lines - but needs doing *after* decoding diff --git a/easybuild/tools/containers/__init__.py b/easybuild/tools/containers/__init__.py index 76cb37219a..215ba61c0c 100644 --- a/easybuild/tools/containers/__init__.py +++ b/easybuild/tools/containers/__init__.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/containers/apptainer.py b/easybuild/tools/containers/apptainer.py index 67a6db5bc3..4cb252dac4 100644 --- a/easybuild/tools/containers/apptainer.py +++ b/easybuild/tools/containers/apptainer.py @@ -1,4 +1,4 @@ -# Copyright 2022-2023 Ghent University +# Copyright 2022-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/containers/base.py b/easybuild/tools/containers/base.py index 68a49610d3..faf3b0cc7a 100644 --- a/easybuild/tools/containers/base.py +++ b/easybuild/tools/containers/base.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/containers/common.py b/easybuild/tools/containers/common.py index bcbdce9a9b..6824c16864 100644 --- a/easybuild/tools/containers/common.py +++ b/easybuild/tools/containers/common.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/containers/docker.py b/easybuild/tools/containers/docker.py index aa37a90873..9061bba762 100644 --- a/easybuild/tools/containers/docker.py +++ b/easybuild/tools/containers/docker.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/containers/singularity.py b/easybuild/tools/containers/singularity.py index dc9cbb39a1..809fdc35d1 100644 --- a/easybuild/tools/containers/singularity.py +++ b/easybuild/tools/containers/singularity.py @@ -1,4 +1,4 @@ -# Copyright 2017-2023 Ghent University +# Copyright 2017-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/containers/utils.py b/easybuild/tools/containers/utils.py index 65be9dadf5..a575254335 100644 --- a/easybuild/tools/containers/utils.py +++ b/easybuild/tools/containers/utils.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/convert.py b/easybuild/tools/convert.py index f085590988..134566812d 100644 --- a/easybuild/tools/convert.py +++ b/easybuild/tools/convert.py @@ -1,5 +1,5 @@ # # -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/docs.py b/easybuild/tools/docs.py index 199cd22d78..b4387454ba 100644 --- a/easybuild/tools/docs.py +++ b/easybuild/tools/docs.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -306,7 +306,7 @@ def avail_easyconfig_licenses_md(): lics = sorted(EASYCONFIG_LICENSES_DICT.items()) table_values = [ ["``%s``" % lic().name for _, lic in lics], - ["%s" % lic().description for _, lic in lics], + [lic().description or '' for _, lic in lics], ["``%s``" % lic().version for _, lic in lics], ] @@ -1091,12 +1091,9 @@ def list_toolchains(output_format=FORMAT_TXT): """Show list of known toolchains.""" _, all_tcs = search_toolchain('') - # filter deprecated 'dummy' toolchain - all_tcs = [x for x in all_tcs if x.NAME != DUMMY_TOOLCHAIN_NAME] - all_tcs_names = [x.NAME for x in all_tcs] - # start with dict that maps toolchain name to corresponding subclass of Toolchain - tcs = dict(zip(all_tcs_names, all_tcs)) + # filter deprecated 'dummy' toolchain + tcs = {tc.NAME: tc for tc in all_tcs if tc.NAME != DUMMY_TOOLCHAIN_NAME} for tcname in sorted(tcs): tcc = tcs[tcname] @@ -1250,10 +1247,9 @@ def avail_toolchain_opts(name, output_format=FORMAT_TXT): tc_dict = {} for cst in ['COMPILER_SHARED_OPTS', 'COMPILER_UNIQUE_OPTS', 'MPI_SHARED_OPTS', 'MPI_UNIQUE_OPTS']: - if hasattr(tc, cst): - opts = getattr(tc, cst) - if opts is not None: - tc_dict.update(opts) + opts = getattr(tc, cst, None) + if opts is not None: + tc_dict.update(opts) return generate_doc('avail_toolchain_opts_%s' % output_format, [name, tc_dict]) @@ -1267,7 +1263,7 @@ def avail_toolchain_opts_md(name, tc_dict): tc_items = sorted(tc_dict.items()) table_values = [ ['``%s``' % val[0] for val in tc_items], - ['%s' % val[1][1] for val in tc_items], + [val[1][1] for val in tc_items], ['``%s``' % val[1][0] for val in tc_items], ] @@ -1285,7 +1281,7 @@ def avail_toolchain_opts_rst(name, tc_dict): tc_items = sorted(tc_dict.items()) table_values = [ ['``%s``' % val[0] for val in tc_items], - ['%s' % val[1][1] for val in tc_items], + [val[1][1] for val in tc_items], ['``%s``' % val[1][0] for val in tc_items], ] diff --git a/easybuild/tools/environment.py b/easybuild/tools/environment.py index d68755ff24..a5cc708ce2 100644 --- a/easybuild/tools/environment.py +++ b/easybuild/tools/environment.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -83,9 +83,9 @@ def setvar(key, value, verbose=True): :param verbose: include message in dry run output for defining this environment variable """ - if key in os.environ: + try: oldval_info = "previous value: '%s'" % os.environ[key] - else: + except KeyError: oldval_info = "previously undefined" # os.putenv() is not necessary. os.environ will call this. os.environ[key] = value @@ -136,7 +136,7 @@ def read_environment(env_vars, strict=False): :param env_vars: a dict with key a name, value a environment variable name :param strict: boolean, if True enforces that all specified environment variables are found """ - result = dict([(k, os.environ.get(v)) for k, v in env_vars.items() if v in os.environ]) + result = {k: os.environ.get(v) for k, v in env_vars.items() if v in os.environ} if not len(env_vars) == len(result): missing = ','.join(["%s / %s" % (k, v) for k, v in env_vars.items() if k not in result]) diff --git a/easybuild/tools/filetools.py b/easybuild/tools/filetools.py index 6e4bd2d83e..695043a595 100644 --- a/easybuild/tools/filetools.py +++ b/easybuild/tools/filetools.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -161,7 +161,7 @@ # tar.Z: using compress (LZW), but can be handled with gzip so use 'z' '.tar.z': "tar xzf %(filepath)s", # shell scripts don't need to be unpacked, just copy there - '.sh': "cp -a %(filepath)s .", + '.sh': "cp -dR %(filepath)s .", } ZIPPED_PATCH_EXTS = ('.bz2', '.gz', '.xz') @@ -966,11 +966,12 @@ def load_index(path, ignore_dirs=None): # check whether index is still valid if valid_ts: curr_ts = datetime.datetime.now() + terse = build_option('terse') if curr_ts > valid_ts: - print_warning("Index for %s is no longer valid (too old), so ignoring it...", path) + print_warning("Index for %s is no longer valid (too old), so ignoring it...", path, silent=terse) index = None else: - print_msg("found valid index for %s, so using it...", path) + print_msg("found valid index for %s, so using it...", path, silent=terse) return index or None @@ -2668,7 +2669,7 @@ def get_source_tarball_from_git(filename, targetdir, git_config): clone_cmd.append('%s/%s.git' % (url, repo_name)) if clone_into: - clone_cmd.append('%s' % clone_into) + clone_cmd.append(clone_into) tmpdir = tempfile.mkdtemp() cwd = change_dir(tmpdir) diff --git a/easybuild/tools/github.py b/easybuild/tools/github.py index 983dc977c4..ae9b78b5ed 100644 --- a/easybuild/tools/github.py +++ b/easybuild/tools/github.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -54,7 +54,7 @@ from easybuild.tools import LooseVersion from easybuild.tools.build_log import EasyBuildError, print_msg, print_warning from easybuild.tools.config import build_option -from easybuild.tools.filetools import apply_patch, copy_dir, copy_easyblocks, copy_framework_files +from easybuild.tools.filetools import apply_patch, copy_dir, copy_easyblocks, copy_file, copy_framework_files from easybuild.tools.filetools import det_patched_files, download_file, extract_file from easybuild.tools.filetools import get_easyblock_class_name, mkdir, read_file, symlink, which, write_file from easybuild.tools.py2vs3 import HTTPError, URLError, ascii_letters, urlopen @@ -355,16 +355,18 @@ def fetch_latest_commit_sha(repo, account, branch=None, github_user=None, token= return res -def download_repo(repo=GITHUB_EASYCONFIGS_REPO, branch=None, account=GITHUB_EB_MAIN, path=None, github_user=None): +def download_repo(repo=GITHUB_EASYCONFIGS_REPO, branch=None, commit=None, account=GITHUB_EB_MAIN, path=None, + github_user=None): """ Download entire GitHub repo as a tar.gz archive, and extract it into specified path. :param repo: repo to download :param branch: branch to download + :param commit: commit to download :param account: GitHub account to download repo from :param path: path to extract to :param github_user: name of GitHub user to use """ - if branch is None: + if branch is None and commit is None: branch = pick_default_branch(account) # make sure path exists, create it if necessary @@ -375,9 +377,25 @@ def download_repo(repo=GITHUB_EASYCONFIGS_REPO, branch=None, account=GITHUB_EB_M path = os.path.join(path, account) mkdir(path, parents=True) - extracted_dir_name = '%s-%s' % (repo, branch) - base_name = '%s.tar.gz' % branch - latest_commit_sha = fetch_latest_commit_sha(repo, account, branch, github_user=github_user) + if commit: + # make sure that full commit SHA is provided + commit_sha1_regex = re.compile('[0-9a-f]{40}') + if commit_sha1_regex.match(commit): + _log.info("Valid commit SHA provided for downloading %s/%s: %s", account, repo, commit) + else: + error_msg = r"Specified commit SHA %s for downloading %s/%s is not valid, " + error_msg += "must be full SHA-1 (40 chars)" + raise EasyBuildError(error_msg, commit, account, repo) + + extracted_dir_name = '%s-%s' % (repo, commit) + base_name = '%s.tar.gz' % commit + latest_commit_sha = commit + elif branch: + extracted_dir_name = '%s-%s' % (repo, branch) + base_name = '%s.tar.gz' % branch + latest_commit_sha = fetch_latest_commit_sha(repo, account, branch, github_user=github_user) + else: + raise EasyBuildError("Either branch or commit should be specified in download_repo") expected_path = os.path.join(path, extracted_dir_name) latest_sha_path = os.path.join(expected_path, 'latest-sha') @@ -393,19 +411,33 @@ def download_repo(repo=GITHUB_EASYCONFIGS_REPO, branch=None, account=GITHUB_EB_M target_path = os.path.join(path, base_name) _log.debug("downloading repo %s/%s as archive from %s to %s" % (account, repo, url, target_path)) - download_file(base_name, url, target_path, forced=True) - _log.debug("%s downloaded to %s, extracting now" % (base_name, path)) + downloaded_path = download_file(base_name, url, target_path, forced=True) + if downloaded_path is None: + raise EasyBuildError("Failed to download tarball for %s/%s commit %s", account, repo, commit) + else: + _log.debug("%s downloaded to %s, extracting now" % (base_name, path)) base_dir = extract_file(target_path, path, forced=True, change_into_dir=False) extracted_path = os.path.join(base_dir, extracted_dir_name) # check if extracted_path exists if not os.path.isdir(extracted_path): - raise EasyBuildError("%s should exist and contain the repo %s at branch %s", extracted_path, repo, branch) + error_msg = "%s should exist and contain the repo %s " % (extracted_path, repo) + if branch: + error_msg += "at branch " + branch + elif commit: + error_msg += "at commit " + commit + raise EasyBuildError(error_msg) write_file(latest_sha_path, latest_commit_sha, forced=True) - _log.debug("Repo %s at branch %s extracted into %s" % (repo, branch, extracted_path)) + log_msg = "Repo %s at %%s extracted into %s" % (repo, extracted_path) + if branch: + log_msg = log_msg % ('branch ' + branch) + elif commit: + log_msg = log_msg % ('commit ' + commit) + _log.debug(log_msg) + return extracted_path @@ -450,14 +482,15 @@ def fetch_files_from_pr(pr, path=None, github_user=None, github_account=None, gi if path is None: if github_repo == GITHUB_EASYCONFIGS_REPO: - pr_paths = build_option('pr_paths') - if pr_paths: + extra_ec_paths = build_option('extra_ec_paths') + if extra_ec_paths: # figure out directory for this specific PR (see also alt_easyconfig_paths) - cands = [p for p in pr_paths if p.endswith('files_pr%s' % pr)] + cands = [p for p in extra_ec_paths if p.endswith('files_pr%s' % pr)] if len(cands) == 1: path = cands[0] else: - raise EasyBuildError("Failed to isolate path for PR #%s from list of PR paths: %s", pr, pr_paths) + raise EasyBuildError("Failed to isolate path for PR #%s from list of PR paths: %s", + pr, extra_ec_paths) elif github_repo == GITHUB_EASYBLOCKS_REPO: path = os.path.join(tempfile.gettempdir(), 'ebs_pr%s' % pr) @@ -558,7 +591,7 @@ def fetch_files_from_pr(pr, path=None, github_user=None, github_account=None, gi def fetch_easyblocks_from_pr(pr, path=None, github_user=None): - """Fetch patched easyconfig files for a particular PR.""" + """Fetch patched easyblocks for a particular PR.""" return fetch_files_from_pr(pr, path, github_user, github_repo=GITHUB_EASYBLOCKS_REPO) @@ -567,6 +600,102 @@ def fetch_easyconfigs_from_pr(pr, path=None, github_user=None): return fetch_files_from_pr(pr, path, github_user, github_repo=GITHUB_EASYCONFIGS_REPO) +def fetch_files_from_commit(commit, files=None, path=None, github_account=None, github_repo=None): + """ + Fetch files from a specific commit. + + If 'files' is None, all files touched in the commit are used. + """ + if github_account is None: + github_account = build_option('pr_target_account') + + if github_repo is None: + github_repo = GITHUB_EASYCONFIGS_REPO + + if path is None: + if github_repo == GITHUB_EASYCONFIGS_REPO: + extra_ec_paths = build_option('extra_ec_paths') + if extra_ec_paths: + # figure out directory for this specific commit (see also alt_easyconfig_paths) + cands = [p for p in extra_ec_paths if p.endswith('files_commit_' + commit)] + if len(cands) == 1: + path = cands[0] + else: + raise EasyBuildError("Failed to isolate path for commit %s from list of commit paths: %s", + commit, extra_ec_paths) + else: + path = os.path.join(tempfile.gettempdir(), 'ecs_commit_' + commit) + + elif github_repo == GITHUB_EASYBLOCKS_REPO: + path = os.path.join(tempfile.gettempdir(), 'ebs_commit_' + commit) + else: + raise EasyBuildError("Unknown repo: %s" % github_repo) + + # if no files are specified, determine which files are touched in commit + if not files: + diff_url = os.path.join(GITHUB_URL, github_account, github_repo, 'commit', commit + '.diff') + diff_fn = os.path.basename(diff_url) + diff_filepath = os.path.join(path, diff_fn) + if download_file(diff_fn, diff_url, diff_filepath, forced=True): + diff_txt = read_file(diff_filepath) + _log.debug("Diff for commit %s:\n%s", commit, diff_txt) + + files = det_patched_files(txt=diff_txt, omit_ab_prefix=True, github=True, filter_deleted=True) + _log.debug("List of patched files for commit %s: %s", commit, files) + else: + raise EasyBuildError("Failed to download diff for commit %s of %s/%s", commit, github_account, github_repo) + + # download tarball for specific commit + repo_commit = download_repo(repo=github_repo, commit=commit, account=github_account) + + if github_repo == GITHUB_EASYCONFIGS_REPO: + files_subdir = 'easybuild/easyconfigs/' + elif github_repo == GITHUB_EASYBLOCKS_REPO: + files_subdir = 'easybuild/easyblocks/' + else: + raise EasyBuildError("Unknown repo: %s" % github_repo) + + # copy specified files to directory where they're expected to be found + file_paths = [] + for file in files: + + # if only filename is specified, we need to determine the file path + if file == os.path.basename(file): + src_path = None + for (dirpath, _, filenames) in os.walk(repo_commit, topdown=True): + if file in filenames: + src_path = os.path.join(dirpath, file) + break + else: + src_path = os.path.join(repo_commit, file) + + # strip of leading subdirectory like easybuild/easyconfigs/ or easybuild/easyblocks/ + # because that's what expected by robot_find_easyconfig + if file.startswith(files_subdir): + file = file[len(files_subdir):] + + # if file is found, copy it to dedicated directory; + # if not, just skip it (may be an easyconfig file in local directory); + if src_path and os.path.exists(src_path): + target_path = os.path.join(path, file) + copy_file(src_path, target_path) + file_paths.append(target_path) + else: + _log.info("File %s not found in %s, so ignoring it...", file, repo_commit) + + return file_paths + + +def fetch_easyblocks_from_commit(commit, files=None, path=None): + """Fetch easyblocks from a specified commit.""" + return fetch_files_from_commit(commit, files=files, path=path, github_repo=GITHUB_EASYBLOCKS_REPO) + + +def fetch_easyconfigs_from_commit(commit, files=None, path=None): + """Fetch specified easyconfig files from a specific commit.""" + return fetch_files_from_commit(commit, files=files, path=path, github_repo=GITHUB_EASYCONFIGS_REPO) + + def create_gist(txt, fn, descr=None, github_user=None, github_token=None): """Create a gist with the provided text.""" @@ -719,9 +848,9 @@ def setup_repo_from(git_repo, github_url, target_account, branch_name, silent=Fa raise EasyBuildError("Fetching branch '%s' from remote %s failed: empty result", branch_name, origin) # git checkout -b ; git pull - if hasattr(origin.refs, branch_name): + try: origin_branch = getattr(origin.refs, branch_name) - else: + except AttributeError: raise EasyBuildError("Branch '%s' not found at %s", branch_name, github_url) _log.debug("Checking out branch '%s' from remote %s", branch_name, github_url) @@ -1370,8 +1499,7 @@ def close_pr(pr, motivation_msg=None): if not reopen: msg += "\nPlease don't hesitate to reopen this PR or add a comment if you feel this contribution is still " msg += "relevant.\nFor more information on our policy w.r.t. closing PRs, see " - msg += "https://easybuild.readthedocs.io/en/latest/Contributing.html" - msg += "#why-a-pull-request-may-be-closed-by-a-maintainer" + msg += "https://docs.easybuild.io/contributing/#contributing_review_process_why_pr_closed_by_maintainer" post_comment_in_issue(pr, msg, account=pr_target_account, repo=pr_target_repo, github_user=github_user) if dry_run: @@ -2008,17 +2136,18 @@ def check_github(): github_user = build_option('github_user') github_account = build_option('github_org') or build_option('github_user') - if github_user is None: - check_res = "(none available) => FAIL" - status['--new-pr'] = status['--update-pr'] = status['--upload-test-report'] = False - else: + if github_user: check_res = "%s => OK" % github_user + else: + check_res = "%s => FAIL" % ('(none available)' if github_user is None else '(empty)') + status['--new-pr'] = status['--update-pr'] = status['--upload-test-report'] = False print_msg(check_res, log=_log, prefix=False) # check GitHub token print_msg("* GitHub token...", log=_log, prefix=False, newline=False) github_token = fetch_github_token(github_user) + github_token_valid = False if github_token is None: check_res = "(no token found) => FAIL" else: @@ -2027,6 +2156,7 @@ def check_github(): token_descr = partial_token + " (len: %d)" % len(github_token) if validate_github_token(github_token, github_user): check_res = "%s => OK (validated)" % token_descr + github_token_valid = True else: check_res = "%s => FAIL (validation failed)" % token_descr @@ -2119,7 +2249,7 @@ def check_github(): try: getattr(git_repo.remotes, remote_name).push(branch_name, delete=True) except GitCommandError as err: - sys.stderr.write("WARNING: failed to delete test branch from GitHub: %s\n" % err) + print_warning("failed to delete test branch from GitHub: %s" % err, log=_log) # test creating a gist print_msg("* creating gists...", log=_log, prefix=False, newline=False) @@ -2137,17 +2267,33 @@ def check_github(): if gist_url and re.match('https://gist.github.com/%s/[0-9a-f]+$' % github_user, gist_url): check_res = "OK" - else: + elif not github_user: + check_res = "FAIL (no GitHub user specified)" + elif not github_token: + check_res = "FAIL (missing github token)" + elif not github_token_valid: + check_res = "FAIL (invalid github token)" + elif gist_url: check_res = "FAIL (gist_url: %s)" % gist_url - status['--upload-test-report'] = False + else: + check_res = "FAIL" + if 'FAIL' in check_res: + status['--upload-test-report'] = False print_msg(check_res, log=_log, prefix=False) # check whether location to local working directories for Git repositories is available (not strictly needed) print_msg("* location to Git working dirs... ", log=_log, prefix=False, newline=False) git_working_dirs_path = build_option('git_working_dirs_path') if git_working_dirs_path: - check_res = "OK (%s)" % git_working_dirs_path + repos = [GITHUB_EASYCONFIGS_REPO, GITHUB_EASYBLOCKS_REPO, GITHUB_FRAMEWORK_REPO] + missing_repos = [repo for repo in repos if not os.path.exists(os.path.join(git_working_dirs_path, repo))] + if not missing_repos: + check_res = "OK (%s)" % git_working_dirs_path + elif missing_repos != repos: + check_res = "OK (%s) but missing %s (suboptimal)" % (git_working_dirs_path, ', '.join(missing_repos)) + else: + check_res = "set (%s) but not populated (suboptimal)" % git_working_dirs_path else: check_res = "not found (suboptimal)" diff --git a/easybuild/tools/hooks.py b/easybuild/tools/hooks.py index f454974edb..f018c40607 100644 --- a/easybuild/tools/hooks.py +++ b/easybuild/tools/hooks.py @@ -1,5 +1,5 @@ # # -# Copyright 2017-2023 Ghent University +# Copyright 2017-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/include.py b/easybuild/tools/include.py index 3898facd4c..0171d74f10 100644 --- a/easybuild/tools/include.py +++ b/easybuild/tools/include.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # # -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/jenkins.py b/easybuild/tools/jenkins.py index 3c00d3961c..50ee563083 100644 --- a/easybuild/tools/jenkins.py +++ b/easybuild/tools/jenkins.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/job/backend.py b/easybuild/tools/job/backend.py index c92ead6a58..1219883740 100644 --- a/easybuild/tools/job/backend.py +++ b/easybuild/tools/job/backend.py @@ -1,5 +1,5 @@ ## -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -104,7 +104,7 @@ def avail_job_backends(check_usable=True): Return all known job execution backends. """ import_available_modules('easybuild.tools.job') - class_dict = dict([(x.__name__, x) for x in get_subclasses(JobBackend)]) + class_dict = {x.__name__: x for x in get_subclasses(JobBackend)} return class_dict diff --git a/easybuild/tools/job/gc3pie.py b/easybuild/tools/job/gc3pie.py index 005cff2e90..f6b57e0f2c 100644 --- a/easybuild/tools/job/gc3pie.py +++ b/easybuild/tools/job/gc3pie.py @@ -1,5 +1,5 @@ ## -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # Copyright 2015 S3IT, University of Zurich # # This file is part of EasyBuild, diff --git a/easybuild/tools/job/pbs_python.py b/easybuild/tools/job/pbs_python.py index a4a020988e..bf90b57063 100644 --- a/easybuild/tools/job/pbs_python.py +++ b/easybuild/tools/job/pbs_python.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -484,7 +484,7 @@ def info(self, types=None): # only expect to have a list with one element j = jobs[0] # convert attribs into useable dict - job_details = dict([(attrib.name, attrib.value) for attrib in j.attribs]) + job_details = {attrib.name: attrib.value for attrib in j.attribs} # manually set 'id' attribute job_details['id'] = j.name self.log.debug("Found jobinfo %s" % job_details) diff --git a/easybuild/tools/job/slurm.py b/easybuild/tools/job/slurm.py index 1f2dea776d..2666cbd6af 100644 --- a/easybuild/tools/job/slurm.py +++ b/easybuild/tools/job/slurm.py @@ -1,5 +1,5 @@ ## -# Copyright 2018-2023 Ghent University +# Copyright 2018-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/module_generator.py b/easybuild/tools/module_generator.py index 0c19b93c8b..5704d24cb0 100644 --- a/easybuild/tools/module_generator.py +++ b/easybuild/tools/module_generator.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -59,7 +59,7 @@ def avail_module_generators(): """ Return all known module syntaxes. """ - return dict([(k.SYNTAX, k) for k in get_subclasses(ModuleGenerator)]) + return {k.SYNTAX: k for k in get_subclasses(ModuleGenerator)} def module_generator(app, fake=False): @@ -1289,7 +1289,7 @@ def get_description(self, conflict=True): extensions_list = self._generate_extensions_list() if extensions_list: - extensions_stmt = 'extensions("%s")' % ','.join(['%s' % x for x in extensions_list]) + extensions_stmt = 'extensions("%s")' % ','.join([str(x) for x in extensions_list]) # put this behind a Lmod version check as 'extensions' is only (well) supported since Lmod 8.2.8, # see https://lmod.readthedocs.io/en/latest/330_extensions.html#module-extensions and # https://github.com/TACC/Lmod/issues/428 diff --git a/easybuild/tools/module_naming_scheme/__init__.py b/easybuild/tools/module_naming_scheme/__init__.py index bea5d52dc5..e54f04c31e 100644 --- a/easybuild/tools/module_naming_scheme/__init__.py +++ b/easybuild/tools/module_naming_scheme/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2011-2023 Ghent University +# Copyright 2011-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/module_naming_scheme/categorized_mns.py b/easybuild/tools/module_naming_scheme/categorized_mns.py index 616baf19c2..cdafc97cbb 100644 --- a/easybuild/tools/module_naming_scheme/categorized_mns.py +++ b/easybuild/tools/module_naming_scheme/categorized_mns.py @@ -1,5 +1,5 @@ ## -# Copyright 2016-2023 Ghent University +# Copyright 2016-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/module_naming_scheme/easybuild_mns.py b/easybuild/tools/module_naming_scheme/easybuild_mns.py index c12ae9a614..93ff663e77 100644 --- a/easybuild/tools/module_naming_scheme/easybuild_mns.py +++ b/easybuild/tools/module_naming_scheme/easybuild_mns.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/module_naming_scheme/hierarchical_mns.py b/easybuild/tools/module_naming_scheme/hierarchical_mns.py index 9f2e026eb8..d0e4ea5966 100644 --- a/easybuild/tools/module_naming_scheme/hierarchical_mns.py +++ b/easybuild/tools/module_naming_scheme/hierarchical_mns.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -120,7 +120,7 @@ def det_toolchain_compilers_name_version(self, tc_comps): res = None else: if len(tc_comps) > 0 and tc_comps[0]: - comp_versions = dict([(comp['name'], self.det_full_version(comp)) for comp in tc_comps]) + comp_versions = {comp['name']: self.det_full_version(comp) for comp in tc_comps} comp_names = comp_versions.keys() key = ','.join(sorted(comp_names)) if key in COMP_NAME_VERSION_TEMPLATES: diff --git a/easybuild/tools/module_naming_scheme/migrate_from_eb_to_hmns.py b/easybuild/tools/module_naming_scheme/migrate_from_eb_to_hmns.py index 8d0c34297f..5603b7db47 100644 --- a/easybuild/tools/module_naming_scheme/migrate_from_eb_to_hmns.py +++ b/easybuild/tools/module_naming_scheme/migrate_from_eb_to_hmns.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/module_naming_scheme/mns.py b/easybuild/tools/module_naming_scheme/mns.py index 487dbac063..fd60dbbe90 100644 --- a/easybuild/tools/module_naming_scheme/mns.py +++ b/easybuild/tools/module_naming_scheme/mns.py @@ -1,5 +1,5 @@ ## -# Copyright 2011-2023 Ghent University +# Copyright 2011-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/module_naming_scheme/toolchain.py b/easybuild/tools/module_naming_scheme/toolchain.py index 135d996ffb..b85032e6e6 100644 --- a/easybuild/tools/module_naming_scheme/toolchain.py +++ b/easybuild/tools/module_naming_scheme/toolchain.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/module_naming_scheme/utilities.py b/easybuild/tools/module_naming_scheme/utilities.py index e46609d22b..4fff90f690 100644 --- a/easybuild/tools/module_naming_scheme/utilities.py +++ b/easybuild/tools/module_naming_scheme/utilities.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -86,7 +86,7 @@ def avail_module_naming_schemes(): import_available_modules('easybuild.tools.module_naming_scheme') # construct name-to-class dict of available module naming scheme - avail_mnss = dict([(x.__name__, x) for x in get_subclasses(ModuleNamingScheme)]) + avail_mnss = {x.__name__: x for x in get_subclasses(ModuleNamingScheme)} return avail_mnss diff --git a/easybuild/tools/modules.py b/easybuild/tools/modules.py index 7d7181fe30..fc21a564b9 100644 --- a/easybuild/tools/modules.py +++ b/easybuild/tools/modules.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -307,9 +307,9 @@ def check_module_function(self, allow_mismatch=False, regex=None): """Check whether selected module tool matches 'module' function definition.""" if self.testing: # grab 'module' function definition from environment if it's there; only during testing - if 'module' in os.environ: + try: out, ec = os.environ['module'], 0 - else: + except KeyError: out, ec = None, 1 else: cmd = "type module" @@ -851,6 +851,8 @@ def run_module(self, *args, **kwargs): # this needs to be taken into account when updating the environment via produced output, see below # keep track of current values of select env vars, so we can correct the adjusted values below + # Identical to `{key: os.environ.get(key, '').split(os.pathsep)[::-1] for key in LD_ENV_VAR_KEYS}` + # but Python 2 treats that as a local function and refused the `exec` below prev_ld_values = dict([(key, os.environ.get(key, '').split(os.pathsep)[::-1]) for key in LD_ENV_VAR_KEYS]) # Change the environment @@ -1126,7 +1128,7 @@ def path_to_top_of_module_tree(self, top_paths, mod_name, full_mod_subdir, deps, if modpath_exts is None: # only retain dependencies that have a non-empty lists of $MODULEPATH extensions - modpath_exts = dict([(k, v) for k, v in self.modpath_extensions_for(deps).items() if v]) + modpath_exts = {k: v for k, v in self.modpath_extensions_for(deps).items() if v} self.log.debug("Non-empty lists of module path extensions for dependencies: %s" % modpath_exts) mods_to_top = [] @@ -1157,7 +1159,7 @@ def path_to_top_of_module_tree(self, top_paths, mod_name, full_mod_subdir, deps, path = mods_to_top[:] if mods_to_top: # remove retained dependencies from the list, since we're climbing up the module tree - remaining_modpath_exts = dict([m for m in modpath_exts.items() if not m[0] in mods_to_top]) + remaining_modpath_exts = {m: v for m, v in modpath_exts.items() if m not in mods_to_top} self.log.debug("Path to top from %s extended to %s, so recursing to find way to the top", mod_name, mods_to_top) @@ -1283,14 +1285,14 @@ def tweak_stdout(txt): return super(EnvironmentModulesTcl, self).run_module(*args, **kwargs) - def available(self, mod_name=None): + def available(self, mod_name=None, extra_args=None): """ Return a list of available modules for the given (partial) module name; use None to obtain a list of all available modules. :param mod_name: a (partial) module name for filtering (default: None) """ - mods = super(EnvironmentModulesTcl, self).available(mod_name=mod_name) + mods = super(EnvironmentModulesTcl, self).available(mod_name=mod_name, extra_args=extra_args) # strip off slash at beginning, if it's there # under certain circumstances, 'modulecmd.tcl avail' (DEISA variant) spits out available modules like this clean_mods = [mod.lstrip(os.path.sep) for mod in mods] @@ -1326,7 +1328,9 @@ class EnvironmentModules(EnvironmentModulesTcl): COMMAND_ENVIRONMENT = 'MODULES_CMD' REQ_VERSION = '4.0.0' MAX_VERSION = None - VERSION_REGEXP = r'^Modules\s+Release\s+(?P\d\S*)\s' + VERSION_REGEXP = r'^Modules\s+Release\s+(?P\d[^+\s]*)(\+\S*)?\s' + + SHOW_HIDDEN_OPTION = '--all' def __init__(self, *args, **kwargs): """Constructor, set Environment Modules-specific class variable values.""" @@ -1383,6 +1387,21 @@ def check_module_output(self, cmd, stdout, stderr): else: self.log.debug("No errors detected when running module command '%s'", cmd) + def available(self, mod_name=None, extra_args=None): + """ + Return a list of available modules for the given (partial) module name; + use None to obtain a list of all available modules. + + :param mod_name: a (partial) module name for filtering (default: None) + """ + if extra_args is None: + extra_args = [] + # make hidden modules visible (requires Environment Modules 4.6.0) + if StrictVersion(self.version) >= StrictVersion('4.6.0'): + extra_args.append(self.SHOW_HIDDEN_OPTION) + + return super(EnvironmentModules, self).available(mod_name=mod_name, extra_args=extra_args) + def get_setenv_value_from_modulefile(self, mod_name, var_name): """ Get value for specific 'setenv' statement from module file for the specified module. @@ -1636,9 +1655,7 @@ def get_software_root(name, with_env_var=False): """ env_var = get_software_root_env_var_name(name) - root = None - if env_var in os.environ: - root = os.getenv(env_var) + root = os.getenv(env_var) if with_env_var: res = (root, env_var) @@ -1706,9 +1723,7 @@ def get_software_version(name): """ env_var = get_software_version_env_var_name(name) - version = None - if env_var in os.environ: - version = os.getenv(env_var) + version = os.getenv(env_var) return version @@ -1737,7 +1752,7 @@ def avail_modules_tools(): """ Return all known modules tools. """ - class_dict = dict([(x.__name__, x) for x in get_subclasses(ModulesTool)]) + class_dict = {x.__name__: x for x in get_subclasses(ModulesTool)} # filter out legacy Modules class if 'Modules' in class_dict: del class_dict['Modules'] diff --git a/easybuild/tools/multidiff.py b/easybuild/tools/multidiff.py index 0f8c7f5bac..99ee949e56 100644 --- a/easybuild/tools/multidiff.py +++ b/easybuild/tools/multidiff.py @@ -1,5 +1,5 @@ # # -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/options.py b/easybuild/tools/options.py index 554775be20..68ddba632a 100644 --- a/easybuild/tools/options.py +++ b/easybuild/tools/options.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -89,7 +89,7 @@ from easybuild.tools.github import GITHUB_PR_DIRECTION_DESC, GITHUB_PR_ORDER_CREATED from easybuild.tools.github import GITHUB_PR_STATE_OPEN, GITHUB_PR_STATES, GITHUB_PR_ORDERS, GITHUB_PR_DIRECTIONS from easybuild.tools.github import HAVE_GITHUB_API, HAVE_KEYRING, VALID_CLOSE_PR_REASONS -from easybuild.tools.github import fetch_easyblocks_from_pr, fetch_github_token +from easybuild.tools.github import fetch_easyblocks_from_commit, fetch_easyblocks_from_pr, fetch_github_token from easybuild.tools.hooks import KNOWN_HOOKS from easybuild.tools.include import include_easyblocks, include_module_naming_schemes, include_toolchains from easybuild.tools.job.backend import avail_job_backends @@ -244,7 +244,7 @@ def __init__(self, *args, **kwargs): # update or define go_configfiles_initenv in named arguments to pass to parent constructor go_cfg_initenv = kwargs.setdefault('go_configfiles_initenv', {}) for section, constants in self.go_cfg_constants.items(): - constants = dict([(name, value) for (name, (value, _)) in constants.items()]) + constants = {name: value for name, (value, _) in constants.items()} go_cfg_initenv.setdefault(section, {}).update(constants) super(EasyBuildOptions, self).__init__(*args, **kwargs) @@ -357,7 +357,8 @@ def override_options(self): None, 'store_true', False), 'allow-use-as-root-and-accept-consequences': ("Allow using of EasyBuild as root (NOT RECOMMENDED!)", None, 'store_true', False), - 'backup-modules': ("Back up an existing module file, if any. Only works when using --module-only", + 'backup-modules': ("Back up an existing module file, if any. " + "Auto-enabled when using --module-only or --skip", None, 'store_true', None), # default None to allow auto-enabling if not disabled 'backup-patched-files': ("Create a backup (*.orig) file when applying a patch", None, 'store_true', False), @@ -701,10 +702,14 @@ def github_options(self): 'check-style': ("Run a style check on the given easyconfigs", None, 'store_true', False), 'cleanup-easyconfigs': ("Clean up easyconfig files for pull request", None, 'store_true', True), 'dump-test-report': ("Dump test report to specified path", None, 'store_or_None', 'test_report.md'), + 'from-commit': ("Obtain easyconfigs from specified commit", 'str', 'store', + None, {'metavar': 'commit_SHA'}), 'from-pr': ("Obtain easyconfigs from specified PR", 'strlist', 'store', [], {'metavar': 'PR#'}), 'git-working-dirs-path': ("Path to Git working directories for EasyBuild repositories", str, 'store', None), 'github-user': ("GitHub username", str, 'store', None), 'github-org': ("GitHub organization", str, 'store', None), + 'include-easyblocks-from-commit': ("Include easyblocks from specified commit", 'str', 'store', None, + {'metavar': 'commit_SHA'}), 'include-easyblocks-from-pr': ("Include easyblocks from specified PR", 'strlist', 'store', [], {'metavar': 'PR#'}), 'install-github-token': ("Install GitHub token (requires --github-user)", None, 'store_true', False), @@ -1223,8 +1228,9 @@ def _postprocess_list_avail(self): if self.options.avail_easyconfig_licenses: msg += avail_easyconfig_licenses(self.options.output_format) - # dump available easyblocks (unless including easyblocks from pr, in which case it will be done later) - if self.options.list_easyblocks and not self.options.include_easyblocks_from_pr: + # dump available easyblocks (unless including easyblocks from commit or PR, in which case it will be done later) + easyblocks_from = self.options.include_easyblocks_from_commit or self.options.include_easyblocks_from_pr + if self.options.list_easyblocks and not easyblocks_from: msg += list_easyblocks(self.options.list_easyblocks, self.options.output_format) # dump known toolchains @@ -1268,7 +1274,7 @@ def _postprocess_list_avail(self): print(msg) # cleanup tmpdir and exit - if not self.options.include_easyblocks_from_pr: + if not (self.options.include_easyblocks_from_commit or self.options.include_easyblocks_from_pr): cleanup_and_exit(self.tmpdir) def avail_repositories(self): @@ -1506,6 +1512,19 @@ def parse_options(args=None, with_include=True): return eb_go +def check_options(options): + """ + Check configuration options, some combinations are not allowed. + """ + if options.from_commit and options.from_pr: + raise EasyBuildError("--from-commit and --from-pr should not be used together, pick one") + + if options.include_easyblocks_from_commit and options.include_easyblocks_from_pr: + error_msg = "--include-easyblocks-from-commit and --include-easyblocks-from-pr " + error_msg += "should not be used together, pick one" + raise EasyBuildError(error_msg) + + def check_root_usage(allow_use_as_root=False): """ Check whether we are running as root, and act accordingly @@ -1523,6 +1542,69 @@ def check_root_usage(allow_use_as_root=False): "so let's end this here.") +def handle_include_easyblocks_from(options, log): + """ + Handle --include-easyblocks-from-pr and --include-easyblocks-from-commit + """ + def check_included_multiple(included_easyblocks_from, source): + """Check whether easyblock is being included multiple times""" + included_multiple = included_easyblocks_from & included_easyblocks + if included_multiple: + warning_msg = "One or more easyblocks included from multiple locations: %s " \ + % ', '.join(included_multiple) + warning_msg += "(the one(s) from %s will be used)" % source + print_warning(warning_msg) + + if options.include_easyblocks_from_pr or options.include_easyblocks_from_commit: + + if options.include_easyblocks: + # check if you are including the same easyblock twice + included_paths = expand_glob_paths(options.include_easyblocks) + included_easyblocks = set([os.path.basename(eb) for eb in included_paths]) + + if options.include_easyblocks_from_pr: + try: + easyblock_prs = [int(x) for x in options.include_easyblocks_from_pr] + except ValueError: + raise EasyBuildError("Argument to --include-easyblocks-from-pr must be a comma separated list of PR #s") + + for easyblock_pr in easyblock_prs: + easyblocks_from_pr = fetch_easyblocks_from_pr(easyblock_pr) + included_from_pr = set([os.path.basename(eb) for eb in easyblocks_from_pr]) + + if options.include_easyblocks: + check_included_multiple(included_from_pr, "PR #%s" % easyblock_pr) + included_easyblocks |= included_from_pr + + for easyblock in included_from_pr: + print_msg("easyblock %s included from PR #%s" % (easyblock, easyblock_pr), log=log) + + include_easyblocks(options.tmpdir, easyblocks_from_pr) + + easyblock_commit = options.include_easyblocks_from_commit + if easyblock_commit: + easyblocks_from_commit = fetch_easyblocks_from_commit(easyblock_commit) + included_from_commit = set([os.path.basename(eb) for eb in easyblocks_from_commit]) + + if options.include_easyblocks: + check_included_multiple(included_from_commit, "commit %s" % easyblock_commit) + + for easyblock in included_from_commit: + print_msg("easyblock %s included from comit %s" % (easyblock, easyblock_commit), log=log) + + include_easyblocks(options.tmpdir, easyblocks_from_commit) + + if options.list_easyblocks: + msg = list_easyblocks(options.list_easyblocks, options.output_format) + if options.unittest_file: + log.info(msg) + else: + print(msg) + # tmpdir is set by option parser via set_tmpdir function + tmpdir = tempfile.gettempdir() + cleanup_and_exit(tmpdir) + + def set_up_configuration(args=None, logfile=None, testing=False, silent=False, reconfigure=False): """ Set up EasyBuild configuration, by parsing configuration settings & initialising build options. @@ -1543,6 +1625,8 @@ def set_up_configuration(args=None, logfile=None, testing=False, silent=False, r eb_go = parse_options(args=args) options = eb_go.options + check_options(options) + # tmpdir is set by option parser via set_tmpdir function tmpdir = tempfile.gettempdir() @@ -1587,10 +1671,11 @@ def set_up_configuration(args=None, logfile=None, testing=False, silent=False, r # determine robot path # --try-X, --dep-graph, --search use robot path for searching, so enable it with path of installed easyconfigs tweaked_ecs = try_to_generate and build_specs - tweaked_ecs_paths, pr_paths = alt_easyconfig_paths(tmpdir, tweaked_ecs=tweaked_ecs, from_prs=from_prs, - review_pr=review_pr) + tweaked_ecs_paths, extra_ec_paths = alt_easyconfig_paths(tmpdir, tweaked_ecs=tweaked_ecs, from_prs=from_prs, + from_commit=eb_go.options.from_commit, + review_pr=review_pr) auto_robot = try_to_generate or options.check_conflicts or options.dep_graph or search_query - robot_path = det_robot_path(options.robot_paths, tweaked_ecs_paths, pr_paths, auto_robot=auto_robot) + robot_path = det_robot_path(options.robot_paths, tweaked_ecs_paths, extra_ec_paths, auto_robot=auto_robot) log.debug("Full robot path: %s", robot_path) if not robot_path: @@ -1604,7 +1689,7 @@ def set_up_configuration(args=None, logfile=None, testing=False, silent=False, r 'build_specs': build_specs, 'command_line': eb_cmd_line, 'external_modules_metadata': parse_external_modules_metadata(options.external_modules_metadata), - 'pr_paths': pr_paths, + 'extra_ec_paths': extra_ec_paths, 'robot_path': robot_path, 'silent': testing or new_update_opt, 'try_to_generate': try_to_generate, @@ -1630,41 +1715,7 @@ def set_up_configuration(args=None, logfile=None, testing=False, silent=False, r init_build_options(build_options=build_options, cmdline_options=options) # done here instead of in _postprocess_include because github integration requires build_options to be initialized - if eb_go.options.include_easyblocks_from_pr: - try: - easyblock_prs = [int(x) for x in eb_go.options.include_easyblocks_from_pr] - except ValueError: - raise EasyBuildError("Argument to --include-easyblocks-from-pr must be a comma separated list of PR #s.") - - if eb_go.options.include_easyblocks: - # check if you are including the same easyblock twice - included_paths = expand_glob_paths(eb_go.options.include_easyblocks) - included_from_file = set([os.path.basename(eb) for eb in included_paths]) - - for easyblock_pr in easyblock_prs: - easyblocks_from_pr = fetch_easyblocks_from_pr(easyblock_pr) - included_from_pr = set([os.path.basename(eb) for eb in easyblocks_from_pr]) - - if eb_go.options.include_easyblocks: - included_twice = included_from_pr & included_from_file - if included_twice: - warning_msg = "One or more easyblocks included from multiple locations: %s " \ - % ', '.join(included_twice) - warning_msg += "(the one(s) from PR #%s will be used)" % easyblock_pr - print_warning(warning_msg) - - for easyblock in included_from_pr: - print_msg("easyblock %s included from PR #%s" % (easyblock, easyblock_pr), log=log) - - include_easyblocks(eb_go.options.tmpdir, easyblocks_from_pr) - - if eb_go.options.list_easyblocks: - msg = list_easyblocks(eb_go.options.list_easyblocks, eb_go.options.output_format) - if eb_go.options.unittest_file: - log.info(msg) - else: - print(msg) - cleanup_and_exit(tmpdir) + handle_include_easyblocks_from(eb_go.options, log) check_python_version() diff --git a/easybuild/tools/output.py b/easybuild/tools/output.py index 0dc5b3b362..b6da8a9245 100644 --- a/easybuild/tools/output.py +++ b/easybuild/tools/output.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # # -# Copyright 2021-2023 Ghent University +# Copyright 2021-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/package/package_naming_scheme/easybuild_deb_friendly_pns.py b/easybuild/tools/package/package_naming_scheme/easybuild_deb_friendly_pns.py index 9ae9b37419..033687fac1 100644 --- a/easybuild/tools/package/package_naming_scheme/easybuild_deb_friendly_pns.py +++ b/easybuild/tools/package/package_naming_scheme/easybuild_deb_friendly_pns.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- vim: set fileencoding=utf-8 ## -# Copyright 2015-2022 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/package/package_naming_scheme/easybuild_pns.py b/easybuild/tools/package/package_naming_scheme/easybuild_pns.py index a6543a7d53..7a53a86101 100644 --- a/easybuild/tools/package/package_naming_scheme/easybuild_pns.py +++ b/easybuild/tools/package/package_naming_scheme/easybuild_pns.py @@ -1,5 +1,5 @@ ## -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/package/package_naming_scheme/pns.py b/easybuild/tools/package/package_naming_scheme/pns.py index 081a94b073..8683ae8d37 100644 --- a/easybuild/tools/package/package_naming_scheme/pns.py +++ b/easybuild/tools/package/package_naming_scheme/pns.py @@ -1,5 +1,5 @@ ## -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/package/utilities.py b/easybuild/tools/package/utilities.py index 087084c687..bf55fdcff1 100644 --- a/easybuild/tools/package/utilities.py +++ b/easybuild/tools/package/utilities.py @@ -1,5 +1,5 @@ ## -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -58,7 +58,7 @@ def avail_package_naming_schemes(): They are loaded from the easybuild.package.package_naming_scheme namespace """ import_available_modules('easybuild.tools.package.package_naming_scheme') - class_dict = dict([(x.__name__, x) for x in get_subclasses(PackageNamingScheme)]) + class_dict = {x.__name__: x for x in get_subclasses(PackageNamingScheme)} return class_dict diff --git a/easybuild/tools/parallelbuild.py b/easybuild/tools/parallelbuild.py index 6c94517c69..3ab31e1efc 100644 --- a/easybuild/tools/parallelbuild.py +++ b/easybuild/tools/parallelbuild.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/py2vs3/__init__.py b/easybuild/tools/py2vs3/__init__.py index 5d9854b39f..5d45e11dc3 100644 --- a/easybuild/tools/py2vs3/__init__.py +++ b/easybuild/tools/py2vs3/__init__.py @@ -1,5 +1,5 @@ # -# Copyright 2019-2023 Ghent University +# Copyright 2019-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/py2vs3/py2.py b/easybuild/tools/py2vs3/py2.py index 1fec4650b1..f619279060 100644 --- a/easybuild/tools/py2vs3/py2.py +++ b/easybuild/tools/py2vs3/py2.py @@ -1,5 +1,5 @@ # -# Copyright 2019-2023 Ghent University +# Copyright 2019-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/py2vs3/py3.py b/easybuild/tools/py2vs3/py3.py index 8d9145179d..62e7a93723 100644 --- a/easybuild/tools/py2vs3/py3.py +++ b/easybuild/tools/py2vs3/py3.py @@ -1,5 +1,5 @@ # -# Copyright 2019-2023 Ghent University +# Copyright 2019-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/repository/filerepo.py b/easybuild/tools/repository/filerepo.py index c7d0cb366d..b18c3c6159 100644 --- a/easybuild/tools/repository/filerepo.py +++ b/easybuild/tools/repository/filerepo.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/repository/gitrepo.py b/easybuild/tools/repository/gitrepo.py index 97fc6c33da..feaf8cb2ad 100644 --- a/easybuild/tools/repository/gitrepo.py +++ b/easybuild/tools/repository/gitrepo.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/repository/hgrepo.py b/easybuild/tools/repository/hgrepo.py index 8cdf145b52..83a7890cc3 100644 --- a/easybuild/tools/repository/hgrepo.py +++ b/easybuild/tools/repository/hgrepo.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/repository/repository.py b/easybuild/tools/repository/repository.py index cbd33ab654..e84c9d3cc5 100644 --- a/easybuild/tools/repository/repository.py +++ b/easybuild/tools/repository/repository.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -146,7 +146,7 @@ def avail_repositories(check_useable=True): """ import_available_modules('easybuild.tools.repository') - class_dict = dict([(x.__name__, x) for x in get_subclasses(Repository) if x.USABLE or not check_useable]) + class_dict = {x.__name__: x for x in get_subclasses(Repository) if x.USABLE or not check_useable} if 'FileRepository' not in class_dict: raise EasyBuildError("avail_repositories: FileRepository missing from list of repositories") diff --git a/easybuild/tools/repository/svnrepo.py b/easybuild/tools/repository/svnrepo.py index 6c955c7fd0..79f593b1ee 100644 --- a/easybuild/tools/repository/svnrepo.py +++ b/easybuild/tools/repository/svnrepo.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/robot.py b/easybuild/tools/robot.py index 68a4c9028b..5189769929 100644 --- a/easybuild/tools/robot.py +++ b/easybuild/tools/robot.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -54,7 +54,7 @@ _log = fancylogger.getLogger('tools.robot', fname=False) -def det_robot_path(robot_paths_option, tweaked_ecs_paths, pr_paths, auto_robot=False): +def det_robot_path(robot_paths_option, tweaked_ecs_paths, extra_ec_paths, auto_robot=False): """Determine robot path.""" robot_path = robot_paths_option[:] _log.info("Using robot path(s): %s", robot_path) @@ -70,9 +70,9 @@ def det_robot_path(robot_paths_option, tweaked_ecs_paths, pr_paths, auto_robot=F _log.info("Prepended list of robot search paths with %s and appended with %s: %s", tweaked_ecs_path, tweaked_ecs_deps_path, robot_path) - if pr_paths is not None: - robot_path.extend(pr_paths) - _log.info("Extended list of robot search paths with %s: %s", pr_paths, robot_path) + if extra_ec_paths is not None: + robot_path.extend(extra_ec_paths) + _log.info("Extended list of robot search paths with %s: %s", extra_ec_paths, robot_path) return robot_path @@ -288,16 +288,18 @@ def dry_run(easyconfigs, modtool, short=False): return '\n'.join(lines) -def missing_deps(easyconfigs, modtool): +def missing_deps(easyconfigs, modtool, terse=False): """ Determine subset of easyconfigs for which no module is installed yet. """ ordered_ecs = resolve_dependencies(easyconfigs, modtool, retain_all_deps=True, raise_error_missing_ecs=False) missing = skip_available(ordered_ecs, modtool) - if missing: + if terse: + lines = [os.path.basename(x['ec'].path) for x in missing] + elif missing: lines = ['', "%d out of %d required modules missing:" % (len(missing), len(ordered_ecs)), ''] - for ec in [x['ec'] for x in missing]: + for ec in (x['ec'] for x in missing): if ec.short_mod_name != ec.full_mod_name: modname = '%s | %s' % (ec.mod_subdir, ec.short_mod_name) else: diff --git a/easybuild/tools/run.py b/easybuild/tools/run.py index 0685fb37f7..30f413be55 100644 --- a/easybuild/tools/run.py +++ b/easybuild/tools/run.py @@ -1,5 +1,5 @@ # # -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/systemtools.py b/easybuild/tools/systemtools.py index 78ba312203..73eb657510 100644 --- a/easybuild/tools/systemtools.py +++ b/easybuild/tools/systemtools.py @@ -1,5 +1,5 @@ ## -# Copyright 2011-2023 Ghent University +# Copyright 2011-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -1340,8 +1340,8 @@ def det_pypkg_version(pkg_name, imported_pkg, import_name=None): except pkg_resources.DistributionNotFound as err: _log.debug("%s Python package not found: %s", pkg_name, err) - if version is None and hasattr(imported_pkg, '__version__'): - version = imported_pkg.__version__ + if version is None: + version = getattr(imported_pkg, '__version__', None) return version diff --git a/easybuild/tools/testing.py b/easybuild/tools/testing.py index 68eedc23ce..881788337e 100644 --- a/easybuild/tools/testing.py +++ b/easybuild/tools/testing.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -178,7 +178,7 @@ def create_test_report(msg, ecs_with_res, init_session_state, pr_nrs=None, gist_ ]) test_report.extend([ "#### Test result", - "%s" % msg, + msg, "", ]) @@ -336,6 +336,14 @@ def post_pr_test_report(pr_nrs, repo_type, test_report, msg, init_session_state, comment_lines = ["Test report by @%s" % github_user] + if build_option('include_easyblocks_from_commit'): + if repo_type == GITHUB_EASYCONFIGS_REPO: + easyblocks_commit = build_option('include_easyblocks_from_commit') + url = 'https://github.com/%s/%s/commit/%s' % (pr_target_account, GITHUB_EASYBLOCKS_REPO, easyblocks_commit) + comment_lines.append("Using easyblocks from %s" % url) + else: + raise EasyBuildError("Don't know how to submit test reports to repo %s.", repo_type) + if build_option('include_easyblocks_from_pr'): if repo_type == GITHUB_EASYCONFIGS_REPO: easyblocks_pr_nrs = [int(x) for x in build_option('include_easyblocks_from_pr')] diff --git a/easybuild/tools/toolchain/__init__.py b/easybuild/tools/toolchain/__init__.py index 876d16c44f..cf755a8e40 100644 --- a/easybuild/tools/toolchain/__init__.py +++ b/easybuild/tools/toolchain/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/toolchain/compiler.py b/easybuild/tools/toolchain/compiler.py index 32634032fc..faf8f03d88 100644 --- a/easybuild/tools/toolchain/compiler.py +++ b/easybuild/tools/toolchain/compiler.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -323,7 +323,7 @@ def _set_optimal_architecture(self, default_optarch=None): optarch = build_option('optarch') # --optarch is specified with flags to use - if optarch is not None and isinstance(optarch, dict): + if isinstance(optarch, dict): # optarch has been validated as complex string with multiple compilers and converted to a dictionary # first try module names, then the family in optarch current_compiler_names = (getattr(self, 'COMPILER_MODULE_NAME', []) + @@ -338,14 +338,12 @@ def _set_optimal_architecture(self, default_optarch=None): self.log.info("_set_optimal_architecture: no optarch found for compiler %s. Ignoring option.", current_compiler) - use_generic = False - if optarch is not None: - # optarch has been parsed as a simple string - if isinstance(optarch, string_type): - if optarch == OPTARCH_GENERIC: - use_generic = True - else: - raise EasyBuildError("optarch is neither an string or a dict %s. This should never happen", optarch) + if isinstance(optarch, string_type): + use_generic = (optarch == OPTARCH_GENERIC) + elif optarch is None: + use_generic = False + else: + raise EasyBuildError("optarch is neither an string or a dict %s. This should never happen", optarch) if use_generic: if (self.arch, self.cpu_family) in (self.COMPILER_GENERIC_OPTION or []): @@ -360,10 +358,11 @@ def _set_optimal_architecture(self, default_optarch=None): optarch = self.COMPILER_OPTIMAL_ARCHITECTURE_OPTION[(self.arch, self.cpu_family)] if optarch is not None: - self.log.info("_set_optimal_architecture: using %s as optarch for %s.", optarch, self.arch) + optarch_log_str = optarch or 'no flags' + self.log.info("_set_optimal_architecture: using %s as optarch for %s/%s.", + optarch_log_str, self.arch, self.cpu_family) self.options.options_map['optarch'] = optarch - - if self.options.options_map.get('optarch', None) is None: + elif self.options.options_map.get('optarch', None) is None: optarch_flags_str = "%soptarch flags" % ('', 'generic ')[use_generic] error_msg = "Don't know how to set %s for %s/%s! " % (optarch_flags_str, self.arch, self.cpu_family) error_msg += "Use --optarch='' to override (see " diff --git a/easybuild/tools/toolchain/constants.py b/easybuild/tools/toolchain/constants.py index 5655f71961..643e8b4d21 100644 --- a/easybuild/tools/toolchain/constants.py +++ b/easybuild/tools/toolchain/constants.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/toolchain/fft.py b/easybuild/tools/toolchain/fft.py index c0e1dedd1a..b7191d5a26 100644 --- a/easybuild/tools/toolchain/fft.py +++ b/easybuild/tools/toolchain/fft.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/toolchain/linalg.py b/easybuild/tools/toolchain/linalg.py index b7ce694ff7..fd74615c4a 100644 --- a/easybuild/tools/toolchain/linalg.py +++ b/easybuild/tools/toolchain/linalg.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -212,9 +212,9 @@ def _set_blacs_variables(self): """Set BLACS related variables""" lib_map = {} - if hasattr(self, 'BLAS_LIB_MAP') and self.BLAS_LIB_MAP is not None: + if getattr(self, 'BLAS_LIB_MAP', None) is not None: lib_map.update(self.BLAS_LIB_MAP) - if hasattr(self, 'BLACS_LIB_MAP') and self.BLACS_LIB_MAP is not None: + if getattr(self, 'BLACS_LIB_MAP', None) is not None: lib_map.update(self.BLACS_LIB_MAP) # BLACS @@ -254,11 +254,11 @@ def _set_scalapack_variables(self): raise EasyBuildError("_set_blas_variables: SCALAPACK_LIB not set") lib_map = {} - if hasattr(self, 'BLAS_LIB_MAP') and self.BLAS_LIB_MAP is not None: + if getattr(self, 'BLAS_LIB_MAP', None) is not None: lib_map.update(self.BLAS_LIB_MAP) - if hasattr(self, 'BLACS_LIB_MAP') and self.BLACS_LIB_MAP is not None: + if getattr(self, 'BLACS_LIB_MAP', None) is not None: lib_map.update(self.BLACS_LIB_MAP) - if hasattr(self, 'SCALAPACK_LIB_MAP') and self.SCALAPACK_LIB_MAP is not None: + if getattr(self, 'SCALAPACK_LIB_MAP', None) is not None: lib_map.update(self.SCALAPACK_LIB_MAP) self.SCALAPACK_LIB = self.variables.nappend('LIBSCALAPACK_ONLY', [x % lib_map for x in self.SCALAPACK_LIB]) diff --git a/easybuild/tools/toolchain/mpi.py b/easybuild/tools/toolchain/mpi.py index 37c964907a..0ea2714490 100644 --- a/easybuild/tools/toolchain/mpi.py +++ b/easybuild/tools/toolchain/mpi.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/toolchain/options.py b/easybuild/tools/toolchain/options.py index 06dcf9ee5d..391a2831e0 100644 --- a/easybuild/tools/toolchain/options.py +++ b/easybuild/tools/toolchain/options.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/toolchain/toolchain.py b/easybuild/tools/toolchain/toolchain.py index a16fe35dc0..f928215fd4 100644 --- a/easybuild/tools/toolchain/toolchain.py +++ b/easybuild/tools/toolchain/toolchain.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -163,13 +163,13 @@ def _is_toolchain_for(cls, name): """see if this class can provide support for toolchain named name""" # TODO report later in the initialization the found version if name: - if hasattr(cls, 'NAME') and name == cls.NAME: - return True - else: + try: + return name == cls.NAME + except AttributeError: return False else: # is no name is supplied, check whether class can be used as a toolchain - return hasattr(cls, 'NAME') and cls.NAME + return bool(getattr(cls, 'NAME', None)) _is_toolchain_for = classmethod(_is_toolchain_for) @@ -330,10 +330,12 @@ def _copy_class_constants(self): if key not in self.CLASS_CONSTANT_COPIES: self.CLASS_CONSTANT_COPIES[key] = {} for cst in self.CLASS_CONSTANTS_TO_RESTORE: - if hasattr(self, cst): - self.CLASS_CONSTANT_COPIES[key][cst] = copy.deepcopy(getattr(self, cst)) - else: + try: + value = getattr(self, cst) + except AttributeError: raise EasyBuildError("Class constant '%s' to be restored does not exist in %s", cst, self) + else: + self.CLASS_CONSTANT_COPIES[key][cst] = copy.deepcopy(value) self.log.devel("Copied class constants: %s", self.CLASS_CONSTANT_COPIES[key]) @@ -342,10 +344,12 @@ def _restore_class_constants(self): key = self.__class__ for cst in self.CLASS_CONSTANT_COPIES[key]: newval = copy.deepcopy(self.CLASS_CONSTANT_COPIES[key][cst]) - if hasattr(self, cst): - self.log.devel("Restoring class constant '%s' to %s (was: %s)", cst, newval, getattr(self, cst)) - else: + try: + oldval = getattr(self, cst) + except AttributeError: self.log.devel("Restoring (currently undefined) class constant '%s' to %s", cst, newval) + else: + self.log.devel("Restoring class constant '%s' to %s (was: %s)", cst, newval, oldval) setattr(self, cst, newval) @@ -941,10 +945,11 @@ def is_rpath_wrapper(path): """ Check whether command at specified location already is an RPATH wrapper script rather than the actual command """ - in_rpath_wrappers_dir = os.path.basename(os.path.dirname(os.path.dirname(path))) == RPATH_WRAPPERS_SUBDIR + if os.path.basename(os.path.dirname(os.path.dirname(path))) != RPATH_WRAPPERS_SUBDIR: + return False + # Check if `rpath_args`` is called in the file # need to use binary mode to read the file, since it may be an actual compiler command (which is a binary file) - calls_rpath_args = b'rpath_args.py $CMD' in read_file(path, mode='rb') - return in_rpath_wrappers_dir and calls_rpath_args + return b'rpath_args.py $CMD' in read_file(path, mode='rb') def prepare_rpath_wrappers(self, rpath_filter_dirs=None, rpath_include_dirs=None): """ diff --git a/easybuild/tools/toolchain/toolchainvariables.py b/easybuild/tools/toolchain/toolchainvariables.py index 286b32aea3..dbb5686040 100644 --- a/easybuild/tools/toolchain/toolchainvariables.py +++ b/easybuild/tools/toolchain/toolchainvariables.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/toolchain/utilities.py b/easybuild/tools/toolchain/utilities.py index 48a586c567..8047778391 100644 --- a/easybuild/tools/toolchain/utilities.py +++ b/easybuild/tools/toolchain/utilities.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -63,7 +63,7 @@ def search_toolchain(name): package = easybuild.tools.toolchain check_attr_name = '%s_PROCESSED' % TC_CONST_PREFIX - if not hasattr(package, check_attr_name) or not getattr(package, check_attr_name): + if not getattr(package, check_attr_name, None): # import all available toolchains, so we know about them tc_modules = import_available_modules('easybuild.toolchains') @@ -76,7 +76,7 @@ def search_toolchain(name): if hasattr(elem, '__module__'): # exclude the toolchain class defined in that module if not tc_mod.__file__ == sys.modules[elem.__module__].__file__: - elem_name = elem.__name__ if hasattr(elem, '__name__') else elem + elem_name = getattr(elem, '__name__', elem) _log.debug("Adding %s to list of imported classes used for looking for constants", elem_name) mod_classes.append(elem) @@ -89,13 +89,14 @@ def search_toolchain(name): tc_const_value = getattr(mod_class_mod, elem) _log.debug("Found constant %s ('%s') in module %s, adding it to %s", tc_const_name, tc_const_value, mod_class_mod.__name__, package.__name__) - if hasattr(package, tc_const_name): + try: cur_value = getattr(package, tc_const_name) + except AttributeError: + setattr(package, tc_const_name, tc_const_value) + else: if not tc_const_value == cur_value: raise EasyBuildError("Constant %s.%s defined as '%s', can't set it to '%s'.", package.__name__, tc_const_name, cur_value, tc_const_value) - else: - setattr(package, tc_const_name, tc_const_value) # indicate that processing of toolchain constants is done, so it's not done again setattr(package, check_attr_name, True) diff --git a/easybuild/tools/toolchain/variables.py b/easybuild/tools/toolchain/variables.py index c201f8a6f8..482f989480 100644 --- a/easybuild/tools/toolchain/variables.py +++ b/easybuild/tools/toolchain/variables.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/utilities.py b/easybuild/tools/utilities.py index b879a4005c..8f6407e55d 100644 --- a/easybuild/tools/utilities.py +++ b/easybuild/tools/utilities.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/variables.py b/easybuild/tools/variables.py index e5fa534c45..cef771f3d8 100644 --- a/easybuild/tools/variables.py +++ b/easybuild/tools/variables.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/easybuild/tools/version.py b/easybuild/tools/version.py index e3d5feb017..0e82ff2ce9 100644 --- a/easybuild/tools/version.py +++ b/easybuild/tools/version.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -45,7 +45,7 @@ # recent setuptools versions will *TRANSFORM* something like 'X.Y.Zdev' into 'X.Y.Z.dev0', with a warning like # UserWarning: Normalizing '2.4.0dev' to '2.4.0.dev0' # This causes problems further up the dependency chain... -VERSION = LooseVersion('4.9.0') +VERSION = LooseVersion('4.9.1') UNKNOWN = 'UNKNOWN' diff --git a/eb b/eb index d214d82b34..ad14ba61d0 100755 --- a/eb +++ b/eb @@ -1,6 +1,6 @@ #!/bin/bash ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/setup.py b/setup.py index 72ffd0e19a..82bae3aa2f 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/__init__.py b/test/__init__.py index 8793b2e4e1..20c9130dcc 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/__init__.py b/test/framework/__init__.py index c6a455e689..fae73ca9e6 100644 --- a/test/framework/__init__.py +++ b/test/framework/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/asyncprocess.py b/test/framework/asyncprocess.py index f8db1927d8..c7eced6c48 100644 --- a/test/framework/asyncprocess.py +++ b/test/framework/asyncprocess.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/build_log.py b/test/framework/build_log.py index a1792b998f..15f6984099 100644 --- a/test/framework/build_log.py +++ b/test/framework/build_log.py @@ -1,5 +1,5 @@ # # -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/config.py b/test/framework/config.py index 4b42672cfc..55234d31b9 100644 --- a/test/framework/config.py +++ b/test/framework/config.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/containers.py b/test/framework/containers.py index bd6dfde7f6..1d9abbf8e4 100644 --- a/test/framework/containers.py +++ b/test/framework/containers.py @@ -1,5 +1,5 @@ # # -# Copyright 2018-2023 Ghent University +# Copyright 2018-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/docs.py b/test/framework/docs.py index 70280892e4..6b5b68ad17 100644 --- a/test/framework/docs.py +++ b/test/framework/docs.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index 5e2407575d..e6b54e0bc8 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -645,6 +645,7 @@ def test_make_module_extra(self): # also check how absolute paths specified in modexself.contents = '\n'.join([ self.contents += "\nmodextrapaths = {'TEST_PATH_VAR': ['foo', '/test/absolute/path', 'bar']}" + self.contents += "\nmodextrapaths_append = {'TEST_PATH_VAR_APPEND': ['foo', '/test/absolute/path', 'bar']}" self.writeEC() ec = EasyConfig(self.eb_file) eb = EasyBlock(ec) @@ -657,6 +658,7 @@ def test_make_module_extra(self): # allow use of absolute paths, and verify contents of module self.contents += "\nallow_prepend_abs_path = True" + self.contents += "\nallow_append_abs_path = True" self.writeEC() ec = EasyConfig(self.eb_file) eb = EasyBlock(ec) @@ -675,6 +677,9 @@ def test_make_module_extra(self): r"^prepend[-_]path.*TEST_PATH_VAR.*root.*foo", r"^prepend[-_]path.*TEST_PATH_VAR.*/test/absolute/path", r"^prepend[-_]path.*TEST_PATH_VAR.*root.*bar", + r"^append[-_]path.*TEST_PATH_VAR_APPEND.*root.*foo", + r"^append[-_]path.*TEST_PATH_VAR_APPEND.*/test/absolute/path", + r"^append[-_]path.*TEST_PATH_VAR_APPEND.*root.*bar", ] for pattern in patterns: self.assertTrue(re.search(pattern, txt, re.M), "Pattern '%s' found in: %s" % (pattern, txt)) @@ -1173,6 +1178,7 @@ def test_make_module_step(self): 'PATH': ('xbin', 'pibin'), 'CPATH': 'pi/include', } + modextrapaths_append = {'APPEND_PATH': 'append_path'} self.contents = '\n'.join([ 'easyblock = "ConfigureMake"', 'name = "%s"' % name, @@ -1186,6 +1192,7 @@ def test_make_module_step(self): "hiddendependencies = [('test', '1.2.3'), ('OpenMPI', '2.1.2-GCC-6.4.0-2.28')]", "modextravars = %s" % str(modextravars), "modextrapaths = %s" % str(modextrapaths), + "modextrapaths_append = %s" % str(modextrapaths_append), ]) # test if module is generated correctly @@ -1256,6 +1263,18 @@ def test_make_module_step(self): num_prepends = len(regex.findall(txt)) self.assertEqual(num_prepends, 1, "Expected exactly 1 %s command in %s" % (regex.pattern, txt)) + for (key, vals) in modextrapaths_append.items(): + if isinstance(vals, string_type): + vals = [vals] + for val in vals: + if get_module_syntax() == 'Tcl': + regex = re.compile(r'^append-path\s+%s\s+\$root/%s$' % (key, val), re.M) + elif get_module_syntax() == 'Lua': + regex = re.compile(r'^append_path\("%s", pathJoin\(root, "%s"\)\)$' % (key, val), re.M) + else: + self.fail("Unknown module syntax: %s" % get_module_syntax()) + self.assertTrue(regex.search(txt), "Pattern %s found in %s" % (regex.pattern, txt)) + for (name, ver) in [('GCC', '6.4.0-2.28')]: if get_module_syntax() == 'Tcl': regex = re.compile(r'^\s*module load %s\s*$' % os.path.join(name, ver), re.M) diff --git a/test/framework/easyconfig.py b/test/framework/easyconfig.py index dda5c0a05b..45e2852221 100644 --- a/test/framework/easyconfig.py +++ b/test/framework/easyconfig.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -733,6 +733,40 @@ def test_tweaking(self): # cleanup os.remove(tweaked_fn) + def test_alt_easyconfig_paths(self): + """Test alt_easyconfig_paths function that collects list of additional paths for easyconfig files.""" + + tweaked_ecs_path, extra_ecs_path = alt_easyconfig_paths(self.test_prefix) + self.assertEqual(tweaked_ecs_path, None) + self.assertEqual(extra_ecs_path, []) + + tweaked_ecs_path, extra_ecs_path = alt_easyconfig_paths(self.test_prefix, tweaked_ecs=True) + self.assertTrue(tweaked_ecs_path) + self.assertTrue(isinstance(tweaked_ecs_path, tuple)) + self.assertEqual(len(tweaked_ecs_path), 2) + self.assertEqual(tweaked_ecs_path[0], os.path.join(self.test_prefix, 'tweaked_easyconfigs')) + self.assertEqual(tweaked_ecs_path[1], os.path.join(self.test_prefix, 'tweaked_dep_easyconfigs')) + self.assertEqual(extra_ecs_path, []) + + tweaked_ecs_path, extra_ecs_path = alt_easyconfig_paths(self.test_prefix, from_prs=[123, 456]) + self.assertEqual(tweaked_ecs_path, None) + self.assertTrue(extra_ecs_path) + self.assertTrue(isinstance(extra_ecs_path, list)) + self.assertEqual(len(extra_ecs_path), 2) + self.assertEqual(extra_ecs_path[0], os.path.join(self.test_prefix, 'files_pr123')) + self.assertEqual(extra_ecs_path[1], os.path.join(self.test_prefix, 'files_pr456')) + + tweaked_ecs_path, extra_ecs_path = alt_easyconfig_paths(self.test_prefix, from_prs=[123, 456], + review_pr=789, from_commit='c0ff33') + self.assertEqual(tweaked_ecs_path, None) + self.assertTrue(extra_ecs_path) + self.assertTrue(isinstance(extra_ecs_path, list)) + self.assertEqual(len(extra_ecs_path), 4) + self.assertEqual(extra_ecs_path[0], os.path.join(self.test_prefix, 'files_pr123')) + self.assertEqual(extra_ecs_path[1], os.path.join(self.test_prefix, 'files_pr456')) + self.assertEqual(extra_ecs_path[2], os.path.join(self.test_prefix, 'files_pr789')) + self.assertEqual(extra_ecs_path[3], os.path.join(self.test_prefix, 'files_commit_c0ff33')) + def test_tweak_multiple_tcs(self): """Test that tweaking variables of ECs from multiple toolchains works""" test_easyconfigs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs') @@ -1151,6 +1185,7 @@ def test_templating_constants(self): 'R: %%(rver)s, %%(rmajver)s, %%(rminver)s, %%(rshortver)s', ]), 'modextrapaths = {"PI_MOD_NAME": "%%(module_name)s"}', + 'modextrapaths_append = {"PATH_APPEND": "appended_path"}', 'license_file = HOME + "/licenses/PI/license.txt"', "github_account = 'easybuilders'", ]) % inp @@ -1191,6 +1226,7 @@ def test_templating_constants(self): self.assertEqual(ec['modloadmsg'], expected) self.assertEqual(ec['modunloadmsg'], expected) self.assertEqual(ec['modextrapaths'], {'PI_MOD_NAME': 'PI/3.04-Python-2.7.10'}) + self.assertEqual(ec['modextrapaths_append'], {'PATH_APPEND': 'appended_path'}) self.assertEqual(ec['license_file'], os.path.join(os.environ['HOME'], 'licenses', 'PI', 'license.txt')) # test the escaping insanity here (ie all the crap we allow in easyconfigs) @@ -3621,7 +3657,7 @@ def test_resolve_template(self): def test_det_subtoolchain_version(self): """Test det_subtoolchain_version function""" _, all_tc_classes = search_toolchain('') - subtoolchains = dict((tc_class.NAME, getattr(tc_class, 'SUBTOOLCHAIN', None)) for tc_class in all_tc_classes) + subtoolchains = {tc_class.NAME: getattr(tc_class, 'SUBTOOLCHAIN', None) for tc_class in all_tc_classes} optional_toolchains = set(tc_class.NAME for tc_class in all_tc_classes if getattr(tc_class, 'OPTIONAL', False)) current_tc = {'name': 'fosscuda', 'version': '2018a'} diff --git a/test/framework/easyconfigformat.py b/test/framework/easyconfigformat.py index e806a88378..7b84a2c867 100644 --- a/test/framework/easyconfigformat.py +++ b/test/framework/easyconfigformat.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/easyconfigparser.py b/test/framework/easyconfigparser.py index 9a17d8f0a5..fa943df938 100644 --- a/test/framework/easyconfigparser.py +++ b/test/framework/easyconfigparser.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/easyconfigversion.py b/test/framework/easyconfigversion.py index 5ef706a72a..4da54b450a 100644 --- a/test/framework/easyconfigversion.py +++ b/test/framework/easyconfigversion.py @@ -1,5 +1,5 @@ # # -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/easystack.py b/test/framework/easystack.py index 91efcc94b3..a51059d280 100644 --- a/test/framework/easystack.py +++ b/test/framework/easystack.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/ebconfigobj.py b/test/framework/ebconfigobj.py index d4d81995d8..169fe988a2 100644 --- a/test/framework/ebconfigobj.py +++ b/test/framework/ebconfigobj.py @@ -1,5 +1,5 @@ # # -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/environment.py b/test/framework/environment.py index 9a81e17486..f184c6b9c7 100644 --- a/test/framework/environment.py +++ b/test/framework/environment.py @@ -1,5 +1,5 @@ # # -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -90,8 +90,7 @@ def test_modify_env(self): # prepare test environment first: # keys in new_env should not be set yet, keys in old_env are expected to be set for key in new_env_vars: - if key in os.environ: - del os.environ[key] + os.environ.pop(key, None) for key in old_env_vars: os.environ[key] = old_env_vars[key] diff --git a/test/framework/filetools.py b/test/framework/filetools.py index 3b879bef85..63cd0a93b7 100644 --- a/test/framework/filetools.py +++ b/test/framework/filetools.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -104,7 +104,7 @@ def test_extract_cmd(self): ('test.txz', "unset TAPE; unxz test.txz --stdout | tar x"), ('test.iso', "7z x test.iso"), ('test.tar.Z', "tar xzf test.tar.Z"), - ('test.foo.bar.sh', "cp -a test.foo.bar.sh ."), + ('test.foo.bar.sh', "cp -dR test.foo.bar.sh ."), # check whether extension is stripped correct to determine name of target file # cfr. https://github.com/easybuilders/easybuild-framework/pull/3705 ('testbz2.bz2', "bunzip2 -c testbz2.bz2 > testbz2"), @@ -320,7 +320,7 @@ def test_checksums(self): self.assertErrorRegex(EasyBuildError, error_pattern, ft.verify_checksum, fp, checksum) # make sure faulty checksums are reported - broken_checksums = dict([(typ, val[:-3] + 'foo') for (typ, val) in known_checksums.items()]) + broken_checksums = {typ: (val[:-3] + 'foo') for typ, val in known_checksums.items()} for checksum_type, checksum in broken_checksums.items(): self.assertFalse(ft.compute_checksum(fp, checksum_type=checksum_type) == checksum) self.assertFalse(ft.verify_checksum(fp, (checksum_type, checksum))) @@ -1505,8 +1505,7 @@ def test_find_flexlm_license(self): lic_server = '1234@example.license.server' # make test robust against environment in which $LM_LICENSE_FILE is defined - if 'LM_LICENSE_FILE' in os.environ: - del os.environ['LM_LICENSE_FILE'] + os.environ.pop('LM_LICENSE_FILE', None) # default return value self.assertEqual(ft.find_flexlm_license(), ([], None)) @@ -2630,8 +2629,7 @@ def test_find_eb_script(self): """Test find_eb_script function.""" # make sure $EB_SCRIPT_PATH is not set already (used as fallback mechanism in find_eb_script) - if 'EB_SCRIPT_PATH' in os.environ: - del os.environ['EB_SCRIPT_PATH'] + os.environ.pop('EB_SCRIPT_PATH', None) self.assertExists(ft.find_eb_script('rpath_args.py')) self.assertExists(ft.find_eb_script('rpath_wrapper_template.sh.in')) diff --git a/test/framework/format_convert.py b/test/framework/format_convert.py index 1bc3f764bb..e0add188b3 100644 --- a/test/framework/format_convert.py +++ b/test/framework/format_convert.py @@ -1,5 +1,5 @@ # # -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/general.py b/test/framework/general.py index 526fe07467..3837cecc87 100644 --- a/test/framework/general.py +++ b/test/framework/general.py @@ -1,5 +1,5 @@ ## -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/github.py b/test/framework/github.py index f011c89b4f..c4eb8c8854 100644 --- a/test/framework/github.py +++ b/test/framework/github.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -50,7 +50,8 @@ from easybuild.tools.filetools import read_file, write_file from easybuild.tools.github import GITHUB_EASYCONFIGS_REPO, GITHUB_EASYBLOCKS_REPO, GITHUB_MERGEABLE_STATE_CLEAN from easybuild.tools.github import VALID_CLOSE_PR_REASONS -from easybuild.tools.github import det_pr_title, is_patch_for, pick_default_branch +from easybuild.tools.github import det_pr_title, fetch_easyconfigs_from_commit, fetch_files_from_commit +from easybuild.tools.github import is_patch_for, pick_default_branch from easybuild.tools.testing import create_test_report, post_pr_test_report, session_state from easybuild.tools.py2vs3 import HTTPError, URLError, ascii_letters import easybuild.tools.github as gh @@ -536,6 +537,65 @@ def test_github_fetch_files_from_pr_cache(self): res = gh.fetch_easyblocks_from_pr(12345, tmpdir) self.assertEqual(sorted(pr12345_files), sorted(res)) + def test_fetch_files_from_commit(self): + """Test fetch_files_from_commit function.""" + + # easyconfigs commit to add EasyBuild-4.8.2.eb + test_commit = '7c83a553950c233943c7b0189762f8c05cfea852' + + # without specifying any files/repo, default is to use easybuilders/easybuilld-easyconfigs + # and determine which files were changed in the commit + res = fetch_files_from_commit(test_commit) + self.assertEqual(len(res), 1) + ec_path = res[0] + expected_path = 'ecs_commit_7c83a553950c233943c7b0189762f8c05cfea852/e/EasyBuild/EasyBuild-4.8.2.eb' + self.assertTrue(ec_path.endswith(expected_path)) + self.assertTrue(os.path.exists(ec_path)) + self.assertIn("version = '4.8.2'", read_file(ec_path)) + + # also test downloading a specific file from easyblocks repo + # commit that enables use_pip & co in PythonPackage easyblock + test_commit = 'd6f0cd7b586108e40f7cf1f1054bb07e16718caf' + res = fetch_files_from_commit(test_commit, files=['pythonpackage.py'], + github_account='easybuilders', github_repo='easybuild-easyblocks') + self.assertEqual(len(res), 1) + self.assertIn("'use_pip': [True,", read_file(res[0])) + + # test downloading with short commit, download_repo currently enforces using long commit + error_pattern = r"Specified commit SHA 7c83a55 for downloading easybuilders/easybuild-easyconfigs " + error_pattern += r"is not valid, must be full SHA-1 \(40 chars\)" + self.assertErrorRegex(EasyBuildError, error_pattern, fetch_files_from_commit, '7c83a55') + + # test downloading of non-existing commit + error_pattern = r"Failed to download diff for commit c0ff33c0ff33 of easybuilders/easybuild-easyconfigs" + self.assertErrorRegex(EasyBuildError, error_pattern, fetch_files_from_commit, 'c0ff33c0ff33') + + def test_fetch_easyconfigs_from_commit(self): + """Test fetch_easyconfigs_from_commit function.""" + + # commit in which easyconfigs for PyTables 3.9.2 + dependencies were added + test_commit = '6515b44cd84a20fe7876cb4bdaf3c0080e688566' + + # without specifying any files/repo, default is to determine which files were changed in the commit + res = fetch_easyconfigs_from_commit(test_commit) + self.assertEqual(len(res), 5) + expected_ec_filenames = ['Blosc-1.21.5-GCCcore-13.2.0.eb', 'Blosc2-2.13.2-GCCcore-13.2.0.eb', + 'PyTables-3.9.2-foss-2023b.eb', 'PyTables-3.9.2_fix-find-blosc2-dep.patch', + 'py-cpuinfo-9.0.0-GCCcore-13.2.0.eb'] + self.assertEqual(sorted([os.path.basename(f) for f in res]), expected_ec_filenames) + for ec_path in res: + self.assertTrue(os.path.exists(ec_path)) + if ec_path.endswith('.eb'): + self.assertIn("version =", read_file(ec_path)) + else: + self.assertTrue(ec_path.endswith('.patch')) + + # merge commit for release of EasyBuild v4.9.0 + test_commit = 'bdcc586189fcb3e5a340cddebb50d0e188c63cdc' + res = fetch_easyconfigs_from_commit(test_commit, files=['RELEASE_NOTES'], path=self.test_prefix) + self.assertEqual(len(res), 1) + self.assertIn("v4.9.0 (30 December 2023)", read_file(res[0])) + def test_github_fetch_latest_commit_sha(self): """Test fetch_latest_commit_sha function.""" if self.skip_github_tests: @@ -590,6 +650,34 @@ def test_github_download_repo(self): self.assertTrue(re.match('^[0-9a-f]{40}$', read_file(shafile))) self.assertExists(os.path.join(repodir, 'easybuild', 'easyblocks', '__init__.py')) + def test_github_download_repo_commit(self): + """Test downloading repo at specific commit (which does not require any GitHub token)""" + + # commit bdcc586189fcb3e5a340cddebb50d0e188c63cdc corresponds to easybuild-easyconfigs release v4.9.0 + test_commit = 'bdcc586189fcb3e5a340cddebb50d0e188c63cdc' + gh.download_repo(path=self.test_prefix, commit=test_commit) + repo_path = os.path.join(self.test_prefix, 'easybuilders', 'easybuild-easyconfigs-' + test_commit) + self.assertTrue(os.path.exists(repo_path)) + + setup_py_txt = read_file(os.path.join(repo_path, 'setup.py')) + self.assertTrue("VERSION = '4.9.0'" in setup_py_txt) + + # also check downloading non-default forked repo + test_commit = '434151c3dbf88b2382e8ead8655b4b2c01b92617' + gh.download_repo(path=self.test_prefix, account='boegel', repo='easybuild-framework', commit=test_commit) + repo_path = os.path.join(self.test_prefix, 'boegel', 'easybuild-framework-' + test_commit) + self.assertTrue(os.path.exists(repo_path)) + + release_notes_txt = read_file(os.path.join(repo_path, 'RELEASE_NOTES')) + self.assertTrue("v4.9.0 (30 December 2023)" in release_notes_txt) + + # short commit doesn't work, must be full commit ID + self.assertErrorRegex(EasyBuildError, "Specified commit SHA bdcc586 .* is not valid", gh.download_repo, + path=self.test_prefix, commit='bdcc586') + + self.assertErrorRegex(EasyBuildError, "Failed to download tarball .* commit", gh.download_repo, + path=self.test_prefix, commit='0000000000000000000000000000000000000000') + def test_install_github_token(self): """Test for install_github_token function.""" if self.skip_github_tests: diff --git a/test/framework/hooks.py b/test/framework/hooks.py index 152d2352a4..5e810ac0f9 100644 --- a/test/framework/hooks.py +++ b/test/framework/hooks.py @@ -1,5 +1,5 @@ # # -# Copyright 2017-2023 Ghent University +# Copyright 2017-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/include.py b/test/framework/include.py index b346f911ae..09a5925a2f 100644 --- a/test/framework/include.py +++ b/test/framework/include.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/lib.py b/test/framework/lib.py index 2f4149314c..7930e00567 100644 --- a/test/framework/lib.py +++ b/test/framework/lib.py @@ -1,5 +1,5 @@ # # -# Copyright 2018-2023 Ghent University +# Copyright 2018-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/license.py b/test/framework/license.py index 80c741908f..6dc79ac6a4 100644 --- a/test/framework/license.py +++ b/test/framework/license.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/module_generator.py b/test/framework/module_generator.py index a0c6131140..075cc3adbd 100644 --- a/test/framework/module_generator.py +++ b/test/framework/module_generator.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -82,7 +82,7 @@ def test_descr(self): '', 'Description', '===========', - "%s" % descr, + descr, '', '', "More information", @@ -107,7 +107,7 @@ def test_descr(self): '', 'Description', '===========', - "%s" % descr, + descr, '', '', "More information", @@ -137,7 +137,7 @@ def test_descr(self): '', 'Description', '===========', - "%s" % descr, + descr, '', '', "More information", @@ -161,7 +161,7 @@ def test_descr(self): '', 'Description', '===========', - "%s" % descr, + descr, '', '', "More information", @@ -900,8 +900,7 @@ def test_getenv_cmd(self): if self.MODULE_GENERATOR_CLASS == ModuleGeneratorTcl: # can't have $LMOD_QUIET set when testing with Tcl syntax, # otherwise we won't get the output produced by the test module file... - if 'LMOD_QUIET' in os.environ: - del os.environ['LMOD_QUIET'] + os.environ.pop('LMOD_QUIET', None) self.assertEqual('$::env(HOSTNAME)', self.modgen.getenv_cmd('HOSTNAME')) self.assertEqual('$::env(HOME)', self.modgen.getenv_cmd('HOME')) diff --git a/test/framework/modules.py b/test/framework/modules.py index c2460c7a11..82d03f6440 100644 --- a/test/framework/modules.py +++ b/test/framework/modules.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -99,8 +99,7 @@ def test_run_module(self): testdir = os.path.dirname(os.path.abspath(__file__)) for key in ['EBROOTGCC', 'EBROOTOPENMPI', 'EBROOTOPENBLAS']: - if key in os.environ: - del os.environ[key] + os.environ.pop(key, None) # arguments can be passed in two ways: multiple arguments, or just 1 list argument self.modtool.run_module('load', 'GCC/6.4.0-2.28') @@ -218,6 +217,12 @@ def test_avail(self): self.assertIn('bzip2/.1.0.6', ms) self.assertIn('toy/.0.0-deps', ms) self.assertIn('OpenMPI/.2.1.2-GCC-6.4.0-2.28', ms) + elif (isinstance(self.modtool, EnvironmentModules) + and StrictVersion(self.modtool.version) >= StrictVersion('4.6.0')): + # bzip2/.1.0.6 is not there, since that's a module file in Lua syntax + self.assertEqual(len(ms), TEST_MODULES_COUNT + 2) + self.assertIn('toy/.0.0-deps', ms) + self.assertIn('OpenMPI/.2.1.2-GCC-6.4.0-2.28', ms) else: self.assertEqual(len(ms), TEST_MODULES_COUNT) @@ -446,8 +451,7 @@ def test_load(self): self.assertEqual(self.modtool.loaded_modules()[-1], 'GCC/6.4.0-2.28') # set things up for checking that GCC does *not* get reloaded when requested - if 'EBROOTGCC' in os.environ: - del os.environ['EBROOTGCC'] + os.environ.pop('EBROOTGCC', None) self.modtool.load(['OpenMPI/2.1.2-GCC-6.4.0-2.28']) if isinstance(self.modtool, Lmod): # order of loaded modules only changes with Lmod @@ -1024,8 +1028,7 @@ def test_modules_tool_stateless(self): init_config() # make sure $LMOD_DEFAULT_MODULEPATH, since Lmod picks it up and tweaks $MODULEPATH to match it - if 'LMOD_DEFAULT_MODULEPATH' in os.environ: - del os.environ['LMOD_DEFAULT_MODULEPATH'] + os.environ.pop('LMOD_DEFAULT_MODULEPATH', None) self.reset_modulepath([os.path.join(self.test_prefix, 'Core')]) @@ -1047,8 +1050,7 @@ def test_modules_tool_stateless(self): self.modtool.load(['OpenMPI/2.1.2']) self.modtool.purge() - if 'LMOD_DEFAULT_MODULEPATH' in os.environ: - del os.environ['LMOD_DEFAULT_MODULEPATH'] + os.environ.pop('LMOD_DEFAULT_MODULEPATH', None) # reset $MODULEPATH, obtain new ModulesTool instance, # which should not remember anything w.r.t. previous $MODULEPATH value diff --git a/test/framework/modulestool.py b/test/framework/modulestool.py index fb991ad797..3cf4493f02 100644 --- a/test/framework/modulestool.py +++ b/test/framework/modulestool.py @@ -1,5 +1,5 @@ # # -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -209,6 +209,21 @@ def test_environment_modules_specific(self): mt = EnvironmentModules(testing=True) self.assertIsInstance(mt.loaded_modules(), list) # dummy usage + # initialize Environment Modules tool with non-official version number + # pass (fake) full path to 'modulecmd.tcl' via $MODULES_CMD + fake_path = os.path.join(self.test_installpath, 'libexec', 'modulecmd.tcl') + fake_modulecmd_txt = '\n'.join([ + 'puts stderr {Modules Release 5.3.1+unload-188-g14b6b59b (2023-10-21)}', + "puts {os.environ['FOO'] = 'foo'}", + ]) + write_file(fake_path, fake_modulecmd_txt) + os.chmod(fake_path, stat.S_IRUSR | stat.S_IXUSR) + os.environ['_module_raw'] = "() { eval `%s' bash $*`;\n}" % fake_path + os.environ['MODULES_CMD'] = fake_path + EnvironmentModules.COMMAND = fake_path + mt = EnvironmentModules(testing=True) + self.assertTrue(os.path.samefile(mt.cmd, fake_path), "%s - %s" % (mt.cmd, fake_path)) + def tearDown(self): """Testcase cleanup.""" super(ModulesToolTest, self).tearDown() @@ -217,8 +232,7 @@ def tearDown(self): if self.orig_module is not None: os.environ['module'] = self.orig_module else: - if 'module' in os.environ: - del os.environ['module'] + os.environ.pop('module', None) def suite(): diff --git a/test/framework/options.py b/test/framework/options.py index 4b5e1afce8..b2f3da43c1 100644 --- a/test/framework/options.py +++ b/test/framework/options.py @@ -1,5 +1,5 @@ # # -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -1422,6 +1422,70 @@ def test_github_copy_ec_from_pr(self): self.assertIn("name = 'ExifTool'", read_file(test_ec)) remove_file(test_ec) + def test_copy_ec_from_commit(self): + """Test combination of --copy-ec with --from-commit.""" + # note: --from-commit does not involve using GitHub API, so no GitHub token required + + # using easyconfigs commit to add EasyBuild-4.8.2.eb + test_commit = '7c83a553950c233943c7b0189762f8c05cfea852' + + test_dir = os.path.join(self.test_prefix, 'from_commit') + mkdir(test_dir, parents=True) + args = ['--copy-ec', '--from-commit=%s' % test_commit, test_dir] + try: + stdout = self.mocked_main(args) + except URLError as err: + print("Ignoring URLError '%s' in test_copy_ec_from_commit" % err) + + pattern = "_%s/e/EasyBuild/EasyBuild-4.8.2.eb copied to " % test_commit + self.assertIn(pattern, stdout) + copied_ecs = os.listdir(test_dir) + self.assertEqual(copied_ecs, ['EasyBuild-4.8.2.eb']) + + # cleanup + remove_dir(test_dir) + mkdir(test_dir) + + # test again, using extra argument (name of file to copy), without specifying target directory + # (should copy to current directory) + cwd = change_dir(test_dir) + args = ['--copy-ec', '--from-commit=%s' % test_commit, "EasyBuild-4.8.2.eb"] + try: + stdout = self.mocked_main(args) + except URLError as err: + print("Ignoring URLError '%s' in test_copy_ec_from_commit" % err) + + self.assertIn(pattern, stdout) + copied_ecs = os.listdir(test_dir) + self.assertEqual(copied_ecs, ['EasyBuild-4.8.2.eb']) + + # cleanup + change_dir(cwd) + remove_dir(test_dir) + mkdir(test_dir) + + # test with commit that touches a bunch of easyconfigs + test_commit = '49c887397b1a948e1909fc24bc905fdc1ad38388' + expected_ecs = [ + 'gompi-2023b.eb', + 'gfbf-2023b.eb', + 'ScaLAPACK-2.2.0-gompi-2023b-fb.eb', + 'foss-2023b.eb', + 'HPL-2.3-foss-2023b.eb', + 'FFTW.MPI-3.3.10-gompi-2023b.eb', + 'SciPy-bundle-2023.11-gfbf-2023b.eb', + 'OSU-Micro-Benchmarks-7.2-gompi-2023b.eb', + ] + args = ['--copy-ec', '--from-commit=%s' % test_commit, test_dir] + try: + stdout = self.mocked_main(args) + except URLError as err: + print("Ignoring URLError '%s' in test_copy_ec_from_commit" % err) + + copied_ecs = os.listdir(test_dir) + for ec in expected_ecs: + self.assertIn(ec, copied_ecs) + def test_dry_run(self): """Test dry run (long format).""" fd, dummylogfn = tempfile.mkstemp(prefix='easybuild-dummy', suffix='.log') @@ -1472,14 +1536,26 @@ def test_missing(self): ]) for opt in ['-M', '--missing-modules']: - self.mock_stderr(True) - self.mock_stdout(True) - self.eb_main(args + [opt], testing=False, raise_error=True) - stderr, stdout = self.get_stderr(), self.get_stdout() - self.mock_stderr(False) - self.mock_stdout(False) + with self.mocked_stdout_stderr(): + self.eb_main(args + [opt], testing=False, raise_error=True) + stderr, stdout = self.get_stderr(), self.get_stdout() self.assertFalse(stderr) self.assertIn(expected, stdout) + # --terse + with self.mocked_stdout_stderr(): + self.eb_main(args + ['-M', '--terse'], testing=False, raise_error=True) + stderr, stdout = self.get_stderr(), self.get_stdout() + self.assertFalse(stderr) + if mns == 'HierarchicalMNS': + expected = '\n'.join([ + "GCC-4.6.3.eb", + "intel-2018a.eb", + "toy-0.0-deps.eb", + "gzip-1.4-GCC-4.6.3.eb", + ]) + else: + expected = 'gzip-1.4-GCC-4.6.3.eb' + self.assertEqual(stdout, expected + '\n') def test_dry_run_short(self): """Test dry run (short format).""" @@ -2011,6 +2087,92 @@ def test_github_from_pr_x(self): except URLError as err: print("Ignoring URLError '%s' in test_from_pr_x" % err) + def test_from_commit(self): + """Test for --from-commit.""" + # note: --from-commit does not involve using GitHub API, so no GitHub token required + + # easyconfigs commit to add EasyBuild-4.8.2.eb + test_commit = '7c83a553950c233943c7b0189762f8c05cfea852' + + fd, dummylogfn = tempfile.mkstemp(prefix='easybuild-dummy', suffix='.log') + os.close(fd) + + tmpdir = tempfile.mkdtemp() + args = [ + '--from-commit=%s' % test_commit, + '--dry-run', + '--tmpdir=%s' % tmpdir, + ] + try: + outtxt = self.eb_main(args, logfile=dummylogfn, raise_error=True) + modules = [ + (tmpdir, 'EasyBuild/4.8.2'), + ] + for path_prefix, module in modules: + ec_fn = "%s.eb" % '-'.join(module.split('/')) + path = '.*%s' % os.path.dirname(path_prefix) + regex = re.compile(r"^ \* \[.\] %s.*%s \(module: %s\)$" % (path, ec_fn, module), re.M) + self.assertTrue(regex.search(outtxt), "Found pattern %s in %s" % (regex.pattern, outtxt)) + + # make sure that *only* these modules are listed, no others + regex = re.compile(r"^ \* \[.\] .*/(?P.*) \(module: (?P.*)\)$", re.M) + self.assertTrue(sorted(regex.findall(outtxt)), sorted(modules)) + + pr_tmpdir = os.path.join(tmpdir, r'eb-\S{6,8}', 'files_commit_%s' % test_commit) + regex = re.compile(r"Extended list of robot search paths with \['%s'\]:" % pr_tmpdir, re.M) + self.assertTrue(regex.search(outtxt), "Found pattern %s in %s" % (regex.pattern, outtxt)) + except URLError as err: + print("Ignoring URLError '%s' in test_from_commit" % err) + shutil.rmtree(tmpdir) + + # must be run after test for --list-easyblocks, hence the '_xxx_' + # cleaning up the imported easyblocks is quite difficult... + def test_xxx_include_easyblocks_from_commit(self): + """Test for --include-easyblocks-from-commit.""" + # note: --include-easyblocks-from-commit does not involve using GitHub API, so no GitHub token required + + orig_local_sys_path = sys.path[:] + # easyblocks commit only touching Binary easyblock + test_commit = '94d28c556947bd96d0978df775b15a50a4600c6f' + + fd, dummylogfn = tempfile.mkstemp(prefix='easybuild-dummy', suffix='.log') + os.close(fd) + + tmpdir = tempfile.mkdtemp() + args = [ + '--include-easyblocks-from-commit=%s' % test_commit, + '--dry-run', + '--tmpdir=%s' % tmpdir, + 'toy-0.0.eb', # test easyconfig + ] + try: + self.mock_stdout(True) + self.mock_stderr(True) + outtxt = self.eb_main(args, logfile=dummylogfn, raise_error=True) + stdout = self.get_stdout() + stderr = self.get_stderr() + self.mock_stdout(False) + self.mock_stderr(False) + + # 'undo' import of foo easyblock + del sys.modules['easybuild.easyblocks.generic.binary'] + sys.path[:] = orig_local_sys_path + import easybuild.easyblocks + reload(easybuild.easyblocks) + import easybuild.easyblocks.generic + reload(easybuild.easyblocks.generic) + + pattern = "== easyblock binary.py included from comit %s" % test_commit + self.assertEqual(stderr, '') + self.assertIn(pattern, stdout) + + regex = re.compile(r"^ \* \[.\] .*/toy-0.0.eb \(module: toy/0.0\)$", re.M) + self.assertTrue(regex.search(outtxt), "Found pattern %s in %s" % (regex.pattern, outtxt)) + + except URLError as err: + print("Ignoring URLError '%s' in test_include_easyblocks_from_commit" % err) + shutil.rmtree(tmpdir) + def test_no_such_software(self): """Test using no arguments.""" @@ -2190,7 +2352,7 @@ def test_ignore_osdeps(self): self.assertTrue(regex.search(outtxt), "OS dependencies are checked, outtxt: %s" % outtxt) msg = "One or more OS dependencies were not found: " msg += r"\[\('nosuchosdependency',\), \('nosuchdep_option1', 'nosuchdep_option2'\)\]" - regex = re.compile(r'%s' % msg, re.M) + regex = re.compile(msg, re.M) self.assertTrue(regex.search(outtxt), "OS dependencies are honored, outtxt: %s" % outtxt) # check whether OS dependencies are effectively ignored @@ -3154,8 +3316,7 @@ def test_show_default_configfiles(self): home = os.environ['HOME'] for envvar in ['XDG_CONFIG_DIRS', 'XDG_CONFIG_HOME']: - if envvar in os.environ: - del os.environ[envvar] + os.environ.pop(envvar, None) reload(easybuild.tools.options) args = [ @@ -3915,6 +4076,18 @@ def test_github_review_pr(self): self.mock_stderr(False) self.assertNotIn("2016.04", txt) + def test_set_multiple_pr_opts(self): + """Test that passing multiple PR options results in an error""" + test_cases = [ + ['--new-pr', 'dummy.eb', '--preview-pr'], + ['--new-pr', 'dummy.eb', '--update-pr', '42'], + ['--new-pr', 'dummy.eb', '--sync-pr-with-develop', '42'], + ['--new-pr', 'dummy.eb', '--new-pr-from-branch', 'mybranch'], + ] + for args in test_cases: + error_pattern = "The following options are set but incompatible.* " + args[0] + self.assertErrorRegex(EasyBuildError, error_pattern, self._run_mock_eb, args, raise_error=True) + def test_set_tmpdir(self): """Test set_tmpdir config function.""" self.purge_environment() @@ -4794,26 +4967,29 @@ def test_github_merge_pr(self): self.assertEqual(stderr.strip(), expected_stderr) self.assertTrue(stdout.strip().endswith(expected_stdout), "'%s' ends with '%s'" % (stdout, expected_stdout)) - # full eligible merged PR, default target branch + # full eligible merged PR, default target branch; + # note: we frequently need to change to a more recent PR here, + # to avoid that this test starts failing because commit status is set to None for old commits del args[-1] - args[1] = '17065' + # easyconfig PR for EasyBuild v4.8.2 + args[1] = '19105' stdout, stderr = self._run_mock_eb(args, do_build=True, raise_error=True, testing=False) expected_stdout = '\n'.join([ - "Checking eligibility of easybuilders/easybuild-easyconfigs PR #17065 for merging...", + "Checking eligibility of easybuilders/easybuild-easyconfigs PR #19105 for merging...", "* targets develop branch: OK", "* test suite passes: OK", "* last test report is successful: OK", "* no pending change requests: OK", "* approved review: OK (by SebastianAchilles)", - "* milestone is set: OK (4.7.1)", + "* milestone is set: OK (4.9.0)", "* mergeable state is clean: PR is already merged", '', "Review OK, merging pull request!", '', - "[DRY RUN] Adding comment to easybuild-easyconfigs issue #17065: 'Going in, thanks @boegel!'", - "[DRY RUN] Merged easybuilders/easybuild-easyconfigs pull request #17065", + "[DRY RUN] Adding comment to easybuild-easyconfigs issue #19105: 'Going in, thanks @boegel!'", + "[DRY RUN] Merged easybuilders/easybuild-easyconfigs pull request #19105", ]) expected_stderr = '' self.assertEqual(stderr.strip(), expected_stderr) @@ -4957,8 +5133,7 @@ def test_show_config_cfg_levels(self): """Test --show-config in relation to how configuring across multiple configuration levels interacts with it.""" # make sure default module syntax is used - if 'EASYBUILD_MODULE_SYNTAX' in os.environ: - del os.environ['EASYBUILD_MODULE_SYNTAX'] + os.environ.pop('EASYBUILD_MODULE_SYNTAX', None) # configuring --modules-tool and --module-syntax on different levels should NOT cause problems # cfr. bug report https://github.com/easybuilders/easybuild-framework/issues/2564 @@ -4984,8 +5159,7 @@ def test_modules_tool_vs_syntax_check(self): """Verify that check for modules tool vs syntax works.""" # make sure default module syntax is used - if 'EASYBUILD_MODULE_SYNTAX' in os.environ: - del os.environ['EASYBUILD_MODULE_SYNTAX'] + os.environ.pop('EASYBUILD_MODULE_SYNTAX', None) # using EnvironmentModulesC modules tool with default module syntax (Lua) is a problem os.environ['EASYBUILD_MODULES_TOOL'] = 'EnvironmentModulesC' @@ -6764,8 +6938,7 @@ def test_easystack_opts(self): mod_ext = '.lua' if get_module_syntax() == 'Lua' else '' # make sure that $EBROOTLIBTOY is not defined - if 'EBROOTLIBTOY' in os.environ: - del os.environ['EBROOTLIBTOY'] + os.environ.pop('EBROOTLIBTOY', None) # libtoy module should be installed, module file should at least set EBROOTLIBTOY mod_dir = os.path.join(self.test_installpath, 'modules', 'all') diff --git a/test/framework/output.py b/test/framework/output.py index d1673a55d1..4429fe29ee 100644 --- a/test/framework/output.py +++ b/test/framework/output.py @@ -1,5 +1,5 @@ # # -# Copyright 2021-2023 Ghent University +# Copyright 2021-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/package.py b/test/framework/package.py index 23e2e37e9c..b839fb32bb 100644 --- a/test/framework/package.py +++ b/test/framework/package.py @@ -1,5 +1,5 @@ # # -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/parallelbuild.py b/test/framework/parallelbuild.py index 3ad85ac3b1..4e75672815 100644 --- a/test/framework/parallelbuild.py +++ b/test/framework/parallelbuild.py @@ -1,5 +1,5 @@ # # -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/repository.py b/test/framework/repository.py index aa1cf402b7..720e0fa8e8 100644 --- a/test/framework/repository.py +++ b/test/framework/repository.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/robot.py b/test/framework/robot.py index 4f226bae35..bbfe8e2f03 100644 --- a/test/framework/robot.py +++ b/test/framework/robot.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -128,8 +128,7 @@ def tearDown(self): config.modules_tool = ORIG_MODULES_TOOL ecec.modules_tool = ORIG_ECEC_MODULES_TOOL if ORIG_MODULE_FUNCTION is None: - if 'module' in os.environ: - del os.environ['module'] + os.environ.pop('module', None) else: os.environ['module'] = ORIG_MODULE_FUNCTION self.modtool = self.orig_modtool @@ -713,6 +712,47 @@ def test_search_paths(self): regex = re.compile(r"^ \* %s$" % os.path.join(self.test_prefix, test_ec), re.M) self.assertTrue(regex.search(outtxt), "Found pattern %s in %s" % (regex.pattern, outtxt)) + def test_github_det_easyconfig_paths_from_commit(self): + """Test det_easyconfig_paths function in combination with --from-commit.""" + # note: --from-commit does not involve using GitHub API, so no GitHub token required + + test_ecs_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs') + + commit = '589282cf52609067616fc2a522f8e4b81f809cb7' + args = [ + os.path.join(test_ecs_path, 't', 'toy', 'toy-0.0.eb'), # absolute path + 'toy-0.0-iter.eb', # relative path, available via robot search path + # commit in which ReFrame-4.3.2.eb was added, + # see https://github.com/easybuilders/easybuild-easyconfigs/pull/18763/commits + '--from-commit', commit, + 'ReFrame-4.3.2.eb', # easyconfig included in commit, should be resolved via robot search path + '--dry-run', + '--robot', + '--robot=%s' % test_ecs_path, + '--unittest-file=%s' % self.logfile, + '--tmpdir=%s' % self.test_prefix, + ] + + self.mock_stderr(True) + outtxt = self.eb_main(args, raise_error=True) + stderr = self.get_stderr() + self.mock_stderr(False) + + self.assertFalse(stderr) + + # full path doesn't matter (helps to avoid failing tests due to resolved symlinks) + test_ecs_path = os.path.join('.*', 'test', 'framework', 'easyconfigs', 'test_ecs') + + modules = [ + (test_ecs_path, 'toy/0.0'), + (test_ecs_path, 'toy/0.0-iter'), + (os.path.join(self.test_prefix, '.*', 'files_commit_%s' % commit), 'ReFrame/4.3.2'), + ] + for path_prefix, module in modules: + ec_fn = "%s.eb" % '-'.join(module.split('/')) + regex = re.compile(r"^ \* \[.\] %s.*%s \(module: %s\)$" % (path_prefix, ec_fn, module), re.M) + self.assertTrue(regex.search(outtxt), "Found pattern %s in %s" % (regex.pattern, outtxt)) + def test_github_det_easyconfig_paths_from_pr(self): """Test det_easyconfig_paths function, with --from-pr enabled as well.""" if self.github_token is None: @@ -1082,8 +1122,8 @@ def test_tweak_robotpath(self): test_easyconfigs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs') # Create directories to store the tweaked easyconfigs - tweaked_ecs_paths, pr_paths = alt_easyconfig_paths(self.test_prefix, tweaked_ecs=True) - robot_path = det_robot_path([test_easyconfigs], tweaked_ecs_paths, pr_paths, auto_robot=True) + tweaked_ecs_paths, extra_ec_paths = alt_easyconfig_paths(self.test_prefix, tweaked_ecs=True) + robot_path = det_robot_path([test_easyconfigs], tweaked_ecs_paths, extra_ec_paths, auto_robot=True) init_config(build_options={ 'valid_module_classes': module_classes(), diff --git a/test/framework/run.py b/test/framework/run.py index d529b41a3a..bab4391cf6 100644 --- a/test/framework/run.py +++ b/test/framework/run.py @@ -1,6 +1,6 @@ # # # -*- coding: utf-8 -*- -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/e/easybuildmeta.py b/test/framework/sandbox/easybuild/easyblocks/e/easybuildmeta.py index e27c0c66d0..7d2ef2d6da 100644 --- a/test/framework/sandbox/easybuild/easyblocks/e/easybuildmeta.py +++ b/test/framework/sandbox/easybuild/easyblocks/e/easybuildmeta.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2020 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/f/fftw.py b/test/framework/sandbox/easybuild/easyblocks/f/fftw.py index 194cead197..0871ce62e1 100644 --- a/test/framework/sandbox/easybuild/easyblocks/f/fftw.py +++ b/test/framework/sandbox/easybuild/easyblocks/f/fftw.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/f/foo.py b/test/framework/sandbox/easybuild/easyblocks/f/foo.py index 07e21608fa..b5a91d9503 100644 --- a/test/framework/sandbox/easybuild/easyblocks/f/foo.py +++ b/test/framework/sandbox/easybuild/easyblocks/f/foo.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/f/foofoo.py b/test/framework/sandbox/easybuild/easyblocks/f/foofoo.py index 3d64b1cf97..6415d6e6e1 100644 --- a/test/framework/sandbox/easybuild/easyblocks/f/foofoo.py +++ b/test/framework/sandbox/easybuild/easyblocks/f/foofoo.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/g/gcc.py b/test/framework/sandbox/easybuild/easyblocks/g/gcc.py index a85b2482fa..5ee5aae1c6 100644 --- a/test/framework/sandbox/easybuild/easyblocks/g/gcc.py +++ b/test/framework/sandbox/easybuild/easyblocks/g/gcc.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/bar.py b/test/framework/sandbox/easybuild/easyblocks/generic/bar.py index d2faf66053..8ba475f700 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/bar.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/bar.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/configuremake.py b/test/framework/sandbox/easybuild/easyblocks/generic/configuremake.py index 4ad690fe5c..b82668434c 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/configuremake.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/configuremake.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/dummyextension.py b/test/framework/sandbox/easybuild/easyblocks/generic/dummyextension.py index d754117b39..3466ce28f2 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/dummyextension.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/dummyextension.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/makecp.py b/test/framework/sandbox/easybuild/easyblocks/generic/makecp.py index 6b258c87d6..dd89704638 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/makecp.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/makecp.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2020 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/modulerc.py b/test/framework/sandbox/easybuild/easyblocks/generic/modulerc.py index 33ab7db67f..72252a46f4 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/modulerc.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/modulerc.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/pythonbundle.py b/test/framework/sandbox/easybuild/easyblocks/generic/pythonbundle.py index 0321602f3f..9c01951adf 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/pythonbundle.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/pythonbundle.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2020 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/toolchain.py b/test/framework/sandbox/easybuild/easyblocks/generic/toolchain.py index fb81a51c96..5151221a13 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/toolchain.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/toolchain.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py b/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py index 9c700cf779..9335611f58 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/h/hpl.py b/test/framework/sandbox/easybuild/easyblocks/h/hpl.py index 89fba75c30..db929d4d31 100644 --- a/test/framework/sandbox/easybuild/easyblocks/h/hpl.py +++ b/test/framework/sandbox/easybuild/easyblocks/h/hpl.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/l/libtoy.py b/test/framework/sandbox/easybuild/easyblocks/l/libtoy.py index 50b573649a..d3e55ed05d 100644 --- a/test/framework/sandbox/easybuild/easyblocks/l/libtoy.py +++ b/test/framework/sandbox/easybuild/easyblocks/l/libtoy.py @@ -1,5 +1,5 @@ ## -# Copyright 2021-2023 Ghent University +# Copyright 2021-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/o/openblas.py b/test/framework/sandbox/easybuild/easyblocks/o/openblas.py index bfb118cefa..e5dc093347 100644 --- a/test/framework/sandbox/easybuild/easyblocks/o/openblas.py +++ b/test/framework/sandbox/easybuild/easyblocks/o/openblas.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/o/openmpi.py b/test/framework/sandbox/easybuild/easyblocks/o/openmpi.py index 630d5413a7..b110b4f921 100644 --- a/test/framework/sandbox/easybuild/easyblocks/o/openmpi.py +++ b/test/framework/sandbox/easybuild/easyblocks/o/openmpi.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/s/scalapack.py b/test/framework/sandbox/easybuild/easyblocks/s/scalapack.py index d404f81648..3ded1247f4 100644 --- a/test/framework/sandbox/easybuild/easyblocks/s/scalapack.py +++ b/test/framework/sandbox/easybuild/easyblocks/s/scalapack.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/t/toy.py b/test/framework/sandbox/easybuild/easyblocks/t/toy.py index c4614e3333..04186a37ef 100644 --- a/test/framework/sandbox/easybuild/easyblocks/t/toy.py +++ b/test/framework/sandbox/easybuild/easyblocks/t/toy.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/t/toy_buggy.py b/test/framework/sandbox/easybuild/easyblocks/t/toy_buggy.py index 3695744630..6445655707 100644 --- a/test/framework/sandbox/easybuild/easyblocks/t/toy_buggy.py +++ b/test/framework/sandbox/easybuild/easyblocks/t/toy_buggy.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/t/toy_eula.py b/test/framework/sandbox/easybuild/easyblocks/t/toy_eula.py index 0b6820adc9..09442d1a79 100644 --- a/test/framework/sandbox/easybuild/easyblocks/t/toy_eula.py +++ b/test/framework/sandbox/easybuild/easyblocks/t/toy_eula.py @@ -1,5 +1,5 @@ ## -# Copyright 2020-2023 Ghent University +# Copyright 2020-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/easyblocks/t/toytoy.py b/test/framework/sandbox/easybuild/easyblocks/t/toytoy.py index a1fc62c69b..a3ef746d53 100644 --- a/test/framework/sandbox/easybuild/easyblocks/t/toytoy.py +++ b/test/framework/sandbox/easybuild/easyblocks/t/toytoy.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/tools/__init__.py b/test/framework/sandbox/easybuild/tools/__init__.py index 1fbb2401b7..389c5ff367 100644 --- a/test/framework/sandbox/easybuild/tools/__init__.py +++ b/test/framework/sandbox/easybuild/tools/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2009-2023 Ghent University +# Copyright 2009-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/tools/module_naming_scheme/__init__.py b/test/framework/sandbox/easybuild/tools/module_naming_scheme/__init__.py index 3a9383c79f..a519340298 100644 --- a/test/framework/sandbox/easybuild/tools/module_naming_scheme/__init__.py +++ b/test/framework/sandbox/easybuild/tools/module_naming_scheme/__init__.py @@ -1,5 +1,5 @@ ## -# Copyright 2011-2023 Ghent University +# Copyright 2011-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/tools/module_naming_scheme/broken_module_naming_scheme.py b/test/framework/sandbox/easybuild/tools/module_naming_scheme/broken_module_naming_scheme.py index 4d33d3d1e7..9113d89045 100644 --- a/test/framework/sandbox/easybuild/tools/module_naming_scheme/broken_module_naming_scheme.py +++ b/test/framework/sandbox/easybuild/tools/module_naming_scheme/broken_module_naming_scheme.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/sandbox/easybuild/tools/module_naming_scheme/test_module_naming_scheme.py b/test/framework/sandbox/easybuild/tools/module_naming_scheme/test_module_naming_scheme.py index 5eb5f66682..424fb55d43 100644 --- a/test/framework/sandbox/easybuild/tools/module_naming_scheme/test_module_naming_scheme.py +++ b/test/framework/sandbox/easybuild/tools/module_naming_scheme/test_module_naming_scheme.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -66,4 +66,4 @@ def is_short_modname_for(self, modname, name): """ Determine whether the specified (short) module name is a module for software with the specified name. """ - return modname.find('%s' % name) != -1 + return modname.find(name) != -1 diff --git a/test/framework/sandbox/easybuild/tools/module_naming_scheme/test_module_naming_scheme_more.py b/test/framework/sandbox/easybuild/tools/module_naming_scheme/test_module_naming_scheme_more.py index 3cbb5cb60d..a0e0429bfe 100644 --- a/test/framework/sandbox/easybuild/tools/module_naming_scheme/test_module_naming_scheme_more.py +++ b/test/framework/sandbox/easybuild/tools/module_naming_scheme/test_module_naming_scheme_more.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/style.py b/test/framework/style.py index 298b165c24..bfdf4e026a 100644 --- a/test/framework/style.py +++ b/test/framework/style.py @@ -1,5 +1,5 @@ ## -# Copyright 2016-2023 Ghent University +# Copyright 2016-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/suite.py b/test/framework/suite.py index 6a40e35754..3b8193469c 100755 --- a/test/framework/suite.py +++ b/test/framework/suite.py @@ -1,6 +1,6 @@ #!/usr/bin/python # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/systemtools.py b/test/framework/systemtools.py index 1707d6ec54..deece97702 100644 --- a/test/framework/systemtools.py +++ b/test/framework/systemtools.py @@ -1,5 +1,5 @@ ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -366,17 +366,14 @@ def setUp(self): self.orig_is_readable = st.is_readable self.orig_read_file = st.read_file self.orig_run_cmd = st.run_cmd - self.orig_platform_dist = st.platform.dist if hasattr(st.platform, 'dist') else None + self.orig_platform_dist = getattr(st.platform, 'dist', None) self.orig_platform_uname = st.platform.uname self.orig_get_tool_version = st.get_tool_version self.orig_sys_version_info = st.sys.version_info self.orig_HAVE_ARCHSPEC = st.HAVE_ARCHSPEC self.orig_HAVE_DISTRO = st.HAVE_DISTRO self.orig_ETC_OS_RELEASE = st.ETC_OS_RELEASE - if hasattr(st, 'archspec_cpu_host'): - self.orig_archspec_cpu_host = st.archspec_cpu_host - else: - self.orig_archspec_cpu_host = None + self.orig_archspec_cpu_host = getattr(st, 'archspec_cpu_host', None) def tearDown(self): """Cleanup after systemtools test.""" diff --git a/test/framework/toolchain.py b/test/framework/toolchain.py index aacde3baf7..0e53639491 100644 --- a/test/framework/toolchain.py +++ b/test/framework/toolchain.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -181,8 +181,7 @@ def test_toolchain_prepare_sysroot(self): # clean environment self.unset_compiler_env_vars() - if 'PKG_CONFIG_PATH' in os.environ: - del os.environ['PKG_CONFIG_PATH'] + os.environ.pop('PKG_CONFIG_PATH', None) self.assertEqual(os.getenv('PKG_CONFIG_PATH'), None) @@ -227,8 +226,7 @@ def unset_compiler_env_vars(self): env_vars.extend(['OMPI_%s' % x for x in comp_env_vars]) for key in env_vars: - if key in os.environ: - del os.environ[key] + os.environ.pop(key, None) def test_toolchain_compiler_env_vars(self): """Test whether environment variables for compilers are defined by toolchain mechanism.""" @@ -345,8 +343,7 @@ def test_toolchain_compiler_env_vars(self): init_config(build_options={'minimal_build_env': 'CC:gcc,CXX:g++,CFLAGS:-O2,CXXFLAGS:-O3 -g,FC:gfortan'}) for key in ['CFLAGS', 'CXXFLAGS', 'FC']: - if key in os.environ: - del os.environ[key] + os.environ.pop(key, None) self.mock_stderr(True) self.mock_stdout(True) @@ -2270,8 +2267,7 @@ def test_rpath_args_script(self): """Test rpath_args.py script""" # $LIBRARY_PATH affects result of rpath_args.py, so make sure it's not set - if 'LIBRARY_PATH' in os.environ: - del os.environ['LIBRARY_PATH'] + os.environ.pop('LIBRARY_PATH', None) script = find_eb_script('rpath_args.py') diff --git a/test/framework/toolchainvariables.py b/test/framework/toolchainvariables.py index db90378d8b..e61bb9031c 100644 --- a/test/framework/toolchainvariables.py +++ b/test/framework/toolchainvariables.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/toy_build.py b/test/framework/toy_build.py index 9ccb3c08df..1bd114d9d7 100644 --- a/test/framework/toy_build.py +++ b/test/framework/toy_build.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ## -# Copyright 2013-2023 Ghent University +# Copyright 2013-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -285,6 +285,7 @@ def test_toy_tweaked(self): ec_extra = '\n'.join([ "versionsuffix = '-tweaked'", "modextrapaths = {'SOMEPATH': ['foo/bar', 'baz', '']}", + "modextrapaths_append = {'SOMEPATH_APPEND': ['qux/fred', 'thud', '']}", "modextravars = {'FOO': 'bar'}", "modloadmsg = '%s'" % modloadmsg, "modtclfooter = 'puts stderr \"oh hai!\"'", # ignored when module syntax is Lua @@ -319,6 +320,9 @@ def test_toy_tweaked(self): self.assertTrue(re.search(r'^prepend-path\s*SOMEPATH\s*\$root/foo/bar$', toy_module_txt, re.M)) self.assertTrue(re.search(r'^prepend-path\s*SOMEPATH\s*\$root/baz$', toy_module_txt, re.M)) self.assertTrue(re.search(r'^prepend-path\s*SOMEPATH\s*\$root$', toy_module_txt, re.M)) + self.assertTrue(re.search(r'^append-path\s*SOMEPATH_APPEND\s*\$root/qux/fred$', toy_module_txt, re.M)) + self.assertTrue(re.search(r'^append-path\s*SOMEPATH_APPEND\s*\$root/thud$', toy_module_txt, re.M)) + self.assertTrue(re.search(r'^append-path\s*SOMEPATH_APPEND\s*\$root$', toy_module_txt, re.M)) mod_load_msg = r'module-info mode load.*\n\s*puts stderr\s*.*%s$' % modloadmsg_regex_tcl self.assertTrue(re.search(mod_load_msg, toy_module_txt, re.M)) self.assertTrue(re.search(r'^puts stderr "oh hai!"$', toy_module_txt, re.M)) @@ -326,6 +330,11 @@ def test_toy_tweaked(self): self.assertTrue(re.search(r'^setenv\("FOO", "bar"\)', toy_module_txt, re.M)) pattern = r'^prepend_path\("SOMEPATH", pathJoin\(root, "foo/bar"\)\)$' self.assertTrue(re.search(pattern, toy_module_txt, re.M)) + pattern = r'^append_path\("SOMEPATH_APPEND", pathJoin\(root, "qux/fred"\)\)$' + self.assertTrue(re.search(pattern, toy_module_txt, re.M)) + pattern = r'^append_path\("SOMEPATH_APPEND", pathJoin\(root, "thud"\)\)$' + self.assertTrue(re.search(pattern, toy_module_txt, re.M)) + self.assertTrue(re.search(r'^append_path\("SOMEPATH_APPEND", root\)$', toy_module_txt, re.M)) self.assertTrue(re.search(r'^prepend_path\("SOMEPATH", pathJoin\(root, "baz"\)\)$', toy_module_txt, re.M)) self.assertTrue(re.search(r'^prepend_path\("SOMEPATH", root\)$', toy_module_txt, re.M)) mod_load_msg = r'^if mode\(\) == "load" then\n\s*io.stderr:write\(%s\)$' % modloadmsg_regex_lua @@ -344,8 +353,7 @@ def test_toy_tweaked(self): expected += "oh hai!" # setting $LMOD_QUIET results in suppression of printed message with Lmod & module files in Tcl syntax - if 'LMOD_QUIET' in os.environ: - del os.environ['LMOD_QUIET'] + os.environ.pop('LMOD_QUIET', None) self.modtool.use(os.path.join(self.test_installpath, 'modules', 'all')) out = self.modtool.run_module('load', 'toy/0.0-tweaked', return_output=True) @@ -1491,7 +1499,7 @@ def test_toy_module_fulltxt(self): mod_txt_regex_pattern = '\n'.join([ r'help\(\[==\[', r'', - r'%s' % help_txt, + help_txt, r'\]==\]\)', r'', r'whatis\(\[==\[Description: Toy C program, 100% toy.\]==\]\)', @@ -1514,6 +1522,9 @@ def test_toy_module_fulltxt(self): r'prepend_path\("SOMEPATH", pathJoin\(root, "foo/bar"\)\)', r'prepend_path\("SOMEPATH", pathJoin\(root, "baz"\)\)', r'prepend_path\("SOMEPATH", root\)', + r'append_path\("SOMEPATH_APPEND", pathJoin\(root, "qux/fred"\)\)', + r'append_path\("SOMEPATH_APPEND", pathJoin\(root, "thud"\)\)', + r'append_path\("SOMEPATH_APPEND", root\)', r'', r'if mode\(\) == "load" then', ] + modloadmsg_lua + [ @@ -1528,7 +1539,7 @@ def test_toy_module_fulltxt(self): r'proc ModulesHelp { } {', r' puts stderr {', r'', - r'%s' % help_txt, + help_txt, r' }', r'}', r'', @@ -1552,6 +1563,9 @@ def test_toy_module_fulltxt(self): r'prepend-path SOMEPATH \$root/foo/bar', r'prepend-path SOMEPATH \$root/baz', r'prepend-path SOMEPATH \$root', + r'append-path SOMEPATH_APPEND \$root/qux/fred', + r'append-path SOMEPATH_APPEND \$root/thud', + r'append-path SOMEPATH_APPEND \$root', r'', r'if { \[ module-info mode load \] } {', ] + modloadmsg_tcl + [ diff --git a/test/framework/tweak.py b/test/framework/tweak.py index eda8046d52..24ec85b2c8 100644 --- a/test/framework/tweak.py +++ b/test/framework/tweak.py @@ -1,5 +1,5 @@ ## -# Copyright 2014-2023 Ghent University +# Copyright 2014-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/type_checking.py b/test/framework/type_checking.py index 83f1ef41ac..8b7edd3215 100644 --- a/test/framework/type_checking.py +++ b/test/framework/type_checking.py @@ -1,5 +1,5 @@ # # -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/utilities.py b/test/framework/utilities.py index 37a9b29318..d07c2202b1 100644 --- a/test/framework/utilities.py +++ b/test/framework/utilities.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), @@ -207,8 +207,7 @@ def disallow_deprecated_behaviour(self): def allow_deprecated_behaviour(self): """Restore EasyBuild version to what it was originally, to allow triggering deprecated behaviour.""" - if 'EASYBUILD_DEPRECATED' in os.environ: - del os.environ['EASYBUILD_DEPRECATED'] + os.environ.pop('EASYBUILD_DEPRECATED', None) eb_build_log.CURRENT_VERSION = self.orig_current_version @contextmanager @@ -278,8 +277,7 @@ def reset_modulepath(self, modpaths): # make very sure $MODULEPATH is totally empty # some paths may be left behind, e.g. when they contain environment variables # example: "module unuse Modules/$MODULE_VERSION/modulefiles" may not yield the desired result - if 'MODULEPATH' in os.environ: - del os.environ['MODULEPATH'] + os.environ.pop('MODULEPATH', None) for modpath in modpaths: self.modtool.add_module_path(modpath, set_mod_paths=False) self.modtool.set_mod_paths() diff --git a/test/framework/utilities_test.py b/test/framework/utilities_test.py index ba4766f302..a17d7beb02 100644 --- a/test/framework/utilities_test.py +++ b/test/framework/utilities_test.py @@ -1,5 +1,5 @@ ## -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/variables.py b/test/framework/variables.py index 8331a6c2dd..cc804d6a65 100644 --- a/test/framework/variables.py +++ b/test/framework/variables.py @@ -1,5 +1,5 @@ # # -# Copyright 2012-2023 Ghent University +# Copyright 2012-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en), diff --git a/test/framework/yeb.py b/test/framework/yeb.py index 74a2a47875..346ffa057b 100644 --- a/test/framework/yeb.py +++ b/test/framework/yeb.py @@ -1,5 +1,5 @@ # # -# Copyright 2015-2023 Ghent University +# Copyright 2015-2024 Ghent University # # This file is part of EasyBuild, # originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),