diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index cef5b1c29c..0000000000 --- a/.coveragerc +++ /dev/null @@ -1,26 +0,0 @@ -# .coveragerc to control coverage.py -[run] -branch = True - -[report] -# Regexes for lines to exclude from consideration -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain about missing debug-only code: - def __repr__ - if self\.debug - - # Don't complain if tests don't hit defensive assertion code: - raise AssertionError - raise NotImplementedError - - # Don't complain if non-runnable code isn't run: - if 0: - if __name__ == .__main__.: - -ignore_errors = True - -[html] -directory = coverage_html_report diff --git a/.github/workflows/container_tests.yml b/.github/workflows/container_tests.yml index 4521186580..bdd07d5cd8 100644 --- a/.github/workflows/container_tests.yml +++ b/.github/workflows/container_tests.yml @@ -74,7 +74,7 @@ jobs: ls dist export PREFIX=/tmp/$USER/$GITHUB_SHA pip install --prefix $PREFIX dist/easybuild[-_]framework*tar.gz - pip install --prefix $PREFIX https://github.com/easybuilders/easybuild-easyblocks/archive/5.0.x.tar.gz + pip install --prefix $PREFIX https://github.com/easybuilders/easybuild-easyblocks/archive/develop.tar.gz - name: run test run: | @@ -95,7 +95,7 @@ jobs: echo '%_dbpath %{_var}/lib/rpm' >> $HOME/.rpmmacros # build CentOS 7 container image for bzip2 1.0.8 using EasyBuild; # see https://docs.easybuild.io/en/latest/Containers.html - curl -OL https://raw.githubusercontent.com/easybuilders/easybuild-easyconfigs/5.0.x/easybuild/easyconfigs/b/bzip2/bzip2-1.0.8.eb + curl -OL https://raw.githubusercontent.com/easybuilders/easybuild-easyconfigs/develop/easybuild/easyconfigs/b/bzip2/bzip2-1.0.8.eb export EASYBUILD_CONTAINERPATH=$PWD export EASYBUILD_CONTAINER_CONFIG='bootstrap=docker,from=ghcr.io/easybuilders/centos-7.9-python3-amd64' eb bzip2-1.0.8.eb --containerize --experimental --container-build-image diff --git a/.github/workflows/container_tests_apptainer.yml b/.github/workflows/container_tests_apptainer.yml index 1f8417ea7d..403ab754ff 100644 --- a/.github/workflows/container_tests_apptainer.yml +++ b/.github/workflows/container_tests_apptainer.yml @@ -68,7 +68,7 @@ jobs: ls dist export PREFIX=/tmp/$USER/$GITHUB_SHA pip install --prefix $PREFIX dist/easybuild[-_]framework*tar.gz - pip install --prefix $PREFIX https://github.com/easybuilders/easybuild-easyblocks/archive/5.0.x.tar.gz + pip install --prefix $PREFIX https://github.com/easybuilders/easybuild-easyblocks/archive/develop.tar.gz - name: run test run: | @@ -89,7 +89,7 @@ jobs: echo '%_dbpath %{_var}/lib/rpm' >> $HOME/.rpmmacros # build CentOS 7 container image for bzip2 1.0.8 using EasyBuild; # see https://docs.easybuild.io/en/latest/Containers.html - curl -OL https://raw.githubusercontent.com/easybuilders/easybuild-easyconfigs/5.0.x/easybuild/easyconfigs/b/bzip2/bzip2-1.0.8.eb + curl -OL https://raw.githubusercontent.com/easybuilders/easybuild-easyconfigs/develop/easybuild/easyconfigs/b/bzip2/bzip2-1.0.8.eb export EASYBUILD_CONTAINERPATH=$PWD export EASYBUILD_CONTAINER_CONFIG='bootstrap=docker,from=ghcr.io/easybuilders/centos-7.9-python3-amd64' export EASYBUILD_CONTAINER_TYPE='apptainer' diff --git a/.github/workflows/end2end.yml b/.github/workflows/end2end.yml index b2bf320d94..3954a3ad7f 100644 --- a/.github/workflows/end2end.yml +++ b/.github/workflows/end2end.yml @@ -26,9 +26,9 @@ jobs: run: | cd $HOME for pkg in easyblocks easyconfigs; do - curl -OL https://github.com/easybuilders/easybuild-${pkg}/archive/5.0.x.tar.gz - tar xfz 5.0.x.tar.gz - rm -f 5.0.x.tar.gz + curl -OL https://github.com/easybuilders/easybuild-${pkg}/archive/develop.tar.gz + tar xfz develop.tar.gz + rm -f develop.tar.gz done - name: Set up environment @@ -36,7 +36,7 @@ jobs: run: | # collect environment variables to be set in subsequent steps in script that can be sourced echo "export PATH=$PWD:$PATH" > /tmp/eb_env - echo "export PYTHONPATH=$PWD:$HOME/easybuild-easyblocks-5.0.x:$HOME/easybuild-easyconfigs-5.0.x" >> /tmp/eb_env + echo "export PYTHONPATH=$PWD:$HOME/easybuild-easyblocks-develop:$HOME/easybuild-easyconfigs-develop" >> /tmp/eb_env - name: Run commands to check test environment shell: bash diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index d5a7163f70..6eb6851544 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -24,7 +24,7 @@ jobs: - name: set up Python uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0 with: - python-version: ${{ matrix.python-version }} + python-version: ${{ matrix.python }} - name: install Python packages run: | diff --git a/README.rst b/README.rst index 36dc86697f..2fcf83c92f 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ :align: center :height: 400px -.. image:: https://github.com/easybuilders/easybuild-framework/workflows/EasyBuild%20framework%20unit%20tests/badge.svg?branch=develop +.. image:: https://github.com/easybuilders/easybuild-framework/actions/workflows/unit_tests.yml/badge.svg?branch=develop `EasyBuild <https://easybuild.io>`_ is a software build and installation framework that allows you to manage (scientific) software diff --git a/easybuild/base/exceptions.py b/easybuild/base/exceptions.py index 959b28de65..86d8cc1177 100644 --- a/easybuild/base/exceptions.py +++ b/easybuild/base/exceptions.py @@ -125,4 +125,4 @@ def __init__(self, msg, *args, **kwargs): getattr(logger, self.LOGGING_METHOD_NAME)(msg) - super(LoggedException, self).__init__(msg) + super().__init__(msg) diff --git a/easybuild/base/frozendict.py b/easybuild/base/frozendict.py index 5d0205687e..5e9312557f 100644 --- a/easybuild/base/frozendict.py +++ b/easybuild/base/frozendict.py @@ -87,13 +87,13 @@ def __init__(self, *args, **kwargs): msg = "Encountered unknown keys %s (known keys: %s)" % (unknown_keys, self.KNOWN_KEYS) self.log.raiseException(msg, exception=KeyError) - super(FrozenDictKnownKeys, self).__init__(tmpdict) + super().__init__(tmpdict) # pylint: disable=arguments-differ def __getitem__(self, key, *args, **kwargs): """Redefine __getitem__ to provide a better KeyError message.""" try: - return super(FrozenDictKnownKeys, self).__getitem__(key, *args, **kwargs) + return super().__getitem__(key, *args, **kwargs) except KeyError as err: if key in self.KNOWN_KEYS: raise KeyError(err) diff --git a/easybuild/base/generaloption.py b/easybuild/base/generaloption.py index 820033a420..c7354d10af 100644 --- a/easybuild/base/generaloption.py +++ b/easybuild/base/generaloption.py @@ -864,7 +864,7 @@ def get_option_by_long_name(self, name): return None -class GeneralOption(object): +class GeneralOption: """ 'Used-to-be simple' wrapper class for option parsing @@ -1745,7 +1745,7 @@ def __init__(self, go_dict=None, short_groupdescr=None, long_groupdescr=None, co if config_files is not None: kwargs['go_configfiles'] = config_files - super(SimpleOption, self).__init__(**kwargs) + super().__init__(**kwargs) def main_options(self): if self.go_dict is not None: diff --git a/easybuild/base/optcomplete.py b/easybuild/base/optcomplete.py index ba0f075cf2..7f76f79194 100644 --- a/easybuild/base/optcomplete.py +++ b/easybuild/base/optcomplete.py @@ -149,7 +149,7 @@ class CompleterMissingCallArgument(Exception): """Exception to raise when call arg is missing""" -class Completer(object): +class Completer: """Base class to derive all other completer classes from. It generates an empty completion list """ @@ -605,7 +605,7 @@ def autocomplete(parser, arg_completer=None, opt_completer=None, subcmd_complete sys.exit(1) -class CmdComplete(object): +class CmdComplete: """Simple default base class implementation for a subcommand that supports command completion. This class is assuming that there might be a method diff --git a/easybuild/base/rest.py b/easybuild/base/rest.py index 4d97eb6183..83247b6d7e 100644 --- a/easybuild/base/rest.py +++ b/easybuild/base/rest.py @@ -46,7 +46,7 @@ from easybuild.base import fancylogger -class Client(object): +class Client: """An implementation of a REST client""" DELETE = 'DELETE' GET = 'GET' @@ -217,7 +217,7 @@ def get_connection(self, method, url, body, headers): return connection -class RequestBuilder(object): +class RequestBuilder: '''RequestBuilder(client).path.to.resource.method(...) stands for RequestBuilder(client).client.method('path/to/resource, ...) @@ -265,7 +265,7 @@ def __repr__(self): return '%s: %s' % (self.__class__, self.url) -class RestClient(object): +class RestClient: """ A client with a request builder, so you can easily create rest requests e.g. to create a github Rest API client just do diff --git a/easybuild/base/testing.py b/easybuild/base/testing.py index 8e6f635b12..92789fd4ce 100644 --- a/easybuild/base/testing.py +++ b/easybuild/base/testing.py @@ -86,7 +86,7 @@ def assertEqual(self, a, b, msg=None): """Make assertEqual always print useful messages""" try: - super(TestCase, self).assertEqual(a, b) + super().assertEqual(a, b, msg=msg) except AssertionError as e: if not self._is_diffable(a) or not self._is_diffable(b): raise @@ -132,7 +132,7 @@ def assertAllExist(self, paths, msg=None): def setUp(self): """Prepare test case.""" - super(TestCase, self).setUp() + super().setUp() self.maxDiff = None self.longMessage = True @@ -225,4 +225,4 @@ def tearDown(self): """Cleanup after running a test.""" self.mock_stdout(False) self.mock_stderr(False) - super(TestCase, self).tearDown() + super().tearDown() diff --git a/easybuild/framework/easyblock.py b/easybuild/framework/easyblock.py index 4d9b4fbdd7..38fb3b0e7b 100644 --- a/easybuild/framework/easyblock.py +++ b/easybuild/framework/easyblock.py @@ -129,7 +129,7 @@ _log = fancylogger.getLogger('easyblock') -class EasyBlock(object): +class EasyBlock: """Generic support for building and installing software, base class for actual easyblocks.""" # static class method for extra easyconfig parameter definitions @@ -3253,7 +3253,7 @@ def post_install_step(self): - run post install commands if any were specified """ # even though post_install_step is deprecated in easyblocks we need to keep this here until it is - # removed in 6.0 for easyblocks calling super(EB_xxx, self).post_install_step() + # removed in 6.0 for easyblocks calling super().post_install_step() # The deprecation warning for those is below, in post_processing_step(). lib_dir = os.path.join(self.installdir, 'lib') diff --git a/easybuild/framework/easyconfig/easyconfig.py b/easybuild/framework/easyconfig/easyconfig.py index 4665a1d1e8..f7a1ea0f01 100644 --- a/easybuild/framework/easyconfig/easyconfig.py +++ b/easybuild/framework/easyconfig/easyconfig.py @@ -422,7 +422,7 @@ def get_toolchain_hierarchy(parent_toolchain, incl_capabilities=False): return toolchain_hierarchy -class EasyConfig(object): +class EasyConfig: """ Class which handles loading, reading, validation of easyconfigs """ diff --git a/easybuild/framework/easyconfig/format/convert.py b/easybuild/framework/easyconfig/format/convert.py index 1fd3182621..59d153a8f6 100644 --- a/easybuild/framework/easyconfig/format/convert.py +++ b/easybuild/framework/easyconfig/format/convert.py @@ -41,7 +41,7 @@ class Dependency(Convert): def __init__(self, obj, name=None): """Convert pass object to a dependency, use specified name if provided.""" - super(Dependency, self).__init__(obj) + super().__init__(obj) if name is not None: self['name'] = name diff --git a/easybuild/framework/easyconfig/format/format.py b/easybuild/framework/easyconfig/format/format.py index eec432967e..d18e1215d3 100644 --- a/easybuild/framework/easyconfig/format/format.py +++ b/easybuild/framework/easyconfig/format/format.py @@ -130,7 +130,7 @@ def __init__(self, parent=None, depth=None): NestedDict.__init__(self, self, 0) -class Squashed(object): +class Squashed: """Class to ease the squashing of OrderedVersionOperators and OrderedToolchainVersionOperators""" def __init__(self): @@ -184,7 +184,7 @@ def final(self): return self.result -class EBConfigObj(object): +class EBConfigObj: """ Enhanced ConfigObj, version/toolchain and other easyconfig specific aspects aware @@ -600,7 +600,7 @@ def get_specs_for(self, version=None, tcname=None, tcversion=None): return res -class EasyConfigFormat(object): +class EasyConfigFormat: """EasyConfigFormat class""" VERSION = EasyVersion('0.0') # dummy EasyVersion instance (shouldn't be None) USABLE = False # disable this class as usable format diff --git a/easybuild/framework/easyconfig/format/one.py b/easybuild/framework/easyconfig/format/one.py index a45c855436..6659c109dd 100644 --- a/easybuild/framework/easyconfig/format/one.py +++ b/easybuild/framework/easyconfig/format/one.py @@ -104,7 +104,7 @@ class FormatOneZero(EasyConfigFormatConfigObj): def __init__(self, *args, **kwargs): """FormatOneZero constructor.""" - super(FormatOneZero, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.log = fancylogger.getLogger(self.__class__.__name__, fname=False) self.strict_sanity_check_paths_keys = True @@ -155,7 +155,7 @@ def parse(self, txt): Pre-process txt to extract header, docstring and pyheader, with non-indented section markers enforced. """ self.rawcontent = txt - super(FormatOneZero, self).parse(self.rawcontent, strict_section_markers=True) + super().parse(self.rawcontent, strict_section_markers=True) def _reformat_line(self, param_name, param_val, outer=False, addlen=0): """ diff --git a/easybuild/framework/easyconfig/format/pyheaderconfigobj.py b/easybuild/framework/easyconfig/format/pyheaderconfigobj.py index b7e7206536..bd01614e17 100644 --- a/easybuild/framework/easyconfig/format/pyheaderconfigobj.py +++ b/easybuild/framework/easyconfig/format/pyheaderconfigobj.py @@ -158,7 +158,7 @@ class EasyConfigFormatConfigObj(EasyConfigFormat): def __init__(self, *args, **kwargs): """Extend EasyConfigFormat with some more attributes""" - super(EasyConfigFormatConfigObj, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.pyheader_localvars = None self.configobj = None diff --git a/easybuild/framework/easyconfig/format/version.py b/easybuild/framework/easyconfig/format/version.py index 4b3cdb6098..9cd45cc134 100644 --- a/easybuild/framework/easyconfig/format/version.py +++ b/easybuild/framework/easyconfig/format/version.py @@ -65,7 +65,7 @@ def __hash__(self): return hash(tuple(self.version)) -class VersionOperator(object): +class VersionOperator: """ VersionOperator class represents a version expression that includes an operator. """ @@ -219,7 +219,7 @@ def versop_regex(self, begin_end=True): """ # construct escaped operator symbols, e.g. '\<\=' operators = [] - for operator in self.OPERATOR_MAP.keys(): + for operator in self.OPERATOR_MAP: operators.append(re.sub(r'(.)', r'\\\1', operator)) # regex to parse version expression @@ -477,7 +477,7 @@ def __init__(self, tcversop_str=None): Initialise VersionOperator instance. :param tcversop_str: intialise with toolchain version operator string """ - super(ToolchainVersionOperator, self).__init__() + super().__init__() self.tc_name = None self.tcversop_str = None # the full string @@ -487,7 +487,7 @@ def __init__(self, tcversop_str=None): def __str__(self): """Return string representation of this instance""" - version_str = super(ToolchainVersionOperator, self).__str__() + version_str = super().__str__() return ''.join(map(str, [self.tc_name, self.SEPARATOR, version_str])) def __hash__(self): @@ -499,7 +499,6 @@ def _get_all_toolchain_names(self, search_string=''): Initialise each search_toolchain request, save in module constant TOOLCHAIN_NAMES. :param search_string: passed to search_toolchain function. """ - global TOOLCHAIN_NAMES if search_string not in TOOLCHAIN_NAMES: _, all_tcs = search_toolchain(search_string) self.log.debug('Found all toolchains for "%s" to %s' % (search_string, all_tcs)) @@ -512,7 +511,7 @@ def is_valid(self): """Check if this is a valid ToolchainVersionOperator""" tc_names = self._get_all_toolchain_names() known_tc_name = self.tc_name in tc_names - return known_tc_name and super(ToolchainVersionOperator, self).is_valid() + return known_tc_name and super().is_valid() def set(self, tcversop_str): """ @@ -536,7 +535,7 @@ def versop_regex(self): tc_names = self._get_all_toolchain_names() self.log.debug("found toolchain names %s" % tc_names) - versop_regex = super(ToolchainVersionOperator, self).versop_regex(begin_end=False) + versop_regex = super().versop_regex(begin_end=False) versop_pattern = r'(?P<versop_str>%s)' % versop_regex.pattern tc_names_regex = r'(?P<tc_name>(?:%s))' % '|'.join(tc_names) tc_regex = re.compile(r'^%s(?:%s%s)?$' % (tc_names_regex, self.SEPARATOR, versop_pattern)) @@ -557,7 +556,7 @@ def parse_versop_str(self, tcversop_str): tcversop_dict = res.groupdict() tcversop_dict['tcversop_str'] = tcversop_str # the total string - tcversop_dict = super(ToolchainVersionOperator, self).parse_versop_str(None, versop_dict=tcversop_dict) + tcversop_dict = super().parse_versop_str(None, versop_dict=tcversop_dict) if tcversop_dict.get('version_str', None) is not None and tcversop_dict.get('operator_str', None) is None: raise EasyBuildError("Toolchain version found, but no operator (use ' == '?).") @@ -587,7 +586,7 @@ def test(self, name, version): tc_name_res = name == self.tc_name if not tc_name_res: self.log.debug('Toolchain name %s different from test toolchain name %s' % (self.tc_name, name)) - version_res = super(ToolchainVersionOperator, self).test(version) + version_res = super().test(version) res = tc_name_res and version_res self.log.debug("result of testing expression tc_name_res %s version_res %s: %s", tc_name_res, version_res, res) @@ -615,7 +614,7 @@ def as_dict(self): return None -class OrderedVersionOperators(object): +class OrderedVersionOperators: """ Ordered version operators. The ordering is defined such that one can test from left to right, and assume that the first matching version operator is the one that is the best match. diff --git a/easybuild/framework/easyconfig/licenses.py b/easybuild/framework/easyconfig/licenses.py index d1f7ac787a..b4f342d566 100644 --- a/easybuild/framework/easyconfig/licenses.py +++ b/easybuild/framework/easyconfig/licenses.py @@ -40,7 +40,7 @@ _log = fancylogger.getLogger('easyconfig.licenses', fname=False) -class License(object): +class License: """EasyBuild easyconfig license class This is also the default restrictive license """ diff --git a/easybuild/framework/easyconfig/parser.py b/easybuild/framework/easyconfig/parser.py index f5914d65a4..683a8b8198 100644 --- a/easybuild/framework/easyconfig/parser.py +++ b/easybuild/framework/easyconfig/parser.py @@ -135,7 +135,7 @@ def fetch_parameters_from_easyconfig(rawtxt, params): return param_values -class EasyConfigParser(object): +class EasyConfigParser: """Read the easyconfig file, return a parsed config object Can contain references to multiple version and toolchain/toolchain versions """ diff --git a/easybuild/framework/easyconfig/tools.py b/easybuild/framework/easyconfig/tools.py index 3d85b931ea..f9b808a2b7 100644 --- a/easybuild/framework/easyconfig/tools.py +++ b/easybuild/framework/easyconfig/tools.py @@ -406,6 +406,8 @@ def parse_easyconfigs(paths, validate=True): parsed_paths = [] for (path, generated) in paths: + if not os.path.exists(path): + raise EasyBuildError("Can't find path %s", path, exit_code=EasyBuildExit.MISSING_EASYCONFIG) # Avoid processing the same file multiple times path = os.path.abspath(path) if any(os.path.samefile(path, p) for p in parsed_paths): @@ -414,8 +416,6 @@ def parse_easyconfigs(paths, validate=True): # keep track of whether any files were generated generated_ecs |= generated - if not os.path.exists(path): - raise EasyBuildError("Can't find path %s", path, exit_code=EasyBuildExit.MISSING_EASYCONFIG) try: ec_files = find_easyconfigs(path, ignore_dirs=build_option('ignore_dirs')) for ec_file in ec_files: diff --git a/easybuild/framework/easystack.py b/easybuild/framework/easystack.py index 471b5ac5db..fd87b3e947 100644 --- a/easybuild/framework/easystack.py +++ b/easybuild/framework/easystack.py @@ -66,7 +66,7 @@ def check_value(value, context): raise EasyBuildError(error_msg % format_info) -class EasyStack(object): +class EasyStack: """One class instance per easystack. General options + list of all SoftwareSpecs instances""" def __init__(self): @@ -90,7 +90,7 @@ def get_general_options(self): return general_options -class SoftwareSpecs(object): +class SoftwareSpecs: """Contains information about every software that should be installed""" def __init__(self, name, version, versionsuffix, toolchain_version, toolchain_name): @@ -101,7 +101,7 @@ def __init__(self, name, version, versionsuffix, toolchain_version, toolchain_na self.versionsuffix = versionsuffix -class EasyStackParser(object): +class EasyStackParser: """Parser for easystack files (in YAML syntax).""" @staticmethod diff --git a/easybuild/framework/extension.py b/easybuild/framework/extension.py index 51a40bbe15..7471670a90 100644 --- a/easybuild/framework/extension.py +++ b/easybuild/framework/extension.py @@ -82,7 +82,7 @@ def resolve_exts_filter_template(exts_filter, ext): return cmd, cmdinput -class Extension(object): +class Extension: """ Support for installing extensions. """ diff --git a/easybuild/framework/extensioneasyblock.py b/easybuild/framework/extensioneasyblock.py index 52d787528d..b85b97265a 100644 --- a/easybuild/framework/extensioneasyblock.py +++ b/easybuild/framework/extensioneasyblock.py @@ -200,9 +200,9 @@ def sanity_check_step(self, exts_filter=None, custom_paths=None, custom_commands self.clean_up_fake_module(fake_mod_data) if custom_paths or custom_commands or not self.is_extension: - super(ExtensionEasyBlock, self).sanity_check_step(custom_paths=custom_paths, - custom_commands=custom_commands, - extension=self.is_extension) + super().sanity_check_step(custom_paths=custom_paths, + custom_commands=custom_commands, + extension=self.is_extension) # pass or fail sanity check if sanity_check_ok: @@ -214,10 +214,18 @@ def sanity_check_step(self, exts_filter=None, custom_paths=None, custom_commands return (sanity_check_ok, '; '.join(self.sanity_check_fail_msgs)) - def make_module_extra(self, extra=None): + def make_module_extra(self, *args, **kwargs): """Add custom entries to module.""" - txt = EasyBlock.make_module_extra(self) + # The signature used to be make_module_extra(self, extra) which was wrong but supported + extra = kwargs.pop('extra', None) + if extra is None and len(args) == 1: + extra = args[0] + args = () + if extra is not None: + self.log.deprecated("Passing the parameter 'extra' to make_module_extra should be " + "replaced by concatenating the result", '6.0') + txt = super().make_module_extra(*args, **kwargs) if extra is not None: txt += extra return txt diff --git a/easybuild/main.py b/easybuild/main.py old mode 100644 new mode 100755 index fd25e27dc1..f91ebbbbec --- a/easybuild/main.py +++ b/easybuild/main.py @@ -240,8 +240,6 @@ def process_easystack(easystack_path, args, logfile, testing, init_session_state # keep copy of original environment, so we can restore it for every easystack entry init_env = copy.deepcopy(os.environ) - global _log - # TODO: insert fast loop that validates if all command line options are valid. If there are errors in options, # we want to know early on, and this loop potentially builds a lot of packages and could take very long # for path in orig_paths: @@ -311,6 +309,9 @@ def process_eb_args(eb_args, eb_go, cfg_settings, modtool, testing, init_session options = eb_go.options global _log + # Unpack cfg_settings + (build_specs, _log, logfile, robot_path, search_query, eb_tmpdir, try_to_generate, + from_pr_list, tweaked_ecs_paths) = cfg_settings # determine easybuild-easyconfigs package install path easyconfigs_pkg_paths = get_paths_for(subdir=EASYCONFIGS_PKG_SUBDIR) @@ -325,10 +326,6 @@ def process_eb_args(eb_args, eb_go, cfg_settings, modtool, testing, init_session eb_file = find_easybuild_easyconfig() eb_args.append(eb_file) - # Unpack cfg_settings - (build_specs, _log, logfile, robot_path, search_query, eb_tmpdir, try_to_generate, - from_pr_list, tweaked_ecs_paths) = cfg_settings - 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=from_pr_list, from_commit=options.from_commit) diff --git a/easybuild/scripts/findPythonDeps.py b/easybuild/scripts/findPythonDeps.py index 6fc6141f00..9ed862bf4c 100755 --- a/easybuild/scripts/findPythonDeps.py +++ b/easybuild/scripts/findPythonDeps.py @@ -212,7 +212,7 @@ def main(): """) parser = argparse.ArgumentParser( description='Find dependencies of Python packages by installing it in a temporary virtualenv. ', - epilog='\n'.join(examples), + epilog=examples, formatter_class=argparse.RawDescriptionHelpFormatter ) parser.add_argument('package', metavar='python-pkg-spec', diff --git a/easybuild/toolchains/compiler/craype.py b/easybuild/toolchains/compiler/craype.py index bcb0197b93..e1da4d1ef6 100644 --- a/easybuild/toolchains/compiler/craype.py +++ b/easybuild/toolchains/compiler/craype.py @@ -96,7 +96,7 @@ class CrayPECompiler(Compiler): def __init__(self, *args, **kwargs): """Constructor.""" - super(CrayPECompiler, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # 'register' additional toolchain options that correspond to a compiler flag self.COMPILER_OPTIONS.extend(['dynamic', 'mpich-mt']) @@ -124,7 +124,7 @@ def _set_optimal_architecture(self): def prepare(self, *args, **kwargs): """Prepare to use this toolchain; define $CRAYPE_LINK_TYPE if 'dynamic' toolchain option is enabled.""" - super(CrayPECompiler, self).prepare(*args, **kwargs) + super().prepare(*args, **kwargs) if self.options['dynamic'] or self.options['shared']: self.log.debug("Enabling building of shared libs/dynamically linked executables via $CRAYPE_LINK_TYPE") @@ -138,7 +138,7 @@ class CrayPEGCC(CrayPECompiler): def __init__(self, *args, **kwargs): """CrayPEGCC constructor.""" - super(CrayPEGCC, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) for precflag in self.COMPILER_PREC_OPTIONS: self.COMPILER_UNIQUE_OPTION_MAP[precflag] = Gcc.COMPILER_UNIQUE_OPTION_MAP[precflag] @@ -150,7 +150,7 @@ class CrayPEIntel(CrayPECompiler): def __init__(self, *args, **kwargs): """CrayPEIntel constructor.""" - super(CrayPEIntel, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) for precflag in self.COMPILER_PREC_OPTIONS: self.COMPILER_UNIQUE_OPTION_MAP[precflag] = IntelIccIfort.COMPILER_UNIQUE_OPTION_MAP[precflag] @@ -162,7 +162,7 @@ class CrayPEPGI(CrayPECompiler): def __init__(self, *args, **kwargs): """CrayPEPGI constructor.""" - super(CrayPEPGI, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.COMPILER_UNIQUE_OPTION_MAP['openmp'] = '-mp' for precflag in self.COMPILER_PREC_OPTIONS: self.COMPILER_UNIQUE_OPTION_MAP[precflag] = Pgi.COMPILER_UNIQUE_OPTION_MAP[precflag] @@ -175,7 +175,7 @@ class CrayPECray(CrayPECompiler): def __init__(self, *args, **kwargs): """CrayPEIntel constructor.""" - super(CrayPECray, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.COMPILER_UNIQUE_OPTION_MAP['openmp'] = '-homp' for precflag in self.COMPILER_PREC_OPTIONS: self.COMPILER_UNIQUE_OPTION_MAP[precflag] = [] diff --git a/easybuild/toolchains/compiler/cuda.py b/easybuild/toolchains/compiler/cuda.py index 24e8c038bb..caa2240561 100644 --- a/easybuild/toolchains/compiler/cuda.py +++ b/easybuild/toolchains/compiler/cuda.py @@ -70,7 +70,7 @@ class Cuda(Compiler): def __init__(self, *args, **kwargs): """Constructor, with settings custom to CUDA.""" - super(Cuda, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # append CUDA prefix to list of compiler prefixes self.prefixes.append(TC_CONSTANT_CUDA) @@ -79,12 +79,12 @@ def _set_compiler_vars(self): # append lib dir paths to LDFLAGS (only if the paths are actually there) root = self.get_software_root('CUDA')[0] self.variables.append_subdirs("LDFLAGS", root, subdirs=["lib64", "lib"]) - super(Cuda, self)._set_compiler_vars() + super()._set_compiler_vars() def _set_compiler_flags(self): """Collect flags to set, and add them as variables.""" - super(Cuda, self)._set_compiler_flags() + super()._set_compiler_flags() # always C++ compiler flags, even for C! # note: using $LIBS will yield the use of -lcudart in Xlinker, which is silly, but fine diff --git a/easybuild/toolchains/compiler/fujitsu.py b/easybuild/toolchains/compiler/fujitsu.py index c49d36fc33..211fc82180 100644 --- a/easybuild/toolchains/compiler/fujitsu.py +++ b/easybuild/toolchains/compiler/fujitsu.py @@ -89,7 +89,7 @@ class FujitsuCompiler(Compiler): } def prepare(self, *args, **kwargs): - super(FujitsuCompiler, self).prepare(*args, **kwargs) + super().prepare(*args, **kwargs) # fcc doesn't accept e.g. -std=c++11 or -std=gnu++11, only -std=c11 or -std=gnu11 pattern = r'-std=(gnu|c)\+\+(\d+)' @@ -106,7 +106,7 @@ def prepare(self, *args, **kwargs): env.setvar('LIBRARY_PATH', os.pathsep.join([library_path, libdir])) def _set_compiler_vars(self): - super(FujitsuCompiler, self)._set_compiler_vars() + super()._set_compiler_vars() # enable clang compatibility mode self.variables.nappend('CFLAGS', ['-Nclang']) diff --git a/easybuild/toolchains/compiler/gcc.py b/easybuild/toolchains/compiler/gcc.py index 20a969e102..6a75a9e877 100644 --- a/easybuild/toolchains/compiler/gcc.py +++ b/easybuild/toolchains/compiler/gcc.py @@ -121,7 +121,7 @@ class Gcc(Compiler): LIB_MATH = ['m'] def _set_compiler_vars(self): - super(Gcc, self)._set_compiler_vars() + super()._set_compiler_vars() # to get rid of lots of problems with libgfortranbegin # or remove the system gcc-gfortran @@ -158,7 +158,7 @@ def _set_optimal_architecture(self, default_optarch=None): # so try to guess a proper default optarch if none was specified default_optarch = self._guess_aarch64_default_optarch() - super(Gcc, self)._set_optimal_architecture(default_optarch=default_optarch) + super()._set_optimal_architecture(default_optarch=default_optarch) def _guess_aarch64_default_optarch(self): """ diff --git a/easybuild/toolchains/compiler/inteliccifort.py b/easybuild/toolchains/compiler/inteliccifort.py index 434250fce0..bd90bb6bf8 100644 --- a/easybuild/toolchains/compiler/inteliccifort.py +++ b/easybuild/toolchains/compiler/inteliccifort.py @@ -104,11 +104,11 @@ def __init__(self, *args, **kwargs): class_constants = kwargs.setdefault('class_constants', []) class_constants.append('LIB_MULTITHREAD') - super(IntelIccIfort, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _set_compiler_vars(self): """Intel compilers-specific adjustments after setting compiler variables.""" - super(IntelIccIfort, self)._set_compiler_vars() + super()._set_compiler_vars() if not ('icc' in self.COMPILER_MODULE_NAME and 'ifort' in self.COMPILER_MODULE_NAME): raise EasyBuildError("_set_compiler_vars: missing icc and/or ifort from COMPILER_MODULE_NAME %s", @@ -137,4 +137,4 @@ def set_variables(self): if LooseVersion(icc_version) < LooseVersion('12'): self.options.options_map['openmp'] = '-openmp' - super(IntelIccIfort, self).set_variables() + super().set_variables() diff --git a/easybuild/toolchains/compiler/nvhpc.py b/easybuild/toolchains/compiler/nvhpc.py index e32d70de8b..1821afff73 100644 --- a/easybuild/toolchains/compiler/nvhpc.py +++ b/easybuild/toolchains/compiler/nvhpc.py @@ -100,8 +100,8 @@ def _set_compiler_flags(self): """Set -tp=x64 if optarch is set to False.""" if not self.options.get('optarch', False): self.variables.nextend('OPTFLAGS', ['tp=x64']) - super(NVHPC, self)._set_compiler_flags() + super()._set_compiler_flags() def _set_compiler_vars(self): """Set the compiler variables""" - super(NVHPC, self)._set_compiler_vars() + super()._set_compiler_vars() diff --git a/easybuild/toolchains/compiler/pgi.py b/easybuild/toolchains/compiler/pgi.py index 416004b1e2..8971684185 100644 --- a/easybuild/toolchains/compiler/pgi.py +++ b/easybuild/toolchains/compiler/pgi.py @@ -97,7 +97,7 @@ def _set_compiler_flags(self): """Set -tp=x64 if optarch is set to False.""" if not self.options.get('optarch', False): self.variables.nextend('OPTFLAGS', ['tp=x64']) - super(Pgi, self)._set_compiler_flags() + super()._set_compiler_flags() def _set_compiler_vars(self): """Set the compiler variables""" @@ -114,4 +114,4 @@ def _set_compiler_vars(self): else: self.COMPILER_F77 = 'pgf77' - super(Pgi, self)._set_compiler_vars() + super()._set_compiler_vars() diff --git a/easybuild/toolchains/fft/fftw.py b/easybuild/toolchains/fft/fftw.py index cb0d3f2cef..2c698396a1 100644 --- a/easybuild/toolchains/fft/fftw.py +++ b/easybuild/toolchains/fft/fftw.py @@ -74,7 +74,7 @@ def _set_fftw_variables(self): def _set_fft_variables(self): self._set_fftw_variables() - super(Fftw, self)._set_fft_variables() + super()._set_fft_variables() # TODO can these be replaced with the FFT ones? self.variables.join('FFTW_INC_DIR', 'FFT_INC_DIR') diff --git a/easybuild/toolchains/foss.py b/easybuild/toolchains/foss.py index 942aa8a2f5..f272331601 100644 --- a/easybuild/toolchains/foss.py +++ b/easybuild/toolchains/foss.py @@ -46,7 +46,7 @@ class Foss(Gompi, OpenBLAS, FlexiBLAS, ScaLAPACK, Fftw): def __init__(self, *args, **kwargs): """Toolchain constructor.""" - super(Foss, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # need to transform a version like '2018b' with something that is safe to compare with '2019' # comparing subversions that include letters causes TypeErrors in Python 3 diff --git a/easybuild/toolchains/iccifort.py b/easybuild/toolchains/iccifort.py index 80841b9aad..72e6ebf362 100644 --- a/easybuild/toolchains/iccifort.py +++ b/easybuild/toolchains/iccifort.py @@ -69,7 +69,7 @@ def is_deprecated(self): def is_dep_in_toolchain_module(self, name): """Check whether a specific software name is listed as a dependency in the module for this toolchain.""" - res = super(IccIfort, self).is_dep_in_toolchain_module(name) + res = super().is_dep_in_toolchain_module(name) # icc & ifort do not need to be actual dependencies in iccifort module, # since they could also be installed together in a single directory; diff --git a/easybuild/toolchains/iimkl.py b/easybuild/toolchains/iimkl.py index 7e55d71dbb..85856ea52d 100644 --- a/easybuild/toolchains/iimkl.py +++ b/easybuild/toolchains/iimkl.py @@ -56,7 +56,7 @@ class Iimkl(IccIfort, IntelCompilersToolchain, IntelMKL, IntelFFTW): def __init__(self, *args, **kwargs): """Constructor for Iimkl toolchain class.""" - super(Iimkl, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # make sure a non-symbolic version (e.g., 'system') is used before making comparisons using LooseVersion if re.match('^[0-9]', self.version): diff --git a/easybuild/toolchains/iimpi.py b/easybuild/toolchains/iimpi.py index a8dca0f953..a6bd60c656 100644 --- a/easybuild/toolchains/iimpi.py +++ b/easybuild/toolchains/iimpi.py @@ -51,7 +51,7 @@ class Iimpi(IccIfort, IntelCompilersToolchain, IntelMPI): def __init__(self, *args, **kwargs): """Constructor for Iimpi toolchain class.""" - super(Iimpi, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # make sure a non-symbolic version (e.g., 'system') is used before making comparisons using LooseVersion if re.match('^[0-9]', self.version): diff --git a/easybuild/toolchains/iompi.py b/easybuild/toolchains/iompi.py index 2ec287cb77..0b1c9b1b3c 100644 --- a/easybuild/toolchains/iompi.py +++ b/easybuild/toolchains/iompi.py @@ -51,7 +51,7 @@ class Iompi(IccIfort, IntelCompilersToolchain, OpenMPI): def __init__(self, *args, **kwargs): """Constructor for Iompi toolchain class.""" - super(Iompi, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # make sure a non-symbolic version (e.g., 'system') is used before making comparisons using LooseVersion if re.match('^[0-9]', self.version): diff --git a/easybuild/toolchains/linalg/acml.py b/easybuild/toolchains/linalg/acml.py index 2a30636243..9978cc9716 100644 --- a/easybuild/toolchains/linalg/acml.py +++ b/easybuild/toolchains/linalg/acml.py @@ -69,7 +69,7 @@ def __init__(self, *args, **kwargs): """Toolchain constructor.""" class_constants = kwargs.setdefault('class_constants', []) class_constants.extend(['BLAS_LIB', 'BLAS_LIB_MT']) - super(Acml, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _set_blas_variables(self): """Fix the map a bit""" @@ -90,4 +90,4 @@ def _set_blas_variables(self): self.BLAS_LIB.insert(0, "acml_mv") self.BLAS_LIB_MT.insert(0, "acml_mv") - super(Acml, self)._set_blas_variables() + super()._set_blas_variables() diff --git a/easybuild/toolchains/linalg/blacs.py b/easybuild/toolchains/linalg/blacs.py index db18ec85d3..77e94d5166 100644 --- a/easybuild/toolchains/linalg/blacs.py +++ b/easybuild/toolchains/linalg/blacs.py @@ -45,4 +45,4 @@ class Blacs(LinAlg): def _set_blacs_variables(self): """Skip setting BLACS variables if it is not required (e.g., with recent ScaLAPACK versions).""" if self.is_required(self.BLACS_MODULE_NAME[0]): - super(Blacs, self)._set_blacs_variables() + super()._set_blacs_variables() diff --git a/easybuild/toolchains/linalg/blis.py b/easybuild/toolchains/linalg/blis.py index f4ba16574f..32d5c946fb 100644 --- a/easybuild/toolchains/linalg/blis.py +++ b/easybuild/toolchains/linalg/blis.py @@ -56,4 +56,4 @@ def _set_blas_variables(self): if LooseVersion(found_version) > LooseVersion('2.1'): self.BLAS_LIB_MT = ['blis-mt'] - super(Blis, self)._set_blas_variables() + super()._set_blas_variables() diff --git a/easybuild/toolchains/linalg/flexiblas.py b/easybuild/toolchains/linalg/flexiblas.py index 8b874cc767..73cb3ffe0c 100644 --- a/easybuild/toolchains/linalg/flexiblas.py +++ b/easybuild/toolchains/linalg/flexiblas.py @@ -84,7 +84,7 @@ def banned_linked_shared_libs(self): List of shared libraries (names, file names, paths) which are not allowed to be linked in any installed binary/library. """ - banned_libs = super(FlexiBLAS, self).banned_linked_shared_libs() + banned_libs = super().banned_linked_shared_libs() # register backends are banned shared libraries, # to avoid that anything links to them directly (rather than to libflexiblas.so) diff --git a/easybuild/toolchains/linalg/fujitsussl.py b/easybuild/toolchains/linalg/fujitsussl.py index 9e32da3a2c..d5d2df58bb 100644 --- a/easybuild/toolchains/linalg/fujitsussl.py +++ b/easybuild/toolchains/linalg/fujitsussl.py @@ -80,13 +80,13 @@ def _get_software_root(self, name, required=True): else: self.log.debug("Obtained install prefix for %s via $%s: %s", name, env_var, root) else: - root = super(FujitsuSSL, self)._get_software_root(name, required=required) + root = super()._get_software_root(name, required=required) return root def _set_blas_variables(self): """Setting FujitsuSSL specific BLAS related variables""" - super(FujitsuSSL, self)._set_blas_variables() + super()._set_blas_variables() if self.options.get('openmp', None): for flags_var, _ in COMPILER_FLAGS: self.variables.nappend(flags_var, ['SSL2BLAMP']) @@ -96,7 +96,7 @@ def _set_blas_variables(self): def _set_scalapack_variables(self): """Setting FujitsuSSL specific SCALAPACK related variables""" - super(FujitsuSSL, self)._set_scalapack_variables() + super()._set_scalapack_variables() for flags_var, _ in COMPILER_FLAGS: self.variables.nappend(flags_var, ['SCALAPACK']) @@ -106,7 +106,7 @@ def definition(self): The SSL2 module is loaded indirectly (and versionless) via the lang module, and thus is not a direct toolchain component. """ - tc_def = super(FujitsuSSL, self).definition() + tc_def = super().definition() tc_def['BLAS'] = [] tc_def['LAPACK'] = [] tc_def['SCALAPACK'] = [] @@ -120,4 +120,4 @@ def set_variables(self): self.log.devel('set_variables: LinAlg variables %s', self.variables) - super(FujitsuSSL, self).set_variables() + super().set_variables() diff --git a/easybuild/toolchains/linalg/intelmkl.py b/easybuild/toolchains/linalg/intelmkl.py index 19f81963b9..6a253b0d67 100644 --- a/easybuild/toolchains/linalg/intelmkl.py +++ b/easybuild/toolchains/linalg/intelmkl.py @@ -86,7 +86,7 @@ def __init__(self, *args, **kwargs): """Toolchain constructor.""" class_constants = kwargs.setdefault('class_constants', []) class_constants.extend(['BLAS_LIB_MAP', 'SCALAPACK_LIB', 'SCALAPACK_LIB_MT', 'SCALAPACK_LIB_MAP']) - super(IntelMKL, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def set_variables(self): """Set the variables""" @@ -103,7 +103,7 @@ def set_variables(self): elif 'dl' not in self.LIB_EXTRA: self.LIB_EXTRA.append('dl') - super(IntelMKL, self).set_variables() + super().set_variables() def _set_blas_variables(self): """Fix the map a bit""" @@ -136,7 +136,7 @@ def _set_blas_variables(self): # ilp64/i8 self.BLAS_LIB_MAP.update({"lp64": '_ilp64'}) # CPP / CFLAGS - self.variables.nappend_el('CFLAGS', 'DMKL_ILP64') + self.variables.nappend_el('CFLAGS', '-DMKL_ILP64') # exact paths/linking statements depend on imkl version root = self.get_software_root(self.BLAS_MODULE_NAME)[0] @@ -161,7 +161,7 @@ def _set_blas_variables(self): self.BLAS_INCLUDE_DIR = [os.path.join(basedir, 'include')] - super(IntelMKL, self)._set_blas_variables() + super()._set_blas_variables() def _set_blacs_variables(self): mpimap = { @@ -183,7 +183,7 @@ def _set_blacs_variables(self): self.BLACS_LIB_DIR = self.BLAS_LIB_DIR self.BLACS_INCLUDE_DIR = self.BLAS_INCLUDE_DIR - super(IntelMKL, self)._set_blacs_variables() + super()._set_blacs_variables() def _set_scalapack_variables(self): imkl_version = self.get_software_version(self.BLAS_MODULE_NAME)[0] @@ -198,4 +198,4 @@ def _set_scalapack_variables(self): self.SCALAPACK_LIB_DIR = self.BLAS_LIB_DIR self.SCALAPACK_INCLUDE_DIR = self.BLAS_INCLUDE_DIR - super(IntelMKL, self)._set_scalapack_variables() + super()._set_scalapack_variables() diff --git a/easybuild/toolchains/linalg/libsci.py b/easybuild/toolchains/linalg/libsci.py index 773952497c..07f660fee7 100644 --- a/easybuild/toolchains/linalg/libsci.py +++ b/easybuild/toolchains/linalg/libsci.py @@ -80,7 +80,7 @@ def _get_software_root(self, name, required=True): env_vars_str = ', '.join('$' + e for e in env_vars) raise EasyBuildError("Failed to determine install prefix for %s via $%s", name, env_vars_str) else: - root = super(LibSci, self)._get_software_root(name, required=required) + root = super()._get_software_root(name, required=required) return root @@ -98,7 +98,7 @@ def definition(self): The cray-libsci module is loaded indirectly (and versionless) via the PrgEnv module, and thus is not a direct toolchain component. """ - tc_def = super(LibSci, self).definition() + tc_def = super().definition() tc_def['BLAS'] = [] tc_def['LAPACK'] = [] return tc_def diff --git a/easybuild/toolchains/linalg/scalapack.py b/easybuild/toolchains/linalg/scalapack.py index b4c12e6963..c8f0265b45 100644 --- a/easybuild/toolchains/linalg/scalapack.py +++ b/easybuild/toolchains/linalg/scalapack.py @@ -47,4 +47,4 @@ def is_required(self, name): # BLACS is no longer required for ScaLAPACK >= 2.0 return LooseVersion(self.get_software_version(self.SCALAPACK_MODULE_NAME)[0]) < LooseVersion("2.0") else: - return super(ScaLAPACK, self).is_required(name) + return super().is_required(name) diff --git a/easybuild/toolchains/mpi/fujitsumpi.py b/easybuild/toolchains/mpi/fujitsumpi.py index 65c411f0d1..f017e47188 100644 --- a/easybuild/toolchains/mpi/fujitsumpi.py +++ b/easybuild/toolchains/mpi/fujitsumpi.py @@ -61,4 +61,4 @@ def _set_mpi_compiler_variables(self): for var, _ in COMPILER_VARIABLES: self.variables.nappend('OMPI_%s' % var, str(self.variables[var].get_first()), var_class=CommandFlagList) - super(FujitsuMPI, self)._set_mpi_compiler_variables() + super()._set_mpi_compiler_variables() diff --git a/easybuild/toolchains/mpi/intelmpi.py b/easybuild/toolchains/mpi/intelmpi.py index 74dfb7fb57..8dad5b1c2b 100644 --- a/easybuild/toolchains/mpi/intelmpi.py +++ b/easybuild/toolchains/mpi/intelmpi.py @@ -71,12 +71,12 @@ def _set_mpi_compiler_variables(self): for var, _ in COMPILER_VARIABLES: self.variables.nappend('I_MPI_%s' % var, str(self.variables[var].get_first()), var_class=CommandFlagList) - super(IntelMPI, self)._set_mpi_compiler_variables() + super()._set_mpi_compiler_variables() def _set_mpi_variables(self): """Set the other MPI variables""" - super(IntelMPI, self)._set_mpi_variables() + super()._set_mpi_variables() if (LooseVersion(self.version) >= LooseVersion('2019')): lib_dir = [os.path.join('intel64', 'lib', 'release')] @@ -94,7 +94,7 @@ def _set_mpi_variables(self): def set_variables(self): """Intel MPI-specific updates to variables.""" - super(IntelMPI, self).set_variables() + super().set_variables() # add -mt_mpi flag to ensure linking against thread-safe MPI library when OpenMP is enabled if self.options.get('openmp', None) and self.options.get('usempi', None): mt_mpi_option = ['-mt_mpi'] diff --git a/easybuild/toolchains/mpi/mpich.py b/easybuild/toolchains/mpi/mpich.py index 6584a88d5d..3cbc331f69 100644 --- a/easybuild/toolchains/mpi/mpich.py +++ b/easybuild/toolchains/mpi/mpich.py @@ -77,4 +77,4 @@ def _set_mpi_compiler_variables(self): for var, _ in COMPILER_VARIABLES: self.variables.nappend('MPICH_%s' % var, str(self.variables[var].get_first()), var_class=CommandFlagList) - super(Mpich, self)._set_mpi_compiler_variables() + super()._set_mpi_compiler_variables() diff --git a/easybuild/toolchains/mpi/mpich2.py b/easybuild/toolchains/mpi/mpich2.py index 24653a662d..ceed3d622a 100644 --- a/easybuild/toolchains/mpi/mpich2.py +++ b/easybuild/toolchains/mpi/mpich2.py @@ -55,4 +55,4 @@ def _set_mpi_compiler_variables(self): self.MPI_COMPILER_MPIF90 = 'mpif90' self.MPI_COMPILER_MPIFC = 'mpif90' - super(Mpich2, self)._set_mpi_compiler_variables() + super()._set_mpi_compiler_variables() diff --git a/easybuild/toolchains/mpi/mpitrampoline.py b/easybuild/toolchains/mpi/mpitrampoline.py index f3001a8897..cf9ab98997 100644 --- a/easybuild/toolchains/mpi/mpitrampoline.py +++ b/easybuild/toolchains/mpi/mpitrampoline.py @@ -59,7 +59,7 @@ class MPItrampoline(Mpi): def __init__(self, *args, **kwargs): """Toolchain constructor""" - super(MPItrampoline, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _set_mpi_compiler_variables(self): """Define MPI wrapper commands and add MPITRAMPOLINE_* variables to set.""" @@ -75,4 +75,4 @@ def _set_mpi_compiler_variables(self): var_class=CommandFlagList ) - super(MPItrampoline, self)._set_mpi_compiler_variables() + super()._set_mpi_compiler_variables() diff --git a/easybuild/toolchains/mpi/openmpi.py b/easybuild/toolchains/mpi/openmpi.py index 44e9b3d380..436944fb71 100644 --- a/easybuild/toolchains/mpi/openmpi.py +++ b/easybuild/toolchains/mpi/openmpi.py @@ -67,7 +67,7 @@ class OpenMPI(Mpi): def __init__(self, *args, **kwargs): """Toolchain constructor""" - super(OpenMPI, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.orig_tmpdir = None @@ -75,7 +75,7 @@ def prepare(self, *args, **kwargs): """ Prepare for using OpenMPI library in toolchain environment """ - super(OpenMPI, self).prepare(*args, **kwargs) + super().prepare(*args, **kwargs) # OpenMPI 2.x trips if path specified in $TMPDIR is too long # see https://www.open-mpi.org/faq/?category=osx#startup-errors-with-open-mpi-2.0.x @@ -106,11 +106,11 @@ def _set_mpi_compiler_variables(self): for var, _ in COMPILER_VARIABLES: self.variables.nappend('OMPI_%s' % var, str(self.variables[var].get_first()), var_class=CommandFlagList) - super(OpenMPI, self)._set_mpi_compiler_variables() + super()._set_mpi_compiler_variables() def cleanup(self, *args, **kwargs): """Clean up after using OpenMPI in toolchain.""" - super(OpenMPI, self).cleanup(*args, **kwargs) + super().cleanup(*args, **kwargs) tmpdir = os.environ.get('TMPDIR') if tmpdir != self.orig_tmpdir: diff --git a/easybuild/toolchains/mpi/psmpi.py b/easybuild/toolchains/mpi/psmpi.py index 03daf3db82..ce68ddff0f 100644 --- a/easybuild/toolchains/mpi/psmpi.py +++ b/easybuild/toolchains/mpi/psmpi.py @@ -45,4 +45,4 @@ def _set_mpi_compiler_variables(self): self.MPI_COMPILER_MPIF90 = 'mpif90' self.MPI_COMPILER_MPIFC = 'mpif90' - super(Psmpi, self)._set_mpi_compiler_variables() + super()._set_mpi_compiler_variables() diff --git a/easybuild/toolchains/mpi/qlogicmpi.py b/easybuild/toolchains/mpi/qlogicmpi.py index 7af5ed98b9..c3e0b331ab 100644 --- a/easybuild/toolchains/mpi/qlogicmpi.py +++ b/easybuild/toolchains/mpi/qlogicmpi.py @@ -52,4 +52,4 @@ def _set_mpi_compiler_variables(self): self.variables.nappend("MPICH_CCC", str(self.variables['CXX'].get_first()), var_class=CommandFlagList) - super(QLogicMPI, self)._set_mpi_compiler_variables() + super()._set_mpi_compiler_variables() diff --git a/easybuild/tools/asyncprocess.py b/easybuild/tools/asyncprocess.py index 2d9f64f22c..0bf91454bf 100644 --- a/easybuild/tools/asyncprocess.py +++ b/easybuild/tools/asyncprocess.py @@ -86,7 +86,7 @@ def __init__(self, *args, **kwargs): # bufsize=0 is the default in Python 2, but not in recent Python 3 versions, # see https://docs.python.org/3/library/subprocess.html#subprocess.Popen kwargs['bufsize'] = 0 - super(Popen, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def recv(self, maxsize=None): return self._recv('stdout', maxsize) diff --git a/easybuild/tools/config.py b/easybuild/tools/config.py index 664080d8f2..eb4af47650 100644 --- a/easybuild/tools/config.py +++ b/easybuild/tools/config.py @@ -202,7 +202,7 @@ class Singleton(ABCMeta): def __call__(cls, *args, **kwargs): if cls not in cls._instances: - cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + cls._instances[cls] = super().__call__(*args, **kwargs) return cls._instances[cls] diff --git a/easybuild/tools/configobj.py b/easybuild/tools/configobj.py index d2ff5d150e..bf84fa9bd6 100644 --- a/easybuild/tools/configobj.py +++ b/easybuild/tools/configobj.py @@ -154,7 +154,7 @@ class UnknownType(Exception): pass -class Builder(object): +class Builder: def build(self, o): m = getattr(self, 'build_' + o.__class__.__name__, None) @@ -299,7 +299,7 @@ class UnreprError(ConfigObjError): """An error parsing in unrepr mode.""" -class InterpolationEngine(object): +class InterpolationEngine: """ A helper class to help perform string interpolation. @@ -2284,7 +2284,7 @@ def reload(self): self._load(filename, configspec) -class SimpleVal(object): +class SimpleVal: """ A simple validator. Can be used to check that all members expected are present. diff --git a/easybuild/tools/containers/base.py b/easybuild/tools/containers/base.py index 3371719c3d..6f0e9d14b0 100644 --- a/easybuild/tools/containers/base.py +++ b/easybuild/tools/containers/base.py @@ -37,7 +37,7 @@ from easybuild.tools.filetools import write_file -class ContainerGenerator(object): +class ContainerGenerator: """ The parent class for concrete container recipe and image generator. Subclasses have to provide at least template resolution and image creation logic. diff --git a/easybuild/tools/containers/docker.py b/easybuild/tools/containers/docker.py index 76f5713e09..7d96895eda 100644 --- a/easybuild/tools/containers/docker.py +++ b/easybuild/tools/containers/docker.py @@ -152,7 +152,7 @@ def validate(self): """Perform validation of specified container configuration.""" if self.container_config not in DOCKER_OS_INSTALL_DEPS_TMPLS.keys(): raise EasyBuildError("Unsupported container config '%s'" % self.container_config) - super(DockerContainer, self).validate() + super().validate() def build_image(self, dockerfile): ec = self.easyconfigs[-1]['ec'] diff --git a/easybuild/tools/convert.py b/easybuild/tools/convert.py index 3b55a392f6..9501c07965 100644 --- a/easybuild/tools/convert.py +++ b/easybuild/tools/convert.py @@ -55,7 +55,7 @@ def __init__(self, obj): self.data = self._from_string(obj) else: raise EasyBuildError("unsupported type %s for %s: %s", type(obj), self.__class__.__name__, obj) - super(Convert, self).__init__(self.data) + super().__init__(self.data) def _split_string(self, txt, sep=None, max=0): """Split using sep, return list with results. diff --git a/easybuild/tools/filetools.py b/easybuild/tools/filetools.py index 00494e5bd9..2ce00ce7aa 100644 --- a/easybuild/tools/filetools.py +++ b/easybuild/tools/filetools.py @@ -189,7 +189,7 @@ def _hashlib_md5(): global_lock_names = set() -class ZlibChecksum(object): +class ZlibChecksum: """ wrapper class for adler32 and crc32 checksums to match the interface of the hashlib module diff --git a/easybuild/tools/github.py b/easybuild/tools/github.py index c03d92ad24..70ae40b612 100644 --- a/easybuild/tools/github.py +++ b/easybuild/tools/github.py @@ -139,7 +139,7 @@ def pick_default_branch(github_owner): return branch -class Githubfs(object): +class Githubfs: """This class implements some higher level functionality on top of the Github api""" def __init__(self, githubuser, reponame, branchname=None, username=None, password=None, token=None): diff --git a/easybuild/tools/job/backend.py b/easybuild/tools/job/backend.py index 9b372c5848..a6cf40796a 100644 --- a/easybuild/tools/job/backend.py +++ b/easybuild/tools/job/backend.py @@ -39,7 +39,7 @@ from easybuild.tools.utilities import get_subclasses, import_available_modules -class JobBackend(object): +class JobBackend: __metaclass__ = ABCMeta def __init__(self): diff --git a/easybuild/tools/job/gc3pie.py b/easybuild/tools/job/gc3pie.py index b912490d1f..271490260d 100644 --- a/easybuild/tools/job/gc3pie.py +++ b/easybuild/tools/job/gc3pie.py @@ -97,7 +97,7 @@ class GC3Pie(JobBackend): @only_if_module_is_available('gc3libs', pkgname='gc3pie') def __init__(self, *args, **kwargs): """GC3Pie JobBackend constructor.""" - super(GC3Pie, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # _check_version is called by __init__, so guard it (too) with the decorator @only_if_module_is_available('gc3libs', pkgname='gc3pie') diff --git a/easybuild/tools/job/pbs_python.py b/easybuild/tools/job/pbs_python.py index 222479bd29..f3fb0b26d1 100644 --- a/easybuild/tools/job/pbs_python.py +++ b/easybuild/tools/job/pbs_python.py @@ -89,7 +89,7 @@ def __init__(self, *args, **kwargs): """Constructor.""" pbs_server = kwargs.pop('pbs_server', None) - super(PbsPython, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.pbs_server = pbs_server or build_option('job_target_resource') or pbs.pbs_default() self.conn = None @@ -188,7 +188,7 @@ def make_job(self, script, name, env_vars=None, hours=None, cores=None): return PbsJob(self, script, name, env_vars=env_vars, hours=hours, cores=cores, conn=self.conn, ppn=self.ppn) -class PbsJob(object): +class PbsJob: """Interaction with TORQUE""" def __init__(self, server, script, name, env_vars=None, diff --git a/easybuild/tools/job/slurm.py b/easybuild/tools/job/slurm.py index 28d39d278e..85a7b914dc 100644 --- a/easybuild/tools/job/slurm.py +++ b/easybuild/tools/job/slurm.py @@ -29,6 +29,7 @@ * Kenneth Hoste (Ghent University) """ +import os import re from easybuild.base import fancylogger @@ -60,7 +61,7 @@ def __init__(self, *args, **kwargs): if path is None: raise EasyBuildError("Required command '%s' not found", cmd) - super(Slurm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) job_deps_type = build_option('job_deps_type') if job_deps_type is None: @@ -152,7 +153,7 @@ def make_job(self, script, name, env_vars=None, hours=None, cores=None): return SlurmJob(script, name, env_vars=env_vars, hours=hours, cores=cores) -class SlurmJob(object): +class SlurmJob: """Job class for SLURM jobs.""" def __init__(self, script, name, env_vars=None, hours=None, cores=None): @@ -162,13 +163,14 @@ def __init__(self, script, name, env_vars=None, hours=None, cores=None): self.jobid = None self.script = script self.name = name + self.output_dir = build_option('job_output_dir') or '' self.job_specs = { 'job-name': self.name, # pattern for output file for submitted job; # SLURM replaces %j with job ID (see https://slurm.schedmd.com/sbatch.html#lbAH) # %x (job name) replacement needs SLURM >= 17.02.1, thus we add name ourselves - 'output': '%s-%%j.out' % self.name, + 'output': '%s-%%j.out' % os.path.join(self.output_dir, self.name), 'wrap': self.script, } diff --git a/easybuild/tools/loose_version.py b/easybuild/tools/loose_version.py index a454912ed0..af74d5167c 100644 --- a/easybuild/tools/loose_version.py +++ b/easybuild/tools/loose_version.py @@ -15,7 +15,7 @@ from itertools import zip_longest -class LooseVersion(object): +class LooseVersion: """Version numbering for anarchists and software realists. A version number consists of a series of numbers, diff --git a/easybuild/tools/module_generator.py b/easybuild/tools/module_generator.py index eebafb3c4e..fb9b29ac6b 100644 --- a/easybuild/tools/module_generator.py +++ b/easybuild/tools/module_generator.py @@ -117,7 +117,7 @@ def dependencies_for(mod_name, modtool, depth=None): return mods -class ModuleGenerator(object): +class ModuleGenerator: """ Class for generating module files. """ @@ -1161,7 +1161,7 @@ class ModuleGeneratorLua(ModuleGenerator): def __init__(self, *args, **kwargs): """ModuleGeneratorLua constructor.""" - super(ModuleGeneratorLua, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if self.modules_tool: if self.modules_tool.version and LooseVersion(self.modules_tool.version) >= LooseVersion('7.7.38'): @@ -1410,8 +1410,7 @@ def modulerc(self, module_version=None, filepath=None, modulerc_txt=None): else: self.log.info("Lmod v%s < v%s, need to stick to Tcl syntax for .modulerc", lmod_ver, min_ver) - return super(ModuleGeneratorLua, self).modulerc(module_version=module_version, filepath=filepath, - modulerc_txt=modulerc_txt) + return super().modulerc(module_version=module_version, filepath=filepath, modulerc_txt=modulerc_txt) def update_paths(self, key, paths, prepend=True, allow_abs=False, expand_relpaths=True, delim=':'): """ diff --git a/easybuild/tools/module_naming_scheme/categorized_hmns.py b/easybuild/tools/module_naming_scheme/categorized_hmns.py index 9b4a29c447..9863e33834 100644 --- a/easybuild/tools/module_naming_scheme/categorized_hmns.py +++ b/easybuild/tools/module_naming_scheme/categorized_hmns.py @@ -68,7 +68,7 @@ def det_module_subdir(self, ec): Core/compiler, Compiler/GCC/4.8.3/mpi, MPI/GCC/4.8.3/OpenMPI/1.6.5/bio """ moduleclass = ec['moduleclass'] - basedir = super(CategorizedHMNS, self).det_module_subdir(ec) + basedir = super().det_module_subdir(ec) return os.path.join(basedir, moduleclass) @@ -81,7 +81,7 @@ def det_modpath_extensions(self, ec): Compiler/GCC/4.8.3/<moduleclasses> (for GCC/4.8.3 module), MPI/GCC/4.8.3/OpenMPI/1.6.5/<moduleclasses> (for OpenMPI/1.6.5 module) """ - basepaths = super(CategorizedHMNS, self).det_modpath_extensions(ec) + basepaths = super().det_modpath_extensions(ec) return self.categorize_paths(basepaths) @@ -94,7 +94,7 @@ def det_user_modpath_extensions(self, ec): Examples: Compiler/GCC/4.8.3 (for GCC/4.8.3 module), MPI/GCC/4.8.3/OpenMPI/1.6.5 (for OpenMPI/1.6.5 module) """ # Use "system" module path extensions of hierarchical MNS (i.e., w/o module class) - return super(CategorizedHMNS, self).det_modpath_extensions(ec) + return super().det_modpath_extensions(ec) def det_init_modulepaths(self, ec): """ @@ -104,7 +104,7 @@ def det_init_modulepaths(self, ec): Examples: Core/<moduleclasses> """ - basepaths = super(CategorizedHMNS, self).det_init_modulepaths(ec) + basepaths = super().det_init_modulepaths(ec) return self.categorize_paths(basepaths) diff --git a/easybuild/tools/modules.py b/easybuild/tools/modules.py index 237b234e39..97d1d5ae15 100644 --- a/easybuild/tools/modules.py +++ b/easybuild/tools/modules.py @@ -484,7 +484,7 @@ def set_alias_vars(self, alias, value): raise EasyBuildError(f"Unknown search path alias: {alias}") from err -class ModulesTool(object): +class ModulesTool: """An abstract interface to a tool that deals with modules.""" # name of this modules tool (used in log/warning/error messages) NAME = None @@ -1561,7 +1561,7 @@ def tweak_stdout(txt): tweak_stdout_fn = tweak_stdout kwargs.update({'tweak_stdout': tweak_stdout_fn}) - return super(EnvironmentModulesC, self).run_module(*args, **kwargs) + return super().run_module(*args, **kwargs) def update(self): """Update after new modules were added.""" @@ -1604,7 +1604,7 @@ class EnvironmentModulesTcl(EnvironmentModulesC): def set_path_env_var(self, key, paths): """Set environment variable with given name to the given list of paths.""" - super(EnvironmentModulesTcl, self).set_path_env_var(key, paths) + super().set_path_env_var(key, paths) # for Tcl Environment Modules, we need to make sure the _modshare env var is kept in sync setvar('%s_modshare' % key, ':1:'.join(paths), verbose=False) @@ -1630,7 +1630,7 @@ def tweak_stdout(txt): tweak_stdout_fn = tweak_stdout kwargs.update({'tweak_stdout': tweak_stdout_fn}) - return super(EnvironmentModulesTcl, self).run_module(*args, **kwargs) + return super().run_module(*args, **kwargs) def available(self, mod_name=None, extra_args=None): """ @@ -1639,7 +1639,7 @@ def available(self, mod_name=None, extra_args=None): :param mod_name: a (partial) module name for filtering (default: None) """ - mods = super(EnvironmentModulesTcl, self).available(mod_name=mod_name, extra_args=extra_args) + mods = super().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] @@ -1702,7 +1702,7 @@ def __init__(self, *args, **kwargs): # ensure only module names are returned on list (MODULES_LIST_TERSE_OUTPUT added in v4.7) setvar('MODULES_LIST_TERSE_OUTPUT', '', verbose=False) - super(EnvironmentModules, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) version = LooseVersion(self.version) self.supports_tcl_getenv = True self.supports_tcl_check_group = version >= LooseVersion(self.REQ_VERSION_TCL_CHECK_GROUP) @@ -1732,7 +1732,7 @@ def check_module_function(self, allow_mismatch=False, regex=None): else: self.log.debug("Pattern '%s' not found in '_module_raw' function, falling back to 'module' function", mod_cmd_re.pattern) - super(EnvironmentModules, self).check_module_function(allow_mismatch, regex) + super().check_module_function(allow_mismatch, regex) def check_module_output(self, cmd, stdout, stderr): """Check output of 'module' command, see if if is potentially invalid.""" @@ -1754,7 +1754,7 @@ def available(self, mod_name=None, extra_args=None): if LooseVersion(self.version) >= LooseVersion('4.6.0'): extra_args.append(self.SHOW_HIDDEN_OPTION) - return super(EnvironmentModules, self).available(mod_name=mod_name, extra_args=extra_args) + return super().available(mod_name=mod_name, extra_args=extra_args) def get_setenv_value_from_modulefile(self, mod_name, var_name): """ @@ -1834,7 +1834,7 @@ def __init__(self, *args, **kwargs): # (introduced in Lmod 8.8, see also https://github.com/TACC/Lmod/issues/690) setvar('LMOD_TERSE_DECORATIONS', 'no', verbose=False) - super(Lmod, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) version = LooseVersion(self.version) self.supports_depends_on = True @@ -1848,7 +1848,7 @@ def check_module_function(self, *args, **kwargs): """Check whether selected module tool matches 'module' function definition.""" if 'regex' not in kwargs: kwargs['regex'] = r".*(%s|%s)" % (self.COMMAND, self.COMMAND_ENVIRONMENT) - super(Lmod, self).check_module_function(*args, **kwargs) + super().check_module_function(*args, **kwargs) def check_module_output(self, cmd, stdout, stderr): """Check output of 'module' command, see if if is potentially invalid.""" @@ -1876,7 +1876,7 @@ def compose_cmd_list(self, args, opts=None): opts.append((0, self.SHOW_HIDDEN_OPTION)) args = [a for a in args if a != self.SHOW_HIDDEN_OPTION] - return super(Lmod, self).compose_cmd_list(args, opts=opts) + return super().compose_cmd_list(args, opts=opts) def available(self, mod_name=None): """ @@ -1888,7 +1888,7 @@ def available(self, mod_name=None): # make hidden modules visible (requires Lmod 5.7.5) extra_args = [self.SHOW_HIDDEN_OPTION] - mods = super(Lmod, self).available(mod_name=mod_name, extra_args=extra_args) + mods = super().available(mod_name=mod_name, extra_args=extra_args) # only retain actual modules, exclude module directories (which end with a '/') real_mods = [mod for mod in mods if not mod.endswith('/')] @@ -1997,12 +1997,12 @@ def module_wrapper_exists(self, mod_name): First check for wrapper defined in .modulerc.lua, fall back to also checking .modulerc (Tcl syntax). """ mod_wrapper_regex_template = r'^module_version\("(?P<wrapped_mod>.*)", "%s"\)$' - res = super(Lmod, self).module_wrapper_exists(mod_name, modulerc_fn='.modulerc.lua', - mod_wrapper_regex_template=mod_wrapper_regex_template) + res = super().module_wrapper_exists(mod_name, modulerc_fn='.modulerc.lua', + mod_wrapper_regex_template=mod_wrapper_regex_template) # fall back to checking for .modulerc in Tcl syntax if res is None: - res = super(Lmod, self).module_wrapper_exists(mod_name) + res = super().module_wrapper_exists(mod_name) return res diff --git a/easybuild/tools/multidiff.py b/easybuild/tools/multidiff.py index e8881275c9..f4bdc59b7d 100644 --- a/easybuild/tools/multidiff.py +++ b/easybuild/tools/multidiff.py @@ -67,7 +67,7 @@ _log = fancylogger.getLogger('multidiff', fname=False) -class MultiDiff(object): +class MultiDiff: """ Class representing a multi-diff. """ diff --git a/easybuild/tools/options.py b/easybuild/tools/options.py index 4068aa1ad6..b4c5cfb229 100644 --- a/easybuild/tools/options.py +++ b/easybuild/tools/options.py @@ -263,7 +263,7 @@ def __init__(self, *args, **kwargs): constants = {name: value for name, (value, _) in constants.items()} go_cfg_initenv.setdefault(section, {}).update(constants) - super(EasyBuildOptions, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def basic_options(self): """basic runtime options""" diff --git a/easybuild/tools/output.py b/easybuild/tools/output.py index 8439d8f08b..db2d7426fa 100644 --- a/easybuild/tools/output.py +++ b/easybuild/tools/output.py @@ -84,7 +84,7 @@ def colorize(txt, color): return coltxt -class DummyRich(object): +class DummyRich: """ Dummy shim for Rich classes. Used in case Rich is not available, or when EasyBuild is not configured to use rich output style. diff --git a/easybuild/tools/package/package_naming_scheme/pns.py b/easybuild/tools/package/package_naming_scheme/pns.py index fbc503be72..df52f6977d 100644 --- a/easybuild/tools/package/package_naming_scheme/pns.py +++ b/easybuild/tools/package/package_naming_scheme/pns.py @@ -37,7 +37,7 @@ from easybuild.tools.config import build_option -class PackageNamingScheme(object): +class PackageNamingScheme: """Abstract class for package naming schemes""" __metaclass__ = ABCMeta diff --git a/easybuild/tools/repository/gitrepo.py b/easybuild/tools/repository/gitrepo.py index 1e343c2375..7419dfb11d 100644 --- a/easybuild/tools/repository/gitrepo.py +++ b/easybuild/tools/repository/gitrepo.py @@ -145,7 +145,7 @@ def add_easyconfig(self, cfg, name, version, stats, previous_stats): :param previous_stats: list of previous build stats :return: location of archived easyconfig """ - path = super(GitRepository, self).add_easyconfig(cfg, name, version, stats, previous_stats) + path = super().add_easyconfig(cfg, name, version, stats, previous_stats) self.stage_file(path) return path @@ -157,7 +157,7 @@ def add_patch(self, patch, name): :param name: software name :return: location of archived patch """ - path = super(GitRepository, self).add_patch(patch, name) + path = super().add_patch(patch, name) self.stage_file(path) return path diff --git a/easybuild/tools/repository/hgrepo.py b/easybuild/tools/repository/hgrepo.py index a3e678df4a..ae7699606b 100644 --- a/easybuild/tools/repository/hgrepo.py +++ b/easybuild/tools/repository/hgrepo.py @@ -148,7 +148,7 @@ def add_easyconfig(self, cfg, name, version, stats, previous_stats): :param previous_stats: list of previous build stats :return: location of archived easyconfig """ - path = super(HgRepository, self).add_easyconfig(cfg, name, version, stats, previous_stats) + path = super().add_easyconfig(cfg, name, version, stats, previous_stats) self.stage_file(path) return path @@ -160,7 +160,7 @@ def add_patch(self, patch, name): :param name: software name :return: location of archived patch """ - path = super(HgRepository, self).add_patch(patch, name) + path = super().add_patch(patch, name) self.stage_file(path) return path diff --git a/easybuild/tools/repository/repository.py b/easybuild/tools/repository/repository.py index 23f4f53cb8..3f851a87c3 100644 --- a/easybuild/tools/repository/repository.py +++ b/easybuild/tools/repository/repository.py @@ -43,7 +43,7 @@ _log = fancylogger.getLogger('repository', fname=False) -class Repository(object): +class Repository: """ Interface for repositories """ diff --git a/easybuild/tools/repository/svnrepo.py b/easybuild/tools/repository/svnrepo.py index 63e04b6b89..3d97ddce93 100644 --- a/easybuild/tools/repository/svnrepo.py +++ b/easybuild/tools/repository/svnrepo.py @@ -159,7 +159,7 @@ def add_easyconfig(self, cfg, name, version, stats, previous_stats): :param previous_stats: list of previous build stats :return: location of archived easyconfig """ - path = super(SvnRepository, self).add_easyconfig(cfg, name, version, stats, previous_stats) + path = super().add_easyconfig(cfg, name, version, stats, previous_stats) self.stage_file(path) return path @@ -171,7 +171,7 @@ def add_patch(self, patch, name): :param name: software name :return: location of archived patch """ - path = super(SvnRepository, self).add_patch(patch, name) + path = super().add_patch(patch, name) self.stage_file(path) return path diff --git a/easybuild/tools/run.py b/easybuild/tools/run.py index 2e118e0860..0f584179fc 100644 --- a/easybuild/tools/run.py +++ b/easybuild/tools/run.py @@ -118,7 +118,7 @@ def __init__(self, cmd_result, caller_info, *args, **kwargs): self.caller_info = caller_info msg = f"Shell command '{self.cmd_name}' failed!" - super(RunShellCmdError, self).__init__(msg, *args, **kwargs) + super().__init__(msg, *args, **kwargs) def print(self): """ diff --git a/easybuild/tools/toolchain/compiler.py b/easybuild/tools/toolchain/compiler.py index 5619ecc733..b1e6cf8909 100644 --- a/easybuild/tools/toolchain/compiler.py +++ b/easybuild/tools/toolchain/compiler.py @@ -158,13 +158,13 @@ def __init__(self, *args, **kwargs): self.cpu_family = systemtools.get_cpu_family() # list of compiler prefixes self.prefixes = [] - super(Compiler, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def set_options(self, options): """Process compiler toolchain options.""" self._set_compiler_toolchainoptions() self.log.devel('_compiler_set_options: compiler toolchain options %s', self.options) - super(Compiler, self).set_options(options) + super().set_options(options) def set_variables(self): """Set the variables""" @@ -173,7 +173,7 @@ def set_variables(self): self._set_compiler_flags() self.log.devel('set_variables: compiler variables %s', self.variables) - super(Compiler, self).set_variables() + super().set_variables() def _set_compiler_toolchainoptions(self): """Set the compiler related toolchain options""" diff --git a/easybuild/tools/toolchain/fft.py b/easybuild/tools/toolchain/fft.py index 53bce4cd8c..13d8b3e9f2 100644 --- a/easybuild/tools/toolchain/fft.py +++ b/easybuild/tools/toolchain/fft.py @@ -50,7 +50,7 @@ class Fft(Toolchain): def __init__(self, *args, **kwargs): Toolchain.base_init(self) - super(Fft, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _set_fft_variables(self): """Set FFT variables""" @@ -87,4 +87,4 @@ def set_variables(self): self.log.devel('set_variables: FFT variables %s', self.variables) - super(Fft, self).set_variables() + super().set_variables() diff --git a/easybuild/tools/toolchain/linalg.py b/easybuild/tools/toolchain/linalg.py index bbf158d9e5..a9f3c03157 100644 --- a/easybuild/tools/toolchain/linalg.py +++ b/easybuild/tools/toolchain/linalg.py @@ -85,7 +85,7 @@ class LinAlg(Toolchain): def __init__(self, *args, **kwargs): Toolchain.base_init(self) - super(LinAlg, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def set_variables(self): """Set the variables""" @@ -98,7 +98,7 @@ def set_variables(self): self.log.devel('set_variables: LinAlg variables %s', self.variables) - super(LinAlg, self).set_variables() + super().set_variables() def _set_blas_variables(self): """Set BLAS related variables""" diff --git a/easybuild/tools/toolchain/mpi.py b/easybuild/tools/toolchain/mpi.py index aaaf4e7078..2f501d2fec 100644 --- a/easybuild/tools/toolchain/mpi.py +++ b/easybuild/tools/toolchain/mpi.py @@ -174,7 +174,7 @@ def __init__(self, *args, **kwargs): self._set_mpi_options() - super(Mpi, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def _set_mpi_options(self): self.options.add_options(self.MPI_SHARED_OPTS, self.MPI_SHARED_OPTION_MAP) @@ -189,7 +189,7 @@ def set_variables(self): self._set_mpi_variables() self.log.devel('set_variables: compiler variables %s', self.variables) - super(Mpi, self).set_variables() + super().set_variables() def _set_mpi_compiler_variables(self): """Set the MPI compiler variables""" diff --git a/easybuild/tools/toolchain/toolchain.py b/easybuild/tools/toolchain/toolchain.py index c13f9e10d7..171caeabcd 100644 --- a/easybuild/tools/toolchain/toolchain.py +++ b/easybuild/tools/toolchain/toolchain.py @@ -153,7 +153,7 @@ def env_vars_external_module(name, version, metadata): return env_vars -class Toolchain(object): +class Toolchain: """General toolchain class""" OPTIONS_CLASS = ToolchainOptions diff --git a/easybuild/tools/toolchain/variables.py b/easybuild/tools/toolchain/variables.py index 16487de7ff..78f867829a 100644 --- a/easybuild/tools/toolchain/variables.py +++ b/easybuild/tools/toolchain/variables.py @@ -190,4 +190,4 @@ def sanitize(self): self.log.devel("sanitize: PACKED_LINKER_OPTIONS IS_BEGIN %s PREFIX %s BEGIN %s", self.IS_BEGIN, self.PREFIX, self.BEGIN) - super(LinkerFlagList, self).sanitize() + super().sanitize() diff --git a/easybuild/tools/variables.py b/easybuild/tools/variables.py index 423f7adb36..e37814629f 100644 --- a/easybuild/tools/variables.py +++ b/easybuild/tools/variables.py @@ -101,7 +101,7 @@ class StrList(list): JOIN_BEGIN_END = False def __init__(self, *args, **kwargs): - super(StrList, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.log = fancylogger.getLogger(self.__class__.__name__, fname=False) def str_convert(self, x): @@ -133,7 +133,7 @@ def __getattribute__(self, attr_name): elif attr_name == 'nextend_el': return self.extend else: - return super(StrList, self).__getattribute__(attr_name) + return super().__getattribute__(attr_name) def copy(self): """Return copy of self""" @@ -221,7 +221,7 @@ class ListOfLists(list): JOIN_BEGIN_END = False def __init__(self, *args, **kwargs): - super(ListOfLists, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.log = fancylogger.getLogger(self.__class__.__name__, fname=False) self._first = None @@ -457,7 +457,7 @@ class Variables(dict): MAP_CLASS = {} # predefined map to specify (default) mapping between variables and classes def __init__(self, *args, **kwargs): - super(Variables, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.log = fancylogger.getLogger(self.__class__.__name__, fname=False) def get_list_class(self, name): @@ -522,7 +522,7 @@ def setdefault(self, name, default=None, append_empty=False): else: if default is None: default = self.get_instance(name) - super(Variables, self).__setitem__(name, default) + super().__setitem__(name, default) if len(default) == 0: self.log.devel("setdefault: name %s initialising.", name) @@ -566,4 +566,4 @@ def _passthrough(name, *args, **kwargs): return res return _passthrough else: - return super(Variables, self).__getattribute__(attr_name) + return super().__getattribute__(attr_name) diff --git a/easybuild/tools/version.py b/easybuild/tools/version.py index 7b1716a497..b966e294c1 100644 --- a/easybuild/tools/version.py +++ b/easybuild/tools/version.py @@ -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('5.0.0') +VERSION = LooseVersion('5.0.1.dev0') UNKNOWN = 'UNKNOWN' UNKNOWN_EASYBLOCKS_VERSION = '0.0.UNKNOWN.EASYBLOCKS' diff --git a/test/framework/asyncprocess.py b/test/framework/asyncprocess.py index 09045e0e01..d089895f1c 100644 --- a/test/framework/asyncprocess.py +++ b/test/framework/asyncprocess.py @@ -43,7 +43,7 @@ class AsyncProcessTest(EnhancedTestCase): def setUp(self): """ setup a basic shell """ - super(AsyncProcessTest, self).setUp() + super().setUp() self.shell = Popen('sh', stdin=p.PIPE, stdout=p.PIPE, shell=True, executable='/bin/bash') def test_echo_between_process(self): @@ -64,7 +64,7 @@ def test_echo_between_process(self): def tearDown(self): """cleanup""" subprocess_terminate(self.shell, timeout=1) - super(AsyncProcessTest, self).tearDown() + super().tearDown() def suite(): diff --git a/test/framework/build_log.py b/test/framework/build_log.py index 4b29a2af26..af939501ea 100644 --- a/test/framework/build_log.py +++ b/test/framework/build_log.py @@ -52,7 +52,7 @@ class BuildLogTest(EnhancedTestCase): def tearDown(self): """Cleanup after test.""" - super(BuildLogTest, self).tearDown() + super().tearDown() # restore default logging format setLogFormat(LOGGING_FORMAT) diff --git a/test/framework/config.py b/test/framework/config.py index 9614d4fb31..fbd8bf7d2c 100644 --- a/test/framework/config.py +++ b/test/framework/config.py @@ -56,7 +56,7 @@ class EasyBuildConfigTest(EnhancedTestCase): def setUp(self): """Prepare for running a config test.""" reload(eboptions) - super(EasyBuildConfigTest, self).setUp() + super().setUp() self.tmpdir = tempfile.mkdtemp() def purge_environment(self): @@ -68,7 +68,7 @@ def purge_environment(self): def tearDown(self): """Clean up after a config test.""" - super(EasyBuildConfigTest, self).tearDown() + super().tearDown() try: shutil.rmtree(self.tmpdir) diff --git a/test/framework/easyblock.py b/test/framework/easyblock.py index de3b3e5198..0cbefe3387 100644 --- a/test/framework/easyblock.py +++ b/test/framework/easyblock.py @@ -67,7 +67,7 @@ def writeEC(self): def setUp(self): """ setup """ - super(EasyBlockTest, self).setUp() + super().setUp() fd, self.eb_file = tempfile.mkstemp(prefix='easyblock_test_file_', suffix='.eb') os.close(fd) diff --git a/test/framework/easyconfig.py b/test/framework/easyconfig.py index 21a6066557..c4f4ce4439 100644 --- a/test/framework/easyconfig.py +++ b/test/framework/easyconfig.py @@ -104,7 +104,7 @@ class EasyConfigTest(EnhancedTestCase): def setUp(self): """Set up everything for running a unit test.""" - super(EasyConfigTest, self).setUp() + super().setUp() self.orig_get_cpu_architecture = st.get_cpu_architecture self.cwd = os.getcwd() @@ -134,7 +134,7 @@ def tearDown(self): """ make sure to remove the temporary file """ st.get_cpu_architecture = self.orig_get_cpu_architecture - super(EasyConfigTest, self).tearDown() + super().tearDown() if os.path.exists(self.eb_file): os.remove(self.eb_file) @@ -4705,7 +4705,7 @@ def test_unexpected_version_keys_caught(self): def test_resolve_exts_filter_template(self): """Test for resolve_exts_filter_template function.""" - class TestExtension(object): + class TestExtension: def __init__(self, values): self.name = values['name'] self.version = values.get('version') @@ -5037,7 +5037,7 @@ def test_easyconfig_import(self): # and a local variable with a list of imported modules, to check clean error handling test_ec_txt += '\n' + '\n'.join([ "import logging", - "class _TestClass(object):", + "class _TestClass:", " def __init__(self):", " self.log = logging.Logger('alogger')", "local_test = _TestClass()", diff --git a/test/framework/easyconfigs/test_ecs/g/GCC/GCC-10.2.0.eb b/test/framework/easyconfigs/test_ecs/g/GCC/GCC-10.2.0.eb new file mode 100644 index 0000000000..8365cc2798 --- /dev/null +++ b/test/framework/easyconfigs/test_ecs/g/GCC/GCC-10.2.0.eb @@ -0,0 +1,23 @@ +# should be EB_GCC, but OK for testing purposes +easyblock = 'EB_toy' + +name = 'GCC' +version = '10.2.0' + +homepage = 'https://gcc.gnu.org/' +description = """The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Java, and Ada, + as well as libraries for these languages (libstdc++, libgcj,...).""" + +toolchain = SYSTEM + +source_urls = [ + 'http://ftpmirror.gnu.org/%(namelower)s/%(namelower)s-%(version)s', # GCC auto-resolving HTTP mirror + 'http://ftpmirror.gnu.org/gmp', # idem for GMP + 'http://ftpmirror.gnu.org/mpfr', # idem for MPFR + 'http://www.multiprecision.org/mpc/download', # MPC official +] +sources = [SOURCELOWER_TAR_GZ] + + +# this bundle serves as a compiler-only toolchain, so it should be marked as compiler (important for HMNS) +moduleclass = 'compiler' diff --git a/test/framework/easystack.py b/test/framework/easystack.py index 900ed43afd..6b5fedf68a 100644 --- a/test/framework/easystack.py +++ b/test/framework/easystack.py @@ -48,7 +48,7 @@ class EasyStackTest(EnhancedTestCase): def setUp(self): """Set up test.""" - super(EasyStackTest, self).setUp() + super().setUp() self.orig_experimental = easybuild.tools.build_log.EXPERIMENTAL # easystack files are an experimental feature easybuild.tools.build_log.EXPERIMENTAL = True @@ -56,7 +56,7 @@ def setUp(self): def tearDown(self): """Clean up after test.""" easybuild.tools.build_log.EXPERIMENTAL = self.orig_experimental - super(EasyStackTest, self).tearDown() + super().tearDown() def test_easystack_basic(self): """Test for basic easystack files.""" diff --git a/test/framework/ebconfigobj.py b/test/framework/ebconfigobj.py index 1b858c0471..048b356193 100644 --- a/test/framework/ebconfigobj.py +++ b/test/framework/ebconfigobj.py @@ -42,7 +42,7 @@ class TestEBConfigObj(EnhancedTestCase): def setUp(self): """Set some convenience attributes""" - super(TestEBConfigObj, self).setUp() + super().setUp() _, tcs = search_toolchain('') self.tc_names = [x.NAME for x in tcs] diff --git a/test/framework/filetools.py b/test/framework/filetools.py index fe37a07820..373bb4c77f 100644 --- a/test/framework/filetools.py +++ b/test/framework/filetools.py @@ -70,7 +70,7 @@ class FileToolsTest(EnhancedTestCase): def setUp(self): """Test setup.""" - super(FileToolsTest, self).setUp() + super().setUp() self.orig_filetools_std_urllib_urlopen = ft.std_urllib.urlopen if ft.HAVE_REQUESTS: @@ -79,7 +79,7 @@ def setUp(self): def tearDown(self): """Cleanup.""" - super(FileToolsTest, self).tearDown() + super().tearDown() ft.std_urllib.urlopen = self.orig_filetools_std_urllib_urlopen ft.HAVE_REQUESTS = self.orig_filetools_HAVE_REQUESTS @@ -2271,8 +2271,8 @@ def test_copy_dir(self): ft.copy_dir(to_copy, target_dir, ignore=lambda src, names: [x for x in names if '6.4.0-2.28' in x]) self.assertExists(target_dir) - expected = ['GCC-4.6.3.eb', 'GCC-4.6.4.eb', 'GCC-4.8.2.eb', 'GCC-4.8.3.eb', 'GCC-4.9.2.eb', 'GCC-4.9.3-2.25.eb', - 'GCC-4.9.3-2.26.eb', 'GCC-7.3.0-2.30.eb'] + expected = ['GCC-10.2.0.eb', 'GCC-4.6.3.eb', 'GCC-4.6.4.eb', 'GCC-4.8.2.eb', 'GCC-4.8.3.eb', 'GCC-4.9.2.eb', + 'GCC-4.9.3-2.25.eb', 'GCC-4.9.3-2.26.eb', 'GCC-7.3.0-2.30.eb'] self.assertEqual(sorted(os.listdir(target_dir)), expected) # GCC-6.4.0-2.28.eb should not get copied, since it's specified as file too ignore self.assertNotExists(os.path.join(target_dir, 'GCC-6.4.0-2.28.eb')) @@ -2613,7 +2613,7 @@ def test_index_functions(self): # test with specified path with and without trailing '/'s for path in [test_ecs, test_ecs + '/', test_ecs + '//']: index = ft.create_index(path) - self.assertEqual(len(index), 94) + self.assertEqual(len(index), 95) expected = [ os.path.join('b', 'bzip2', 'bzip2-1.0.6-GCC-4.9.2.eb'), @@ -2663,7 +2663,7 @@ def test_index_functions(self): regex = re.compile(r"^== found valid index for %s, so using it\.\.\.$" % ecs_dir) self.assertTrue(regex.match(stdout.strip()), "Pattern '%s' matches with: %s" % (regex.pattern, stdout)) - self.assertEqual(len(index), 25) + self.assertEqual(len(index), 26) for fn in expected: self.assertIn(fn, index) @@ -2693,7 +2693,7 @@ def test_index_functions(self): regex = re.compile(r"^== found valid index for %s, so using it\.\.\.$" % ecs_dir) self.assertTrue(regex.match(stdout.strip()), "Pattern '%s' matches with: %s" % (regex.pattern, stdout)) - self.assertEqual(len(index), 25) + self.assertEqual(len(index), 26) for fn in expected: self.assertIn(fn, index) diff --git a/test/framework/github.py b/test/framework/github.py index ea862afb05..512d01f84f 100644 --- a/test/framework/github.py +++ b/test/framework/github.py @@ -97,7 +97,7 @@ class GithubTest(EnhancedTestCase): def setUp(self): """Test setup.""" - super(GithubTest, self).setUp() + super().setUp() self.github_token = gh.fetch_github_token(GITHUB_TEST_ACCOUNT) @@ -116,7 +116,7 @@ def tearDown(self): """Cleanup after running test.""" easybuild.tools.testing.create_gist = self.orig_testing_create_gist - super(GithubTest, self).tearDown() + super().tearDown() def test_det_pr_title(self): """Test det_pr_title function""" @@ -406,17 +406,16 @@ def test_github_fetch_easyblocks_from_pr(self): 'pr_target_account': gh.GITHUB_EB_MAIN, }) - # TODO: no 5.x PRs for new easyblocks # PR with new easyblock plus non-easyblock file - # all_ebs_pr1964 = ['lammps.py'] + all_ebs_pr1964 = ['lammps.py'] # PR with changed easyblock - all_ebs_pr3631 = ['root.py'] + all_ebs_pr3674 = ['llvm.py'] # PR with more than one easyblock - all_ebs_pr3596 = ['wps.py', 'wrf.py'] + all_ebs_pr1949 = ['configuremake.py', 'rpackage.py'] - for pr, all_ebs in [(3631, all_ebs_pr3631), (3596, all_ebs_pr3596)]: + for pr, all_ebs in [(1964, all_ebs_pr1964), (3674, all_ebs_pr3674), (1949, all_ebs_pr1949)]: try: tmpdir = os.path.join(self.test_prefix, 'pr%s' % pr) with self.mocked_stdout_stderr(): @@ -606,7 +605,7 @@ def test_github_download_repo(self): self.assertExists(repodir) shafile = os.path.join(repodir, 'latest-sha') self.assertTrue(re.match('^[0-9a-f]{40}$', read_file(shafile))) - self.assertExists(os.path.join(repodir, 'easybuild', 'easyconfigs', 'f', 'foss', 'foss-2019b.eb')) + self.assertExists(os.path.join(repodir, 'easybuild', 'easyconfigs', 'f', 'foss', 'foss-2024a.eb')) # current directory should not have changed after calling download_repo self.assertTrue(os.path.samefile(cwd, os.getcwd())) diff --git a/test/framework/hooks.py b/test/framework/hooks.py index 052df5ffdd..18813b4655 100644 --- a/test/framework/hooks.py +++ b/test/framework/hooks.py @@ -45,7 +45,7 @@ class HooksTest(EnhancedTestCase): def setUp(self): """Set up for testing.""" - super(HooksTest, self).setUp() + super().setUp() self.test_hooks_pymod = os.path.join(self.test_prefix, 'test_hooks.py') test_hooks_pymod_txt = '\n'.join([ 'def start_hook():', @@ -92,7 +92,7 @@ def tearDown(self): # reset cached hooks easybuild.tools.hooks._cached_hooks.clear() - super(HooksTest, self).tearDown() + super().tearDown() def test_load_hooks(self): """Test for load_hooks function.""" diff --git a/test/framework/lib.py b/test/framework/lib.py index ca95c0ab47..b9771a41e2 100644 --- a/test/framework/lib.py +++ b/test/framework/lib.py @@ -51,7 +51,7 @@ class EasyBuildLibTest(TestCase): def setUp(self): """Prepare for running test.""" - super(EasyBuildLibTest, self).setUp() + super().setUp() # make sure BuildOptions instance is re-created if BuildOptions in BuildOptions._instances: @@ -61,7 +61,7 @@ def setUp(self): def tearDown(self): """Cleanup after running test.""" - super(EasyBuildLibTest, self).tearDown() + super().tearDown() shutil.rmtree(self.tmpdir) diff --git a/test/framework/module_generator.py b/test/framework/module_generator.py index c5fc23fe06..003c19aea7 100644 --- a/test/framework/module_generator.py +++ b/test/framework/module_generator.py @@ -55,7 +55,7 @@ class ModuleGeneratorTest(EnhancedTestCase): def setUp(self): """Test setup.""" - super(ModuleGeneratorTest, self).setUp() + super().setUp() # find .eb file topdir = os.path.dirname(os.path.abspath(__file__)) eb_path = os.path.join(topdir, 'easyconfigs', 'test_ecs', 'g', 'gzip', 'gzip-1.4.eb') diff --git a/test/framework/modulestool.py b/test/framework/modulestool.py index 594b8b59f4..518714658b 100644 --- a/test/framework/modulestool.py +++ b/test/framework/modulestool.py @@ -63,7 +63,7 @@ class ModulesToolTest(EnhancedTestCase): def setUp(self): """Testcase setup.""" - super(ModulesToolTest, self).setUp() + super().setUp() # keep track of original 'module' function definition so we can restore it self.orig_module = os.environ.get('module', None) @@ -250,7 +250,7 @@ def test_environment_modules_specific(self): def tearDown(self): """Testcase cleanup.""" - super(ModulesToolTest, self).tearDown() + super().tearDown() # restore 'module' function if self.orig_module is not None: diff --git a/test/framework/options.py b/test/framework/options.py index f54bfc4f1a..bd4f4918c5 100644 --- a/test/framework/options.py +++ b/test/framework/options.py @@ -105,7 +105,7 @@ class CommandLineOptionsTest(EnhancedTestCase): def setUp(self): """Set up test.""" - super(CommandLineOptionsTest, self).setUp() + super().setUp() self.github_token = fetch_github_token(GITHUB_TEST_ACCOUNT) self.orig_terminal_supports_colors = easybuild.tools.options.terminal_supports_colors @@ -118,7 +118,7 @@ def tearDown(self): easybuild.tools.options.terminal_supports_colors = self.orig_terminal_supports_colors easybuild.tools.build_log.EXPERIMENTAL = self.orig_experimental - super(CommandLineOptionsTest, self).tearDown() + super().tearDown() def purge_environment(self): """Remove any leftover easybuild variables""" @@ -3758,21 +3758,21 @@ def test_xxx_include_easyblocks(self): from easybuild.framework.easyblock import EasyBlock class EB_afoo(EasyBlock): def __init__(self, *args, **kwargs): - super(EB_afoo, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) """) write_file(os.path.join(self.test_prefix, 'afoo.py'), afoo_txt) foo_txt = textwrap.dedent(""" from easybuild.easyblocks.zfoo import EB_zfoo class EB_foo(EB_zfoo): def __init__(self, *args, **kwargs): - super(EB_foo, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) """) write_file(os.path.join(self.test_prefix, 'foo.py'), foo_txt) zfoo_txt = textwrap.dedent(""" from easybuild.easyblocks.afoo import EB_afoo class EB_zfoo(EB_afoo): def __init__(self, *args, **kwargs): - super(EB_zfoo, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) """) write_file(os.path.join(self.test_prefix, 'zfoo.py'), zfoo_txt) @@ -3933,7 +3933,7 @@ def test_github_xxx_include_easyblocks_from_pr(self): args = [ '--include-easyblocks=%s/*.py' % self.test_prefix, # this shouldn't interfere - '--include-easyblocks-from-pr=3399', # a PR for CMakeMake easyblock + '--include-easyblocks-from-pr=3677', # a PR for CMakeMake easyblock '--list-easyblocks=detailed', '--unittest-file=%s' % self.logfile, '--github-user=%s' % GITHUB_TEST_ACCOUNT, @@ -3947,7 +3947,7 @@ def test_github_xxx_include_easyblocks_from_pr(self): logtxt = read_file(self.logfile) self.assertFalse(stderr) - self.assertEqual(stdout, "== easyblock cmakemake.py included from PR #3399\n") + self.assertEqual(stdout, "== easyblock cmakemake.py included from PR #3677\n") # easyblock included from pr is found path_pattern = os.path.join(self.test_prefix, '.*', 'included-easyblocks-.*', 'easybuild', 'easyblocks') @@ -3977,7 +3977,7 @@ def test_github_xxx_include_easyblocks_from_pr(self): # including the same easyblock twice should work and give priority to the one from the PR args = [ '--include-easyblocks=%s/*.py' % self.test_prefix, - '--include-easyblocks-from-pr=3399', + '--include-easyblocks-from-pr=3677', '--list-easyblocks=detailed', '--unittest-file=%s' % self.logfile, '--github-user=%s' % GITHUB_TEST_ACCOUNT, @@ -3991,9 +3991,9 @@ def test_github_xxx_include_easyblocks_from_pr(self): logtxt = read_file(self.logfile) expected = "WARNING: One or more easyblocks included from multiple locations: " - expected += "cmakemake.py (the one(s) from PR #3399 will be used)" + expected += "cmakemake.py (the one(s) from PR #3677 will be used)" self.assertEqual(stderr.strip(), expected) - self.assertEqual(stdout, "== easyblock cmakemake.py included from PR #3399\n") + self.assertEqual(stdout, "== easyblock cmakemake.py included from PR #3677\n") # easyblock included from pr is found path_pattern = os.path.join(self.test_prefix, '.*', 'included-easyblocks-.*', 'easybuild', 'easyblocks') @@ -4027,8 +4027,8 @@ def test_github_xxx_include_easyblocks_from_pr(self): write_file(self.logfile, '') args = [ - '--from-pr=22227', # PR for Togl easyconfig - '--include-easyblocks-from-pr=3563,3634', # PRs for ConfigureMake and GROMACS easyblock + '--from-pr=22589', # PR for DIAMOND easyconfig + '--include-easyblocks-from-pr=3677,3674', # PRs for CMakeMake and LLVM easyblock '--unittest-file=%s' % self.logfile, '--github-user=%s' % GITHUB_TEST_ACCOUNT, '--extended-dry-run', @@ -4042,27 +4042,27 @@ def test_github_xxx_include_easyblocks_from_pr(self): logtxt = read_file(self.logfile) self.assertFalse(stderr) - self.assertEqual(stdout, "== easyblock configuremake.py included from PR #3563\n" + - "== easyblock gromacs.py included from PR #3634\n") + self.assertEqual(stdout, "== easyblock cmakemake.py included from PR #3677\n" + + "== easyblock llvm.py included from PR #3674\n") # easyconfig from pr is found - ec_pattern = os.path.join(self.test_prefix, '.*', 'files_pr22227', 't', 'Togl', - 'Togl-2.0-GCCcore-13.3.0.eb') + ec_pattern = os.path.join(self.test_prefix, '.*', 'files_pr22589', 'd', 'DIAMOND', + 'DIAMOND-2.1.11-GCC-13.3.0.eb') ec_regex = re.compile(r"Parsing easyconfig file %s" % ec_pattern, re.M) self.assertTrue(ec_regex.search(logtxt), "Pattern '%s' found in: %s" % (ec_regex.pattern, logtxt)) # easyblock included from pr is found eb_regex = re.compile( - r"Derived full easyblock module path for ConfigureMake: easybuild.easyblocks.generic.configuremake", re.M) + r"Derived full easyblock module path for CMakeMake: easybuild.easyblocks.generic.cmakemake", re.M) self.assertTrue(eb_regex.search(logtxt), "Pattern '%s' found in: %s" % (eb_regex.pattern, logtxt)) # easyblock is found via get_easyblock_class - klass = get_easyblock_class('ConfigureMake') + klass = get_easyblock_class('CMakeMake') self.assertTrue(issubclass(klass, EasyBlock), "%s is an EasyBlock derivative class" % klass) # 'undo' import of easyblocks - del sys.modules['easybuild.easyblocks.gromacs'] - del sys.modules['easybuild.easyblocks.generic.configuremake'] + del sys.modules['easybuild.easyblocks.llvm'] + del sys.modules['easybuild.easyblocks.generic.cmakemake'] sys.path[:] = orig_local_sys_path import easybuild.easyblocks reload(easybuild.easyblocks) @@ -4288,7 +4288,7 @@ def test_github_preview_pr(self): self.eb_main(args, raise_error=True) txt = self.get_stdout() self.mock_stdout(False) - regex = re.compile(r"^Comparing bzip2-1.0.6\S* with bzip2-1.0.6") + regex = re.compile(r"^Comparing bzip2-1.0.6\S* with bzip2-1.0.8") self.assertTrue(regex.search(txt), "Pattern '%s' not found in: %s" % (regex.pattern, txt)) def test_github_review_pr(self): @@ -4781,12 +4781,13 @@ def test_github_new_update_pr(self): unstaged_file = os.path.join('easybuild-easyconfigs', 'easybuild', 'easyconfigs', 'test.eb') write_file(os.path.join(git_working_dir, unstaged_file), 'test123') + ec_name = 'bzip2-1.0.8.eb' # a custom commit message is required when doing more than just adding new easyconfigs (e.g., deleting a file) args.extend([ '--git-working-dirs-path=%s' % git_working_dir, - ':bzip2-1.0.6.eb', + f':{ec_name}', ]) - error_msg = "A meaningful commit message must be specified via --pr-commit-msg.*\nDeleted: bzip2-1.0.6.eb" + error_msg = f"A meaningful commit message must be specified via --pr-commit-msg.*\nDeleted: {ec_name}" self.mock_stdout(True) self.assertErrorRegex(EasyBuildError, error_msg, self.eb_main, args, raise_error=True, testing=False) @@ -4808,7 +4809,7 @@ def test_github_new_update_pr(self): regexs[-1] = r"^\s*2 files changed" regexs.remove(r"^\* title: \"\{tools\}\[gompi/2018a\] toy v0.0 w/ test\"") regexs.append(r"^\* title: \"just a test\"") - regexs.append(r".*/bzip2-1.0.6.eb\s*\|") + regexs.append(rf".*/{ec_name}\s*\|") regexs.append(r".*[0-9]+ deletions\(-\)") self._assert_regexs(regexs, txt) @@ -4835,7 +4836,7 @@ def test_github_new_update_pr(self): r"^\* title: \"test-1-2-3\"", r"^\* overview of changes:", r".*/toy-0.0-gompi-2018a-test.eb\s*\|", - r".*/bzip2-1.0.6.eb\s*\|", + rf".*/{ec_name}\s*\|", r"^\s*2 files changed", r".*[0-9]+ deletions\(-\)", ] @@ -4855,7 +4856,7 @@ def test_github_new_update_pr(self): self.assertTrue(regex.search(txt), "Pattern '%s' found in: %s" % (regex.pattern, txt)) # modifying an existing easyconfig requires a custom PR title - gcc_ec = os.path.join(test_ecs, 'g', 'GCC', 'GCC-4.9.2.eb') + gcc_ec = os.path.join(test_ecs, 'g', 'GCC', 'GCC-10.2.0.eb') self.assertExists(gcc_ec) args = [ @@ -5088,20 +5089,21 @@ def test_github_new_pr_delete(self): print("Skipping test_new_pr_delete, no GitHub token available?") return + ec_name = 'bzip2-1.0.8.eb' args = [ '--new-pr', '--github-user=%s' % GITHUB_TEST_ACCOUNT, - ':bzip2-1.0.6.eb', + f':{ec_name}', '-D', '--disable-cleanup-tmpdir', - '--pr-title=delete bzip2-1.6.0', - '--pr-commit-msg="delete bzip2-1.6.0.eb"' + f'--pr-title=delete {ec_name}', + f'--pr-commit-msg="delete {ec_name}"' ] txt, _ = self._run_mock_eb(args, do_build=True, raise_error=True, testing=False) regexs = [ r"^== fetching branch 'develop' from https://github.com/easybuilders/easybuild-easyconfigs.git...", - r'title: "delete bzip2-1.6.0"', + rf'title: "delete {ec_name}"', r"1 file(s?) changed,( 0 insertions\(\+\),)? [0-9]+ deletions\(-\)", ] self._assert_regexs(regexs, txt) @@ -5302,10 +5304,12 @@ def test_github_empty_pr(self): # get file from develop branch full_url = URL_SEPARATOR.join([GITHUB_RAW, GITHUB_EB_MAIN, GITHUB_EASYCONFIGS_REPO, - 'develop/easybuild/easyconfigs/z/zlib/zlib-1.2.11-GCCcore-6.4.0.eb']) + 'develop/easybuild/easyconfigs/z/zlib/zlib-1.3.1-GCCcore-14.2.0.eb']) ec_fn = os.path.basename(full_url) with self.mocked_stdout_stderr(): ec = download_file(ec_fn, full_url, path=os.path.join(self.test_prefix, ec_fn)) + if not ec: + self.fail(f"Failed to download {full_url}") # try to open new pr with unchanged file args = [ @@ -6839,7 +6843,7 @@ def test_sanity_check_only(self): self.assertNotIn('self.build_in_installdir = True', toy_eb_txt) - regex = re.compile(r'^(\s+)(super\(EB_toy, self\).__init__.*)\n', re.M) + regex = re.compile(r'^(\s+)(super\(\).__init__.*)\n', re.M) toy_eb_txt = regex.sub(r'\1\2\n\1self.build_in_installdir = True', toy_eb_txt) self.assertIn('self.build_in_installdir = True', toy_eb_txt) diff --git a/test/framework/parallelbuild.py b/test/framework/parallelbuild.py index 90c4d0df1c..e89dd2a8e3 100644 --- a/test/framework/parallelbuild.py +++ b/test/framework/parallelbuild.py @@ -84,7 +84,7 @@ def mock(*args, **kwargs): return 1 -class MockPbsJob(object): +class MockPbsJob: """Mocking class for PbsJob.""" def __init__(self, *args, **kwargs): diff --git a/test/framework/repository.py b/test/framework/repository.py index aeb4f97155..488d6c1e91 100644 --- a/test/framework/repository.py +++ b/test/framework/repository.py @@ -51,7 +51,7 @@ class RepositoryTest(EnhancedTestCase): def setUp(self): """Set up test.""" - super(RepositoryTest, self).setUp() + super().setUp() self.path = tempfile.mkdtemp(prefix='easybuild-repo-') shutil.rmtree(self.path, True) @@ -165,7 +165,7 @@ def check_ec(path, expected_buildstats): def tearDown(self): """Clean up after test.""" - super(RepositoryTest, self).tearDown() + super().tearDown() shutil.rmtree(self.path, True) diff --git a/test/framework/robot.py b/test/framework/robot.py index 746d71639e..5c9843526c 100644 --- a/test/framework/robot.py +++ b/test/framework/robot.py @@ -112,14 +112,14 @@ def install_mock_module(self): def setUp(self): """Set up test.""" - super(RobotTest, self).setUp() + super().setUp() self.github_token = fetch_github_token(GITHUB_TEST_ACCOUNT) self.orig_experimental = easybuild.framework.easyconfig.tools._log.experimental self.orig_modtool = self.modtool def tearDown(self): """Test cleanup.""" - super(RobotTest, self).tearDown() + super().tearDown() # restore log.experimental easybuild.framework.easyconfig.tools._log.experimental = self.orig_experimental diff --git a/test/framework/run.py b/test/framework/run.py index 1c5cf3a422..0b8c8397bf 100644 --- a/test/framework/run.py +++ b/test/framework/run.py @@ -64,12 +64,12 @@ class RunTest(EnhancedTestCase): def setUp(self): """Set up test.""" - super(RunTest, self).setUp() + super().setUp() self.orig_experimental = easybuild.tools.utilities._log.experimental def tearDown(self): """Test cleanup.""" - super(RunTest, self).tearDown() + super().tearDown() # restore log.experimental easybuild.tools.utilities._log.experimental = self.orig_experimental diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/dummyextension.py b/test/framework/sandbox/easybuild/easyblocks/generic/dummyextension.py index e0429a450b..4fef55690a 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/dummyextension.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/dummyextension.py @@ -36,7 +36,7 @@ class DummyExtension(ExtensionEasyBlock): def __init__(self, *args, **kwargs): - super(DummyExtension, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # use lowercase name as default value for expected module name, and replace '-' with '_' if 'modulename' not in self.options: diff --git a/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py b/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py index 12a1e5830b..c347e05d40 100644 --- a/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py +++ b/test/framework/sandbox/easybuild/easyblocks/generic/toy_extension.py @@ -64,10 +64,10 @@ def pre_install_extension(self): """ Prepare installation of toy extension. """ - super(Toy_Extension, self).pre_install_extension() + super().pre_install_extension() if self.src: - super(Toy_Extension, self).install_extension(unpack_src=True) + super().install_extension(unpack_src=True) EB_toy.configure_step(self.master, name=self.name, cfg=self.cfg) def install_extension(self, *args, **kwargs): @@ -99,7 +99,7 @@ def post_install_extension(self): """ Wrap up installation of toy extension. """ - super(Toy_Extension, self).post_install_extension() + super().post_install_extension() EB_toy.install_step(self.master, name=self.name) @@ -112,4 +112,4 @@ def sanity_check_step(self, *args, **kwargs): } if self.src: custom_paths['files'].extend(['bin/%s' % self.name, 'lib/lib%s.a' % self.name]) - return super(Toy_Extension, self).sanity_check_step(custom_paths=custom_paths) + return super().sanity_check_step(custom_paths=custom_paths) diff --git a/test/framework/sandbox/easybuild/easyblocks/t/toy.py b/test/framework/sandbox/easybuild/easyblocks/t/toy.py index 5c434e31c7..764c00dac7 100644 --- a/test/framework/sandbox/easybuild/easyblocks/t/toy.py +++ b/test/framework/sandbox/easybuild/easyblocks/t/toy.py @@ -69,7 +69,7 @@ def extra_options(extra_vars=None): def __init__(self, *args, **kwargs): """Constructor""" - super(EB_toy, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) setvar('TOY', '%s-%s' % (self.name, self.version)) @@ -93,7 +93,7 @@ def run_all_steps(self, *args, **kwargs): # inject list of values for prebuildopts, same length as buildopts self.cfg['prebuildopts'] = ["echo hello && "] * len(self.cfg['buildopts']) - return super(EB_toy, self).run_all_steps(*args, **kwargs) + return super().run_all_steps(*args, **kwargs) def configure_step(self, name=None, cfg=None): """Configure build of toy.""" @@ -150,7 +150,7 @@ def post_processing_step(self): """Any postprocessing for toy""" libdir = os.path.join(self.installdir, 'lib') write_file(os.path.join(libdir, 'lib%s_post.a' % self.name), self.name.upper()) - super(EB_toy, self).post_processing_step() + super().post_processing_step() @property def required_deps(self): @@ -164,7 +164,7 @@ def pre_install_extension(self): """ Prepare installation of toy as extension. """ - super(EB_toy, self).install_extension(unpack_src=True) + super().install_extension(unpack_src=True) self.configure_step() def install_extension(self): @@ -191,7 +191,7 @@ def post_install_extension(self): def make_module_step(self, fake=False): """Generate module file.""" if self.cfg.get('make_module', True) or fake: - modpath = super(EB_toy, self).make_module_step(fake=fake) + modpath = super().make_module_step(fake=fake) else: modpath = self.module_generator.get_modules_path(fake=fake) @@ -199,6 +199,6 @@ def make_module_step(self, fake=False): def make_module_extra(self): """Extra stuff for toy module""" - txt = super(EB_toy, self).make_module_extra() + txt = super().make_module_extra() txt += self.module_generator.set_environment('TOY', os.getenv('TOY', '<TOY_env_var_not_defined>')) return txt diff --git a/test/framework/sandbox/easybuild/easyblocks/t/toy_deprecated.py b/test/framework/sandbox/easybuild/easyblocks/t/toy_deprecated.py index 80891ff152..a184697ed6 100644 --- a/test/framework/sandbox/easybuild/easyblocks/t/toy_deprecated.py +++ b/test/framework/sandbox/easybuild/easyblocks/t/toy_deprecated.py @@ -37,4 +37,4 @@ class EB_toy_deprecated(EB_toy): def post_install_step(self): """Any postprocessing for toy (deprecated)""" print("This step is deprecated.") - super(EB_toy, self).post_install_step() + super().post_install_step() diff --git a/test/framework/sandbox/easybuild/easyblocks/t/toy_eula.py b/test/framework/sandbox/easybuild/easyblocks/t/toy_eula.py index add589838d..18a1932255 100644 --- a/test/framework/sandbox/easybuild/easyblocks/t/toy_eula.py +++ b/test/framework/sandbox/easybuild/easyblocks/t/toy_eula.py @@ -35,7 +35,7 @@ class EB_toy_eula(EB_toy): def prepare_step(self, *args, **kwargs): """Constructor""" - super(EB_toy_eula, self).prepare_step(*args, **kwargs) + super().prepare_step(*args, **kwargs) # EULA for toy must be accepted via --accept-eula-for EasyBuild configuration option, # or via 'accept_eula = True' in easyconfig file diff --git a/test/framework/sandbox/sources/p/Python/Python-3.7.2.tgz b/test/framework/sandbox/sources/p/Python/Python-3.7.2.tgz deleted file mode 100644 index a1583ec2c0..0000000000 Binary files a/test/framework/sandbox/sources/p/Python/Python-3.7.2.tgz and /dev/null differ diff --git a/test/framework/systemtools.py b/test/framework/systemtools.py index 7529166d72..3f0fa7ecc7 100644 --- a/test/framework/systemtools.py +++ b/test/framework/systemtools.py @@ -356,7 +356,7 @@ class SystemToolsTest(EnhancedTestCase): def setUp(self): """Set up systemtools test.""" - super(SystemToolsTest, self).setUp() + super().setUp() self.orig_get_cpu_architecture = st.get_cpu_architecture self.orig_get_os_name = st.get_os_name self.orig_get_os_type = st.get_os_type @@ -390,7 +390,7 @@ def tearDown(self): st.ETC_OS_RELEASE = self.orig_ETC_OS_RELEASE if self.orig_archspec_cpu_host is not None: st.archspec_cpu_host = self.orig_archspec_cpu_host - super(SystemToolsTest, self).tearDown() + super().tearDown() def test_avail_core_count_native(self): """Test getting core count.""" @@ -580,7 +580,7 @@ def test_cpu_arch_name_native(self): def test_cpu_arch_name(self): """Test getting CPU arch name.""" - class MicroArch(object): + class MicroArch: def __init__(self, name): self.name = name diff --git a/test/framework/toolchain.py b/test/framework/toolchain.py index e55ccabe93..57d0406174 100644 --- a/test/framework/toolchain.py +++ b/test/framework/toolchain.py @@ -66,7 +66,7 @@ class ToolchainTest(EnhancedTestCase): def setUp(self): """Set up toolchain test.""" - super(ToolchainTest, self).setUp() + super().setUp() self.orig_get_cpu_architecture = st.get_cpu_architecture self.orig_get_cpu_family = st.get_cpu_family self.orig_get_cpu_model = st.get_cpu_model @@ -80,7 +80,7 @@ def tearDown(self): st.get_cpu_family = self.orig_get_cpu_family st.get_cpu_model = self.orig_get_cpu_model st.get_cpu_vendor = self.orig_get_cpu_vendor - super(ToolchainTest, self).tearDown() + super().tearDown() def get_toolchain(self, name, version=None): """Get a toolchain object instance to test with.""" diff --git a/test/framework/toy_build.py b/test/framework/toy_build.py index d46e755ebc..5f02ea2f1e 100644 --- a/test/framework/toy_build.py +++ b/test/framework/toy_build.py @@ -70,7 +70,7 @@ class ToyBuildTest(EnhancedTestCase): def setUp(self): """Test setup.""" - super(ToyBuildTest, self).setUp() + super().setUp() fd, self.dummylogfn = tempfile.mkstemp(prefix='easybuild-dummy', suffix='.log') os.close(fd) @@ -106,7 +106,7 @@ def tearDown(self): # reset cached hooks easybuild.tools.hooks._cached_hooks.clear() - super(ToyBuildTest, self).tearDown() + super().tearDown() # remove logs if os.path.exists(self.dummylogfn): @@ -2645,7 +2645,7 @@ def test_toy_build_enhanced_sanity_check(self): " 'dirs': [],", " }", " cmds = ['toy']", - " return super(EB_toy, self).sanity_check_step(custom_paths=paths, custom_commands=cmds)", + " return super().sanity_check_step(custom_paths=paths, custom_commands=cmds)", ]) test_toy_easyblock = os.path.join(self.test_prefix, 'toy.py') write_file(test_toy_easyblock, toy_easyblock_txt + toy_custom_sanity_check_step) @@ -2810,7 +2810,7 @@ def sanity_check_step(self): 'dirs': ['lib/py-%(pyshortver)s'], } cmds = ['python%(pyshortver)s'] - return super(EB_toy, self).sanity_check_step(custom_paths=paths, custom_commands=cmds) + return super().sanity_check_step(custom_paths=paths, custom_commands=cmds) """) test_toy_easyblock = os.path.join(self.test_prefix, 'toy.py') write_file(test_toy_easyblock, toy_easyblock_txt + toy_custom_sanity_check_step) @@ -3852,7 +3852,7 @@ def test_toy_build_lock(self): orig_sigalrm_handler = signal.getsignal(signal.SIGALRM) # define a context manager that remove a lock after a while, so we can check the use of --wait-for-lock - class RemoveLockAfter(object): + class RemoveLockAfter: def __init__(self, seconds, lock_fp): self.seconds = seconds self.lock_fp = lock_fp @@ -3955,7 +3955,7 @@ def test_toy_lock_cleanup_signals(self): orig_sigalrm_handler = signal.getsignal(signal.SIGALRM) # context manager which stops the function being called with the specified signal - class WaitAndSignal(object): + class WaitAndSignal: def __init__(self, seconds, signum): self.seconds = seconds self.signum = signum diff --git a/test/framework/tweak.py b/test/framework/tweak.py index 79d39ef440..dcc3d8dd5e 100644 --- a/test/framework/tweak.py +++ b/test/framework/tweak.py @@ -80,7 +80,8 @@ def test_find_matching_easyconfigs(self): self.assertTrue(len(ecs) == 1 and ecs[0].endswith('/%s-%s.eb' % (name, installver))) ecs = find_matching_easyconfigs('GCC', '*', [test_easyconfigs_path]) - gccvers = ['4.6.3', '4.6.4', '4.8.2', '4.8.3', '4.9.2', '4.9.3-2.25', '4.9.3-2.26', '6.4.0-2.28', '7.3.0-2.30'] + gccvers = ['10.2.0', '4.6.3', '4.6.4', '4.8.2', '4.8.3', '4.9.2', '4.9.3-2.25', + '4.9.3-2.26', '6.4.0-2.28', '7.3.0-2.30'] self.assertEqual(len(ecs), len(gccvers)) ecs_basename = [os.path.basename(ec) for ec in ecs] for gccver in gccvers: @@ -127,7 +128,7 @@ def test_obtain_ec_for(self): } (generated, ec_file) = obtain_ec_for(specs, [test_easyconfigs_path]) self.assertFalse(generated) - self.assertEqual(os.path.basename(ec_file), 'GCC-7.3.0-2.30.eb') + self.assertEqual(os.path.basename(ec_file), 'GCC-10.2.0.eb') # generate non-existing easyconfig change_dir(self.test_prefix) diff --git a/test/framework/utilities.py b/test/framework/utilities.py index 27ba444d96..1600d6f67b 100644 --- a/test/framework/utilities.py +++ b/test/framework/utilities.py @@ -85,7 +85,7 @@ class EnhancedTestCase(TestCase): def setUp(self): """Set up testcase.""" - super(EnhancedTestCase, self).setUp() + super().setUp() # make sure option parser doesn't pick up any cmdline arguments/options while len(sys.argv) > 1: @@ -232,7 +232,7 @@ def log_to_testlogfile(self): def tearDown(self): """Clean up after running testcase.""" - super(EnhancedTestCase, self).tearDown() + super().tearDown() self.log.info("Cleaning up for test %s", self.id()) diff --git a/test/framework/utilities_test.py b/test/framework/utilities_test.py index ee36a0bdff..64af27ce91 100644 --- a/test/framework/utilities_test.py +++ b/test/framework/utilities_test.py @@ -47,7 +47,7 @@ class UtilitiesTest(EnhancedTestCase): def setUp(self): """ setup """ - super(UtilitiesTest, self).setUp() + super().setUp() self.test_tmp_logdir = tempfile.mkdtemp() os.environ['EASYBUILD_TMP_LOGDIR'] = self.test_tmp_logdir