Skip to content

Commit d9dec7f

Browse files
authored
Merge pull request #3783 from Flamefire/20250617135218_new_pr_bundle
enhance `Bundle` easyblock to show status of component installation
2 parents eb919df + d506e16 commit d9dec7f

File tree

1 file changed

+48
-21
lines changed

1 file changed

+48
-21
lines changed

easybuild/easyblocks/generic/bundle.py

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"""
3636
import copy
3737
import os
38+
from datetime import datetime
3839

3940
import easybuild.tools.environment as env
4041
from easybuild.framework.easyblock import EasyBlock
@@ -45,7 +46,17 @@
4546
from easybuild.tools.config import build_option
4647
from easybuild.tools.hooks import TEST_STEP
4748
from easybuild.tools.modules import get_software_root, get_software_version
48-
from easybuild.tools.utilities import nub
49+
from easybuild.tools.utilities import nub, time2str
50+
51+
52+
# Description and step name run during component installation
53+
COMPONENT_INSTALL_STEPS = [
54+
('patching', 'patch'),
55+
('configuring', 'configure'),
56+
('building', 'build'),
57+
('testing', 'test'),
58+
('installing', 'install'),
59+
]
4960

5061

5162
class Bundle(EasyBlock):
@@ -265,14 +276,39 @@ def build_step(self):
265276
"""Do nothing."""
266277
pass
267278

279+
def _install_component(self, comp):
280+
"""Run the installation steps for a single component"""
281+
# run relevant steps
282+
for descr, step_name in COMPONENT_INSTALL_STEPS:
283+
if step_name in comp.cfg['skipsteps']:
284+
comp.log.info("Skipping '%s' step for component %s v%s", step_name, comp.name, comp.version)
285+
elif build_option('skip_test_step') and step_name == TEST_STEP:
286+
comp.log.info("Skipping %s step for component %s v%s, as requested via skip-test-step", step_name,
287+
comp.name, comp.version)
288+
else:
289+
msg = f' {descr} component {comp.name}...'
290+
if self.dry_run:
291+
self.dry_run_msg("%s [DRY RUN]\n", msg)
292+
else:
293+
print_msg(msg, log=self.log, silent=self.silent)
294+
start_time = datetime.now()
295+
try:
296+
comp.run_step(step_name, [lambda x: getattr(x, '%s_step' % step_name)])
297+
finally:
298+
if not self.dry_run:
299+
step_duration = datetime.now() - start_time
300+
if step_duration.total_seconds() >= 1:
301+
print_msg(" ... (took %s)", time2str(step_duration), log=self.log, silent=self.silent)
302+
elif self.logdebug or build_option('trace'):
303+
print_msg(" ... (took < 1 sec)", log=self.log, silent=self.silent)
304+
268305
def install_step(self):
269306
"""Install components, if specified."""
270307
comp_cnt = len(self.cfg['components'])
271308
for idx, (cfg, comp) in enumerate(self.comp_instances):
272-
273309
print_msg("installing bundle component %s v%s (%d/%d)..." %
274-
(cfg['name'], cfg['version'], idx + 1, comp_cnt))
275-
self.log.info("Installing component %s v%s using easyblock %s", cfg['name'], cfg['version'], cfg.easyblock)
310+
(comp.name, comp.version, idx + 1, comp_cnt))
311+
self.log.info("Installing component %s v%s using easyblock %s", comp.name, comp.version, cfg.easyblock)
276312

277313
# correct build/install dirs
278314
comp.builddir = self.builddir
@@ -317,18 +353,10 @@ def install_step(self):
317353
comp.src[-1]['finalpath'] = comp.cfg['start_dir']
318354

319355
# check if sanity checks are enabled for the component
320-
if self.cfg['sanity_check_all_components'] or comp.cfg['name'] in self.cfg['sanity_check_components']:
356+
if self.cfg['sanity_check_all_components'] or comp.name in self.cfg['sanity_check_components']:
321357
self.comp_cfgs_sanity_check.append(comp)
322358

323-
# run relevant steps
324-
for step_name in ['patch', 'configure', 'build', 'test', 'install']:
325-
if step_name in cfg['skipsteps']:
326-
comp.log.info("Skipping '%s' step for component %s v%s", step_name, cfg['name'], cfg['version'])
327-
elif build_option('skip_test_step') and step_name == TEST_STEP:
328-
comp.log.info("Skipping %s step for component %s v%s, as requested via skip-test-step", step_name,
329-
cfg['name'], cfg['version'])
330-
else:
331-
comp.run_step(step_name, [lambda x: getattr(x, '%s_step' % step_name)])
359+
self._install_component(comp)
332360

333361
if comp.make_module_req_guess.__qualname__ != 'EasyBlock.make_module_req_guess':
334362
depr_msg = f"Easyblock used to install component {comp.name} still uses make_module_req_guess"
@@ -381,13 +409,13 @@ def make_module_step(self, *args, **kwargs):
381409
as this is done in the generic EasyBlock while creating
382410
the module file already.
383411
"""
384-
for cfg, comp in self.comp_instances:
385-
self.log.info("Gathering module paths for component %s v%s", cfg['name'], cfg['version'])
412+
for _, comp in self.comp_instances:
413+
self.log.info("Gathering module paths for component %s v%s", comp.name, comp.version)
386414

387415
# take into account that easyblock used for component may not be migrated yet to module_load_environment
388416
if comp.make_module_req_guess.__qualname__ != 'EasyBlock.make_module_req_guess':
389417

390-
depr_msg = f"Easyblock used to install component {cfg['name']} still uses make_module_req_guess"
418+
depr_msg = f"Easyblock used to install component {comp.name} still uses make_module_req_guess"
391419
self.log.deprecated(depr_msg, '6.0')
392420

393421
reqs = comp.make_module_req_guess()
@@ -403,7 +431,7 @@ def make_module_step(self, *args, **kwargs):
403431
setattr(self.module_load_environment, key, value)
404432
except AttributeError:
405433
raise EasyBuildError("Cannot process module requirements of bundle component %s v%s",
406-
cfg['name'], cfg['version'])
434+
comp.name, comp.version)
407435
else:
408436
# Explicit call required as adding step to 'install_step' is not sufficient
409437
# for module-only build. Set fake arg to True, as module components should
@@ -445,8 +473,7 @@ def sanity_check_step(self, *args, **kwargs):
445473
# run sanity checks for specific components
446474
cnt = len(self.comp_cfgs_sanity_check)
447475
for idx, comp in enumerate(self.comp_cfgs_sanity_check):
448-
comp_name, comp_ver = comp.cfg['name'], comp.cfg['version']
449-
print_msg("sanity checking bundle component %s v%s (%i/%i)...", comp_name, comp_ver, idx + 1, cnt)
450-
self.log.info("Starting sanity check step for component %s v%s", comp_name, comp_ver)
476+
print_msg("sanity checking bundle component %s v%s (%i/%i)...", comp.name, comp.version, idx + 1, cnt)
477+
self.log.info("Starting sanity check step for component %s v%s", comp.name, comp.version)
451478

452479
comp.run_step('sanity_check', [lambda x: x.sanity_check_step])

0 commit comments

Comments
 (0)