Skip to content

Commit 1bbd3b6

Browse files
committed
Merge branch '5.0.x' of github.com:easybuilders/easybuild-framework into 5.0.x_fix_ci_apptainer
2 parents e330850 + ae320db commit 1bbd3b6

File tree

6 files changed

+78
-19
lines changed

6 files changed

+78
-19
lines changed

easybuild/framework/easyblock.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import traceback
5555
from concurrent.futures import ThreadPoolExecutor
5656
from datetime import datetime
57+
from textwrap import indent
5758

5859
import easybuild.tools.environment as env
5960
import easybuild.tools.toolchain as toolchain
@@ -953,7 +954,8 @@ def obtain_file(self, filename, extension=False, urls=None, download_filename=No
953954
if download_instructions is None:
954955
download_instructions = self.cfg['download_instructions']
955956
if download_instructions is not None and download_instructions != "":
956-
msg = "\nDownload instructions:\n\n" + download_instructions + '\n'
957+
msg = "\nDownload instructions:\n\n" + indent(download_instructions, ' ') + '\n\n'
958+
msg += "Make the files available in the active source path: %s\n" % ':'.join(source_paths())
957959
print_msg(msg, prefix=False, stderr=True)
958960
error_msg += "please follow the download instructions above, and make the file available "
959961
error_msg += "in the active source path (%s)" % ':'.join(source_paths())

easybuild/framework/easyconfig/templates.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@
9797
('cuda_cc_cmake', "List of CUDA compute capabilities suitable for use with $CUDAARCHS in CMake 3.18+"),
9898
('cuda_cc_space_sep', "Space-separated list of CUDA compute capabilities"),
9999
('cuda_cc_semicolon_sep', "Semicolon-separated list of CUDA compute capabilities"),
100+
('cuda_int_comma_sep', "Comma-separated list of integer CUDA compute capabilities"),
101+
('cuda_int_space_sep', "Space-separated list of integer CUDA compute capabilities"),
102+
('cuda_int_semicolon_sep', "Semicolon-separated list of integer CUDA compute capabilities"),
100103
('cuda_sm_comma_sep', "Comma-separated list of sm_* values that correspond with CUDA compute capabilities"),
101104
('cuda_sm_space_sep', "Space-separated list of sm_* values that correspond with CUDA compute capabilities"),
102105
]
@@ -365,6 +368,10 @@ def template_constant_dict(config, ignore=None, toolchain=None):
365368
template_values['cuda_cc_space_sep'] = ' '.join(cuda_compute_capabilities)
366369
template_values['cuda_cc_semicolon_sep'] = ';'.join(cuda_compute_capabilities)
367370
template_values['cuda_cc_cmake'] = ';'.join(cc.replace('.', '') for cc in cuda_compute_capabilities)
371+
int_values = [cc.replace('.', '') for cc in cuda_compute_capabilities]
372+
template_values['cuda_int_comma_sep'] = ','.join(int_values)
373+
template_values['cuda_int_space_sep'] = ' '.join(int_values)
374+
template_values['cuda_int_semicolon_sep'] = ';'.join(int_values)
368375
sm_values = ['sm_' + cc.replace('.', '') for cc in cuda_compute_capabilities]
369376
template_values['cuda_sm_comma_sep'] = ','.join(sm_values)
370377
template_values['cuda_sm_space_sep'] = ' '.join(sm_values)

easybuild/tools/run.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import re
4343
import signal
4444
import shutil
45+
import string
4546
import subprocess
4647
import sys
4748
import tempfile
@@ -187,6 +188,19 @@ def cache_aware_func(cmd, *args, **kwargs):
187188
run_shell_cmd_cache = run_cmd_cache
188189

189190

191+
def fileprefix_from_cmd(cmd, allowed_chars=False):
192+
"""
193+
Simplify the cmd to only the allowed_chars we want in a filename
194+
195+
:param cmd: the cmd (string)
196+
:param allowed_chars: characters allowed in filename (defaults to string.ascii_letters + string.digits + "_-")
197+
"""
198+
if not allowed_chars:
199+
allowed_chars = f"{string.ascii_letters}{string.digits}_-"
200+
201+
return ''.join([c for c in cmd if c in allowed_chars])
202+
203+
190204
@run_shell_cmd_cache
191205
def run_shell_cmd(cmd, fail_on_error=True, split_stderr=False, stdin=None, env=None,
192206
hidden=False, in_dry_run=False, verbose_dry_run=False, work_dir=None, use_bash=True,
@@ -238,7 +252,6 @@ def to_cmd_str(cmd):
238252
work_dir = os.getcwd()
239253

240254
cmd_str = to_cmd_str(cmd)
241-
cmd_name = os.path.basename(cmd_str.split(' ')[0])
242255

243256
thread_id = None
244257
if asynchronous:
@@ -254,6 +267,7 @@ def to_cmd_str(cmd):
254267
if output_file:
255268
toptmpdir = os.path.join(tempfile.gettempdir(), 'run-shell-cmd-output')
256269
os.makedirs(toptmpdir, exist_ok=True)
270+
cmd_name = fileprefix_from_cmd(os.path.basename(cmd_str.split(' ')[0]))
257271
tmpdir = tempfile.mkdtemp(dir=toptmpdir, prefix=f'{cmd_name}-')
258272
cmd_out_fp = os.path.join(tmpdir, 'out.txt')
259273
_log.info(f'run_cmd: Output of "{cmd_str}" will be logged to {cmd_out_fp}')

test/framework/easyblock.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,7 +1582,8 @@ def test_download_instructions(self):
15821582
self.assertErrorRegex(EasyBuildError, error_pattern, eb.fetch_step)
15831583
stderr = self.get_stderr().strip()
15841584
self.mock_stderr(False)
1585-
self.assertIn("Download instructions:\n\nManual download from example.com required", stderr)
1585+
self.assertIn("Download instructions:\n\n Manual download from example.com required", stderr)
1586+
self.assertIn("Make the files available in the active source path", stderr)
15861587

15871588
# create dummy source file
15881589
write_file(os.path.join(os.path.dirname(self.eb_file), 'software_with_missing_sources-0.0.tar.gz'), '')
@@ -1596,7 +1597,8 @@ def test_download_instructions(self):
15961597
stderr = self.get_stderr().strip()
15971598
self.mock_stderr(False)
15981599
self.mock_stdout(False)
1599-
self.assertIn("Download instructions:\n\nManual download from example.com required", stderr)
1600+
self.assertIn("Download instructions:\n\n Manual download from example.com required", stderr)
1601+
self.assertIn("Make the files available in the active source path", stderr)
16001602

16011603
# wipe top-level download instructions, try again
16021604
self.contents = self.contents.replace(download_instructions, '')
@@ -1625,7 +1627,8 @@ def test_download_instructions(self):
16251627
stderr = self.get_stderr().strip()
16261628
self.mock_stderr(False)
16271629
self.mock_stdout(False)
1628-
self.assertIn("Download instructions:\n\nExtension sources must be downloaded via example.com", stderr)
1630+
self.assertIn("Download instructions:\n\n Extension sources must be downloaded via example.com", stderr)
1631+
self.assertIn("Make the files available in the active source path", stderr)
16291632

16301633
# download instructions should also be printed if 'source_tmpl' is used to specify extension sources
16311634
self.contents = self.contents.replace(sources, "'source_tmpl': SOURCE_TAR_GZ,")
@@ -1638,7 +1641,8 @@ def test_download_instructions(self):
16381641
stderr = self.get_stderr().strip()
16391642
self.mock_stderr(False)
16401643
self.mock_stdout(False)
1641-
self.assertIn("Download instructions:\n\nExtension sources must be downloaded via example.com", stderr)
1644+
self.assertIn("Download instructions:\n\n Extension sources must be downloaded via example.com", stderr)
1645+
self.assertIn("Make the files available in the active source path", stderr)
16421646

16431647
# create dummy source file for extension
16441648
write_file(os.path.join(os.path.dirname(self.eb_file), 'ext_with_missing_sources-0.0.tar.gz'), '')

test/framework/easyconfig.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4438,31 +4438,39 @@ def test_cuda_compute_capabilities(self):
44384438
description = 'test'
44394439
toolchain = SYSTEM
44404440
cuda_compute_capabilities = ['5.1', '7.0', '7.1']
4441-
installopts = '%(cuda_compute_capabilities)s'
4442-
preinstallopts = '%(cuda_cc_space_sep)s'
4443-
prebuildopts = '%(cuda_cc_semicolon_sep)s'
4444-
configopts = 'comma="%(cuda_sm_comma_sep)s" space="%(cuda_sm_space_sep)s"'
44454441
preconfigopts = 'CUDAARCHS="%(cuda_cc_cmake)s"'
4442+
configopts = 'comma="%(cuda_sm_comma_sep)s" space="%(cuda_sm_space_sep)s"'
4443+
prebuildopts = '%(cuda_cc_semicolon_sep)s'
4444+
buildopts = ('comma="%(cuda_int_comma_sep)s" space="%(cuda_int_space_sep)s" '
4445+
'semi="%(cuda_int_semicolon_sep)s"')
4446+
preinstallopts = '%(cuda_cc_space_sep)s'
4447+
installopts = '%(cuda_compute_capabilities)s'
44464448
""")
44474449
self.prep()
44484450

44494451
ec = EasyConfig(self.eb_file)
4450-
self.assertEqual(ec['installopts'], '5.1,7.0,7.1')
4451-
self.assertEqual(ec['preinstallopts'], '5.1 7.0 7.1')
4452-
self.assertEqual(ec['prebuildopts'], '5.1;7.0;7.1')
4452+
self.assertEqual(ec['preconfigopts'], 'CUDAARCHS="51;70;71"')
44534453
self.assertEqual(ec['configopts'], 'comma="sm_51,sm_70,sm_71" '
44544454
'space="sm_51 sm_70 sm_71"')
4455-
self.assertEqual(ec['preconfigopts'], 'CUDAARCHS="51;70;71"')
4455+
self.assertEqual(ec['prebuildopts'], '5.1;7.0;7.1')
4456+
self.assertEqual(ec['buildopts'], 'comma="51,70,71" '
4457+
'space="51 70 71" '
4458+
'semi="51;70;71"')
4459+
self.assertEqual(ec['preinstallopts'], '5.1 7.0 7.1')
4460+
self.assertEqual(ec['installopts'], '5.1,7.0,7.1')
44564461

44574462
# build options overwrite it
44584463
init_config(build_options={'cuda_compute_capabilities': ['4.2', '6.3']})
44594464
ec = EasyConfig(self.eb_file)
4460-
self.assertEqual(ec['installopts'], '4.2,6.3')
4461-
self.assertEqual(ec['preinstallopts'], '4.2 6.3')
4462-
self.assertEqual(ec['prebuildopts'], '4.2;6.3')
4465+
self.assertEqual(ec['preconfigopts'], 'CUDAARCHS="42;63"')
44634466
self.assertEqual(ec['configopts'], 'comma="sm_42,sm_63" '
44644467
'space="sm_42 sm_63"')
4465-
self.assertEqual(ec['preconfigopts'], 'CUDAARCHS="42;63"')
4468+
self.assertEqual(ec['buildopts'], 'comma="42,63" '
4469+
'space="42 63" '
4470+
'semi="42;63"')
4471+
self.assertEqual(ec['prebuildopts'], '4.2;6.3')
4472+
self.assertEqual(ec['preinstallopts'], '4.2 6.3')
4473+
self.assertEqual(ec['installopts'], '4.2,6.3')
44664474

44674475
def test_det_copy_ec_specs(self):
44684476
"""Test det_copy_ec_specs function."""
@@ -4725,6 +4733,9 @@ def test_get_cuda_cc_template_value(self):
47254733
'cuda_compute_capabilities': '6.5,7.0',
47264734
'cuda_cc_space_sep': '6.5 7.0',
47274735
'cuda_cc_semicolon_sep': '6.5;7.0',
4736+
'cuda_int_comma_sep': '65,70',
4737+
'cuda_int_space_sep': '65 70',
4738+
'cuda_int_semicolon_sep': '65;70',
47284739
'cuda_sm_comma_sep': 'sm_65,sm_70',
47294740
'cuda_sm_space_sep': 'sm_65 sm_70',
47304741
}

test/framework/run.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import os
3636
import re
3737
import signal
38+
import string
3839
import stat
3940
import subprocess
4041
import sys
@@ -52,7 +53,7 @@
5253
from easybuild.tools.config import update_build_option
5354
from easybuild.tools.filetools import adjust_permissions, change_dir, mkdir, read_file, write_file
5455
from easybuild.tools.run import RunShellCmdResult, RunShellCmdError, check_async_cmd, check_log_for_errors
55-
from easybuild.tools.run import complete_cmd, get_output_from_process, parse_log_for_error
56+
from easybuild.tools.run import complete_cmd, fileprefix_from_cmd, get_output_from_process, parse_log_for_error
5657
from easybuild.tools.run import run_cmd, run_cmd_qa, run_shell_cmd, subprocess_terminate
5758
from easybuild.tools.config import ERROR, IGNORE, WARN
5859

@@ -194,6 +195,26 @@ def test_run_shell_cmd_basic(self):
194195
self.assertTrue(isinstance(res.output, str))
195196
self.assertTrue(res.work_dir and isinstance(res.work_dir, str))
196197

198+
def test_fileprefix_from_cmd(self):
199+
"""test simplifications from fileprefix_from_cmd."""
200+
cmds = {
201+
'abd123': 'abd123',
202+
'ab"a': 'aba',
203+
'a{:$:S@"a': 'aSa',
204+
'cmd-with-dash': 'cmd-with-dash',
205+
'cmd_with_underscore': 'cmd_with_underscore',
206+
}
207+
for cmd, expected_simplification in cmds.items():
208+
self.assertEqual(fileprefix_from_cmd(cmd), expected_simplification)
209+
210+
cmds = {
211+
'abd123': 'abd',
212+
'ab"a': 'aba',
213+
'0a{:$:2@"a': 'aa',
214+
}
215+
for cmd, expected_simplification in cmds.items():
216+
self.assertEqual(fileprefix_from_cmd(cmd, allowed_chars=string.ascii_letters), expected_simplification)
217+
197218
def test_run_cmd_log(self):
198219
"""Test logging of executed commands."""
199220
fd, logfile = tempfile.mkstemp(suffix='.log', prefix='eb-test-')

0 commit comments

Comments
 (0)