Skip to content

Commit d6fd2ec

Browse files
authored
Merge pull request #3077 from boegel/depr_Lmod6
deprecate support for using Lmod 6.x
2 parents cb1408d + d56d09e commit d6fd2ec

File tree

7 files changed

+65
-54
lines changed

7 files changed

+65
-54
lines changed

.github/workflows/unit_tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
strategy:
88
matrix:
99
python: [2.7, 3.5, 3.6, 3.7, 3.8]
10-
modules_tool: [Lmod-6.6.3, Lmod-7.8.22, Lmod-8.1.14, modules-tcl-1.147, modules-3.2.10, modules-4.1.4]
10+
modules_tool: [Lmod-7.8.22, Lmod-8.2.3, modules-tcl-1.147, modules-3.2.10, modules-4.1.4]
1111
module_syntax: [Lua, Tcl]
1212
# exclude some configuration for non-Lmod modules tool:
1313
# - don't test with Lua module syntax (only supported in Lmod)

.travis.yml

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
language: python
2-
python: 2.6
3-
dist: trusty
2+
python: 2.7
3+
dist: xenial
44
env:
55
matrix:
66
# purposely specifying slowest builds first, to gain time overall
7-
- LMOD_VERSION=6.5.1
8-
- LMOD_VERSION=6.5.1 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
97
- LMOD_VERSION=7.8.22
108
- LMOD_VERSION=7.8.22 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
11-
- LMOD_VERSION=8.0.9
12-
- LMOD_VERSION=8.0.9 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
9+
- LMOD_VERSION=8.2.3
10+
- LMOD_VERSION=8.2.3 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
1311
- ENV_MOD_VERSION=3.2.10 TEST_EASYBUILD_MODULES_TOOL=EnvironmentModulesC TEST_EASYBUILD_MODULE_SYNTAX=Tcl
1412
- ENV_MOD_TCL_VERSION=1.147 TEST_EASYBUILD_MODULES_TOOL=EnvironmentModulesTcl TEST_EASYBUILD_MODULE_SYNTAX=Tcl
1513
- ENV_MOD_VERSION=4.1.4 TEST_EASYBUILD_MODULE_SYNTAX=Tcl TEST_EASYBUILD_MODULES_TOOL=EnvironmentModules # Tmod 4.1.4 is used in RHEL8
@@ -19,44 +17,32 @@ matrix:
1917
# mark build as finished as soon as job has failed
2018
fast_finish: true
2119
include:
22-
# also test default configuration with Python 2.7
20+
# also test default configuration with Python 2.6
21+
- python: 2.6
22+
env: LMOD_VERSION=7.8.22
23+
dist: trusty
24+
# single configuration to test with Lmod 6 and Python 2.7
2325
- python: 2.7
24-
env: LMOD_VERSION=6.6.3
25-
dist: xenial
26+
env: LMOD_VERSION=6.5.1 TEST_EASYBUILD_SILENCE_DEPRECATION_WARNINGS=Lmod6
2627
# also test with Python 3.6
27-
- python: 3.6
28-
env: LMOD_VERSION=6.6.3
29-
dist: xenial
30-
- python: 3.6
31-
env: LMOD_VERSION=6.5.1 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
32-
dist: xenial
3328
- python: 3.6
3429
env: LMOD_VERSION=7.8.22
35-
dist: xenial
3630
- python: 3.6
3731
env: LMOD_VERSION=7.8.22 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
38-
dist: xenial
3932
- python: 3.6
40-
env: LMOD_VERSION=8.0.9
41-
dist: xenial
33+
env: LMOD_VERSION=8.2.3
4234
- python: 3.6
43-
env: LMOD_VERSION=8.0.9 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
44-
dist: xenial
35+
env: LMOD_VERSION=8.2.3 TEST_EASYBUILD_MODULE_SYNTAX=Tcl
4536
- python: 3.6
4637
env: ENV_MOD_VERSION=3.2.10 TEST_EASYBUILD_MODULES_TOOL=EnvironmentModulesC TEST_EASYBUILD_MODULE_SYNTAX=Tcl
47-
dist: xenial
4838
- python: 3.6
4939
env: ENV_MOD_TCL_VERSION=1.147 TEST_EASYBUILD_MODULES_TOOL=EnvironmentModulesTcl TEST_EASYBUILD_MODULE_SYNTAX=Tcl
50-
dist: xenial
5140
- python: 3.6
5241
env: ENV_MOD_VERSION=4.1.4 TEST_EASYBUILD_MODULE_SYNTAX=Tcl TEST_EASYBUILD_MODULES_TOOL=EnvironmentModules # Tmod 4.1.4 is used in RHEL8
53-
dist: xenial
5442
# also test most common configuration with Python 3.5 and 3.7
5543
- python: 3.5
5644
env: LMOD_VERSION=7.8.22
57-
dist: xenial
5845
- python: 3.7
59-
dist: xenial
6046
env: LMOD_VERSION=7.8.22
6147
- python: 3.8
6248
dist: xenial

easybuild/tools/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX):
196196
'pr_target_repo',
197197
'rpath_filter',
198198
'regtest_output_dir',
199+
'silence_deprecation_warnings',
199200
'skip',
200201
'stop',
201202
'subdir_user_modules',

easybuild/tools/modules.py

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@
130130

131131
class ModulesTool(object):
132132
"""An abstract interface to a tool that deals with modules."""
133+
# name of this modules tool (used in log/warning/error messages)
134+
NAME = None
133135
# position and optionname
134136
TERSE_OPTION = (0, '--terse')
135137
# module command to use
@@ -143,6 +145,8 @@ class ModulesTool(object):
143145
VERSION_OPTION = '--version'
144146
# minimal required version (StrictVersion; suffix rc replaced with b (and treated as beta by StrictVersion))
145147
REQ_VERSION = None
148+
# deprecated version limit (support for versions below this version is deprecated)
149+
DEPR_VERSION = None
146150
# maximum version allowed (StrictVersion; suffix rc replaced with b (and treated as beta by StrictVersion))
147151
MAX_VERSION = None
148152
# the regexp, should have a "version" group (multiline search)
@@ -159,7 +163,7 @@ def __init__(self, mod_paths=None, testing=False):
159163
# this can/should be set to True during testing
160164
self.testing = testing
161165

162-
self.log = fancylogger.getLogger(self.__class__.__name__, fname=False)
166+
self.log = fancylogger.getLogger(self.NAME, fname=False)
163167

164168
# DEPRECATED!
165169
self._modules = []
@@ -178,19 +182,20 @@ def __init__(self, mod_paths=None, testing=False):
178182

179183
# only use command path in environment variable if command in not available in $PATH
180184
if which(self.cmd) is None and env_cmd_path is not None:
181-
self.log.debug('Set command via environment variable %s: %s', self.COMMAND_ENVIRONMENT, self.cmd)
185+
self.log.debug("Set %s command via environment variable %s: %s",
186+
self.NAME, self.COMMAND_ENVIRONMENT, self.cmd)
182187
self.cmd = env_cmd_path
183188

184189
# check whether paths obtained via $PATH and $LMOD_CMD are different
185190
elif which(self.cmd) != env_cmd_path:
186-
self.log.debug("Different paths found for module command '%s' via which/$PATH and $%s: %s vs %s",
187-
self.COMMAND, self.COMMAND_ENVIRONMENT, self.cmd, env_cmd_path)
191+
self.log.debug("Different paths found for %s command '%s' via which/$PATH and $%s: %s vs %s",
192+
self.NAME, self.COMMAND, self.COMMAND_ENVIRONMENT, self.cmd, env_cmd_path)
188193

189194
# make sure the module command was found
190195
if self.cmd is None:
191-
raise EasyBuildError("No command set.")
196+
raise EasyBuildError("No command set for %s", self.NAME)
192197
else:
193-
self.log.debug('Using command %s' % self.cmd)
198+
self.log.debug('Using %s command %s', self.NAME, self.cmd)
194199

195200
# version of modules tool
196201
self.version = None
@@ -204,13 +209,13 @@ def __init__(self, mod_paths=None, testing=False):
204209

205210
def buildstats(self):
206211
"""Return tuple with data to be included in buildstats"""
207-
return (self.__class__.__name__, self.cmd, self.version)
212+
return (self.NAME, self.cmd, self.version)
208213

209214
def set_and_check_version(self):
210215
"""Get the module version, and check any requirements"""
211-
if self.COMMAND in MODULE_VERSION_CACHE:
212-
self.version = MODULE_VERSION_CACHE[self.COMMAND]
213-
self.log.debug("Found cached version for %s: %s", self.COMMAND, self.version)
216+
if self.cmd in MODULE_VERSION_CACHE:
217+
self.version = MODULE_VERSION_CACHE[self.cmd]
218+
self.log.debug("Found cached version for %s command %s: %s", self.NAME, self.COMMAND, self.version)
214219
return
215220

216221
if self.VERSION_REGEXP is None:
@@ -223,7 +228,7 @@ def set_and_check_version(self):
223228
res = ver_re.search(txt)
224229
if res:
225230
self.version = res.group('version')
226-
self.log.info("Found version %s" % self.version)
231+
self.log.info("Found %s version %s", self.NAME, self.version)
227232

228233
# make sure version is a valid StrictVersion (e.g., 5.7.3.1 is invalid),
229234
# and replace 'rc' by 'b', to make StrictVersion treat it as a beta-release
@@ -233,47 +238,59 @@ def set_and_check_version(self):
233238

234239
self.log.info("Converted actual version to '%s'" % self.version)
235240
else:
236-
raise EasyBuildError("Failed to determine version from option '%s' output: %s",
237-
self.VERSION_OPTION, txt)
241+
raise EasyBuildError("Failed to determine %s version from option '%s' output: %s",
242+
self.NAME, self.VERSION_OPTION, txt)
238243
except (OSError) as err:
239-
raise EasyBuildError("Failed to check version: %s", err)
244+
raise EasyBuildError("Failed to check %s version: %s", self.NAME, err)
240245

241246
if self.REQ_VERSION is None and self.MAX_VERSION is None:
242247
self.log.debug("No version requirement defined.")
243248

244249
elif build_option('modules_tool_version_check'):
245-
self.log.debug("Checking whether modules tool version '%s' meets requirements", self.version)
250+
self.log.debug("Checking whether %s version %s meets requirements", self.NAME, self.version)
246251

247252
if self.REQ_VERSION is not None:
248-
self.log.debug("Required minimum version defined.")
253+
self.log.debug("Required minimum %s version defined: %s", self.NAME, self.REQ_VERSION)
249254
if StrictVersion(self.version) < StrictVersion(self.REQ_VERSION):
250255
raise EasyBuildError("EasyBuild requires %s >= v%s, found v%s",
251-
self.__class__.__name__, self.REQ_VERSION, self.version)
256+
self.NAME, self.REQ_VERSION, self.version)
252257
else:
253-
self.log.debug('Version %s matches requirement >= %s', self.version, self.REQ_VERSION)
258+
self.log.debug('%s version %s matches requirement >= %s', self.NAME, self.version, self.REQ_VERSION)
259+
260+
if self.DEPR_VERSION is not None:
261+
self.log.debug("Deprecated %s version limit defined: %s", self.NAME, self.DEPR_VERSION)
262+
if StrictVersion(self.version) < StrictVersion(self.DEPR_VERSION):
263+
depr_msg = "Support for %s version < %s is deprecated, " % (self.NAME, self.DEPR_VERSION)
264+
depr_msg += "found version %s" % self.version
265+
266+
silence_deprecation_warnings = build_option('silence_deprecation_warnings') or []
267+
268+
if self.version.startswith('6') and 'Lmod6' in silence_deprecation_warnings:
269+
self.log.warning(depr_msg)
270+
else:
271+
self.log.deprecated(depr_msg, '5.0')
254272

255273
if self.MAX_VERSION is not None:
256-
self.log.debug("Maximum allowed version defined.")
274+
self.log.debug("Maximum allowed %s version defined: %s", self.NAME, self.MAX_VERSION)
257275
if StrictVersion(self.version) > StrictVersion(self.MAX_VERSION):
258276
raise EasyBuildError("EasyBuild requires %s <= v%s, found v%s",
259-
self.__class__.__name__, self.MAX_VERSION, self.version)
277+
self.NAME, self.MAX_VERSION, self.version)
260278
else:
261279
self.log.debug('Version %s matches requirement <= %s', self.version, self.MAX_VERSION)
262280
else:
263281
self.log.debug("Skipping modules tool version '%s' requirements check", self.version)
264282

265-
MODULE_VERSION_CACHE[self.COMMAND] = self.version
283+
MODULE_VERSION_CACHE[self.cmd] = self.version
266284

267285
def check_cmd_avail(self):
268286
"""Check whether modules tool command is available."""
269287
cmd_path = which(self.cmd)
270288
if cmd_path is not None:
271289
self.cmd = cmd_path
272-
self.log.info("Full path for module command is %s, so using it" % self.cmd)
290+
self.log.info("Full path for %s command is %s, so using it", self.NAME, self.cmd)
273291
else:
274-
mod_tool = self.__class__.__name__
275292
mod_tools = avail_modules_tools().keys()
276-
error_msg = "%s modules tool can not be used, '%s' command is not available" % (mod_tool, self.cmd)
293+
error_msg = "%s modules tool can not be used, '%s' command is not available" % (self.NAME, self.cmd)
277294
error_msg += "; use --modules-tool to specify a different modules tool to use (%s)" % ', '.join(mod_tools)
278295
raise EasyBuildError(error_msg)
279296

@@ -292,7 +309,7 @@ def check_module_function(self, allow_mismatch=False, regex=None):
292309
if regex is None:
293310
regex = r".*%s" % os.path.basename(self.cmd)
294311
mod_cmd_re = re.compile(regex, re.M)
295-
mod_details = "pattern '%s' (%s)" % (mod_cmd_re.pattern, self.__class__.__name__)
312+
mod_details = "pattern '%s' (%s)" % (mod_cmd_re.pattern, self.NAME)
296313

297314
if ec == 0:
298315
if mod_cmd_re.search(out):
@@ -671,7 +688,7 @@ def set_path_env_var(self, key, paths):
671688

672689
def check_module_output(self, cmd, stdout, stderr):
673690
"""Check output of 'module' command, see if if is potentially invalid."""
674-
self.log.debug("No checking of module output implemented for %s", self.__class__.__name__)
691+
self.log.debug("No checking of module output implemented for %s", self.NAME)
675692

676693
def compose_cmd_list(self, args, opts=None):
677694
"""
@@ -1075,6 +1092,7 @@ def update(self):
10751092

10761093
class EnvironmentModulesC(ModulesTool):
10771094
"""Interface to (C) environment modules (modulecmd)."""
1095+
NAME = "Environment Modules v3"
10781096
COMMAND = "modulecmd"
10791097
REQ_VERSION = '3.2.10'
10801098
MAX_VERSION = '3.99'
@@ -1110,6 +1128,7 @@ def update(self):
11101128

11111129
class EnvironmentModulesTcl(EnvironmentModulesC):
11121130
"""Interface to (Tcl) environment modules (modulecmd.tcl)."""
1131+
NAME = "ancient Tcl-only Environment Modules"
11131132
# Tcl environment modules have no --terse (yet),
11141133
# -t must be added after the command ('avail', 'list', etc.)
11151134
TERSE_OPTION = (1, '-t')
@@ -1182,6 +1201,7 @@ def remove_module_path(self, path, set_mod_paths=True):
11821201

11831202
class EnvironmentModules(EnvironmentModulesTcl):
11841203
"""Interface to environment modules 4.0+"""
1204+
NAME = "Environment Modules v4"
11851205
COMMAND = os.path.join(os.getenv('MODULESHOME', 'MODULESHOME_NOT_DEFINED'), 'libexec', 'modulecmd.tcl')
11861206
REQ_VERSION = '4.0.0'
11871207
MAX_VERSION = None
@@ -1197,9 +1217,11 @@ def check_module_output(self, cmd, stdout, stderr):
11971217

11981218
class Lmod(ModulesTool):
11991219
"""Interface to Lmod."""
1220+
NAME = "Lmod"
12001221
COMMAND = 'lmod'
12011222
COMMAND_ENVIRONMENT = 'LMOD_CMD'
12021223
REQ_VERSION = '6.5.1'
1224+
DEPR_VERSION = '7.0.0'
12031225
REQ_VERSION_DEPENDS_ON = '7.6.1'
12041226
VERSION_REGEXP = r"^Modules\s+based\s+on\s+Lua:\s+Version\s+(?P<version>\d\S*)\s"
12051227
USER_CACHE_DIR = os.path.join(os.path.expanduser('~'), '.lmod.d', '.cache')

easybuild/tools/options.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ def override_options(self):
412412
'rpath-filter': ("List of regex patterns to use for filtering out RPATH paths", 'strlist', 'store', None),
413413
'set-default-module': ("Set the generated module as default", None, 'store_true', False),
414414
'set-gid-bit': ("Set group ID bit on newly created directories", None, 'store_true', False),
415+
'silence-deprecation-warnings': ("Silence specified deprecation warnings", 'strlist', 'extend', None),
415416
'sticky-bit': ("Set sticky bit on newly created directories", None, 'store_true', False),
416417
'skip-test-cases': ("Skip running test cases", None, 'store_true', False, 't'),
417418
'trace': ("Provide more information in output to stdout on progress", None, 'store_true', False, 'T'),

test/framework/modulestool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ def test_lmod_specific(self):
176176
fake_path = os.path.join(self.test_installpath, 'lmod')
177177
fake_lmod_txt = '\n'.join([
178178
'#!/bin/bash',
179-
'echo "Modules based on Lua: Version %s " >&2' % Lmod.REQ_VERSION,
179+
'echo "Modules based on Lua: Version %s " >&2' % Lmod.DEPR_VERSION,
180180
'echo "os.environ[\'FOO\'] = \'foo\'"',
181181
])
182182
write_file(fake_path, fake_lmod_txt)

test/framework/utilities.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ def init_config(args=None, build_options=None, with_include=True):
435435
'extended_dry_run': False,
436436
'external_modules_metadata': ConfigObj(),
437437
'local_var_naming_check': 'error',
438+
'silence_deprecation_warnings': eb_go.options.silence_deprecation_warnings,
438439
'suffix_modules_path': GENERAL_CLASS,
439440
'valid_module_classes': module_classes(),
440441
'valid_stops': [x[0] for x in EasyBlock.get_steps()],

0 commit comments

Comments
 (0)