Skip to content

Commit 7846bb9

Browse files
Merge pull request #3111 from boegel/pick_dep_version
take into account that dependency version could be a dict rather than a string value in template_constant_dict
2 parents cbde621 + 1ea42a2 commit 7846bb9

File tree

5 files changed

+93
-36
lines changed

5 files changed

+93
-36
lines changed

easybuild/framework/easyconfig/easyconfig.py

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
from easybuild.tools.module_naming_scheme.utilities import det_hidden_modname, is_valid_module_name
6969
from easybuild.tools.modules import modules_tool
7070
from easybuild.tools.py2vs3 import OrderedDict, create_base_metaclass, string_type
71-
from easybuild.tools.systemtools import check_os_dependency, get_cpu_architecture
71+
from easybuild.tools.systemtools import check_os_dependency, pick_dep_version
7272
from easybuild.tools.toolchain.toolchain import SYSTEM_TOOLCHAIN_NAME, is_system_toolchain
7373
from easybuild.tools.toolchain.toolchain import TOOLCHAIN_CAPABILITIES, TOOLCHAIN_CAPABILITY_CUDA
7474
from easybuild.tools.toolchain.utilities import get_toolchain, search_toolchain
@@ -1231,31 +1231,6 @@ def get_parsed_multi_deps(self):
12311231

12321232
return multi_deps
12331233

1234-
def find_dep_version_match(self, dep_version):
1235-
"""Identify the correct version for this system from the choices provided. This returns the version to use."""
1236-
if isinstance(dep_version, string_type):
1237-
self.log.debug("Version is already a string ('%s'), OK", dep_version)
1238-
return dep_version
1239-
elif dep_version is None:
1240-
self.log.debug("Version is None, OK")
1241-
return None
1242-
elif isinstance(dep_version, dict):
1243-
# figure out matches based on dict keys (after splitting on '=')
1244-
my_arch_key = 'arch=%s' % get_cpu_architecture()
1245-
arch_keys = [x for x in dep_version.keys() if x.startswith('arch=')]
1246-
other_keys = [x for x in dep_version.keys() if x not in arch_keys]
1247-
if other_keys:
1248-
raise EasyBuildError("Unexpected keys in version: %s. Only 'arch=' keys are supported", other_keys)
1249-
if arch_keys:
1250-
if my_arch_key in dep_version:
1251-
ver = dep_version[my_arch_key]
1252-
self.log.info("Version selected from %s using key %s: %s", dep_version, my_arch_key, ver)
1253-
return ver
1254-
else:
1255-
raise EasyBuildError("No matches for version in %s (looking for %s)", dep_version, my_arch_key)
1256-
1257-
raise EasyBuildError("Unknown value type for version: %s", dep_version)
1258-
12591234
# private method
12601235
def _parse_dependency(self, dep, hidden=False, build_only=False):
12611236
"""
@@ -1337,7 +1312,7 @@ def _parse_dependency(self, dep, hidden=False, build_only=False):
13371312
raise EasyBuildError("Dependency %s of unsupported type: %s", dep, type(dep))
13381313

13391314
# Find the version to use on this system
1340-
dependency['version'] = self.find_dep_version_match(dependency['version'])
1315+
dependency['version'] = pick_dep_version(dependency['version'])
13411316

13421317
if dependency['external_module']:
13431318
# check whether the external module is hidden

easybuild/framework/easyconfig/templates.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
from easybuild.base import fancylogger
3939
from easybuild.tools.build_log import EasyBuildError
4040
from easybuild.tools.py2vs3 import string_type
41-
from easybuild.tools.systemtools import get_shared_lib_ext
41+
from easybuild.tools.systemtools import get_shared_lib_ext, pick_dep_version
4242

4343

4444
_log = fancylogger.getLogger('easyconfig.templates', fname=False)
@@ -228,6 +228,7 @@ def template_constant_dict(config, ignore=None, skip_lower=None):
228228
raise EasyBuildError("Unexpected type for dependency: %s", dep)
229229

230230
if isinstance(dep_name, string_type) and dep_name.lower() == name.lower():
231+
dep_version = pick_dep_version(dep_version)
231232
template_values['%sver' % pref] = dep_version
232233
dep_version_parts = dep_version.split('.')
233234
template_values['%smajver' % pref] = dep_version_parts[0]

easybuild/tools/systemtools.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
from easybuild.tools.build_log import EasyBuildError
4646
from easybuild.tools.config import build_option
4747
from easybuild.tools.filetools import is_readable, read_file, which
48+
from easybuild.tools.py2vs3 import string_type
4849
from easybuild.tools.run import run_cmd
4950

5051

@@ -864,3 +865,40 @@ def check_python_version():
864865
raise EasyBuildError("EasyBuild is not compatible (yet) with Python %s", python_ver)
865866

866867
return (python_maj_ver, python_min_ver)
868+
869+
870+
def pick_dep_version(dep_version):
871+
"""
872+
Pick the correct dependency version to use for this system.
873+
Input can either be:
874+
* a string value (or None)
875+
* a dict with options to choose from
876+
877+
Return value is the version to use.
878+
"""
879+
if isinstance(dep_version, string_type):
880+
_log.debug("Version is already a string ('%s'), OK", dep_version)
881+
result = dep_version
882+
883+
elif dep_version is None:
884+
_log.debug("Version is None, OK")
885+
result = None
886+
887+
elif isinstance(dep_version, dict):
888+
# figure out matches based on dict keys (after splitting on '=')
889+
my_arch_key = 'arch=%s' % get_cpu_architecture()
890+
arch_keys = [x for x in dep_version.keys() if x.startswith('arch=')]
891+
other_keys = [x for x in dep_version.keys() if x not in arch_keys]
892+
if other_keys:
893+
raise EasyBuildError("Unexpected keys in version: %s. Only 'arch=' keys are supported", other_keys)
894+
if arch_keys:
895+
if my_arch_key in dep_version:
896+
result = dep_version[my_arch_key]
897+
_log.info("Version selected from %s using key %s: %s", dep_version, my_arch_key, result)
898+
else:
899+
raise EasyBuildError("No matches for version in %s (looking for %s)", dep_version, my_arch_key)
900+
901+
else:
902+
raise EasyBuildError("Unknown value type for version: %s", dep_version)
903+
904+
return result

test/framework/easyconfig.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
from easybuild.framework.easyconfig.easyconfig import letter_dir_for, process_easyconfig, resolve_template
5353
from easybuild.framework.easyconfig.easyconfig import triage_easyconfig_params, verify_easyconfig_filename
5454
from easybuild.framework.easyconfig.licenses import License, LicenseGPLv3
55-
from easybuild.framework.easyconfig.parser import fetch_parameters_from_easyconfig
55+
from easybuild.framework.easyconfig.parser import EasyConfigParser, fetch_parameters_from_easyconfig
5656
from easybuild.framework.easyconfig.templates import template_constant_dict, to_template_str
5757
from easybuild.framework.easyconfig.style import check_easyconfigs_style
5858
from easybuild.framework.easyconfig.tools import categorize_files_by_type, check_sha256_checksums, dep_graph
@@ -2560,25 +2560,48 @@ def test_template_constant_dict(self):
25602560
expected['parallel'] = 42
25612561
self.assertEqual(res, expected)
25622562

2563-
ec = EasyConfig(os.path.join(test_ecs_dir, 't', 'toy', 'toy-0.0-deps.eb'))
2563+
toy_ec = os.path.join(test_ecs_dir, 't', 'toy', 'toy-0.0-deps.eb')
2564+
toy_ec_txt = read_file(toy_ec)
2565+
25642566
# fiddle with version to check version_minor template ('0' should be retained)
2565-
ec['version'] = '0.01'
2567+
toy_ec_txt = re.sub('version = .*', 'version = "0.01"', toy_ec_txt)
2568+
2569+
my_arch = st.get_cpu_architecture()
2570+
2571+
# add Java dep with version specified using a dict value
2572+
toy_ec_txt += '\n'.join([
2573+
"dependencies += [",
2574+
" ('Python', '3.7.2'),"
2575+
" ('Java', {",
2576+
" 'arch=%s': '1.8.0_221'," % my_arch,
2577+
" 'arch=fooarch': '1.8.0-foo',",
2578+
" })",
2579+
"]",
2580+
])
2581+
2582+
test_ec = os.path.join(self.test_prefix, 'test.eb')
2583+
write_file(test_ec, toy_ec_txt)
2584+
2585+
# only perform shallow/quick parse (as is done in list_software function)
2586+
ec = EasyConfigParser(filename=test_ec).get_config_dict()
25662587

25672588
expected = {
2568-
'bitbucket_account': 'toy',
2569-
'github_account': 'toy',
2589+
'javamajver': '1',
2590+
'javashortver': '1.8',
2591+
'javaver': '1.8.0_221',
25702592
'name': 'toy',
25712593
'namelower': 'toy',
25722594
'nameletter': 't',
25732595
'toolchain_name': 'system',
25742596
'toolchain_version': 'system',
25752597
'nameletterlower': 't',
2576-
'parallel': None,
2598+
'pymajver': '3',
2599+
'pyshortver': '3.7',
2600+
'pyver': '3.7.2',
25772601
'version': '0.01',
25782602
'version_major': '0',
25792603
'version_major_minor': '0.01',
25802604
'version_minor': '01',
2581-
'versionprefix': '',
25822605
'versionsuffix': '-deps',
25832606
}
25842607
res = template_constant_dict(ec)

test/framework/systemtools.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
from easybuild.tools.systemtools import CPU_FAMILIES, POWER_LE, DARWIN, LINUX, UNKNOWN
4444
from easybuild.tools.systemtools import CPU_VENDORS, AMD, APM, ARM, CAVIUM, IBM, INTEL
4545
from easybuild.tools.systemtools import MAX_FREQ_FP, PROC_CPUINFO_FP, PROC_MEMINFO_FP
46-
from easybuild.tools.systemtools import check_python_version
46+
from easybuild.tools.systemtools import check_python_version, pick_dep_version
4747
from easybuild.tools.systemtools import det_parallelism, get_avail_core_count, get_cpu_architecture, get_cpu_family
4848
from easybuild.tools.systemtools import get_cpu_features, get_cpu_model, get_cpu_speed, get_cpu_vendor
4949
from easybuild.tools.systemtools import get_gcc_version, get_glibc_version, get_os_type, get_os_name, get_os_version
@@ -837,6 +837,26 @@ def mock_python_ver(py_maj_ver, py_min_ver):
837837
if sys.version_info[:2] == (2, 6):
838838
self.assertTrue(stderr.startswith(py26_depr_warning))
839839

840+
def test_pick_dep_version(self):
841+
"""Test pick_dep_version function."""
842+
843+
self.assertEqual(pick_dep_version(None), None)
844+
self.assertEqual(pick_dep_version('1.2.3'), '1.2.3')
845+
846+
dep_ver_dict = {
847+
'arch=x86_64': '1.2.3-amd64',
848+
'arch=POWER': '1.2.3-ppc64le',
849+
}
850+
851+
st.get_cpu_architecture = lambda: X86_64
852+
self.assertEqual(pick_dep_version(dep_ver_dict), '1.2.3-amd64')
853+
854+
st.get_cpu_architecture = lambda: POWER
855+
self.assertEqual(pick_dep_version(dep_ver_dict), '1.2.3-ppc64le')
856+
857+
error_pattern = "Unknown value type for version"
858+
self.assertErrorRegex(EasyBuildError, error_pattern, pick_dep_version, ('1.2.3', '4.5.6'))
859+
840860

841861
def suite():
842862
""" returns all the testcases in this module """

0 commit comments

Comments
 (0)