Skip to content

Commit 1d18c7e

Browse files
committed
EasyBlock: Allow to pass logfile from other EasyBlock
In the case an EasyBlock creates another instance of an EasyBlock (for example when dealing with Bundles), each instance will create new log file, which may stay open and cause issues down the line. To prevent this, add an option to the EasyBlock constructor to pass a logfile from another EasyBlock. Signed-off-by: Jan André Reuter <[email protected]>
1 parent d700144 commit 1d18c7e

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

easybuild/framework/easyblock.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* Maxime Boissonneault (Compute Canada)
4141
* Davide Vanzo (Vanderbilt University)
4242
* Caspar van Leeuwen (SURF)
43+
* Jan Andre Reuter (Juelich Supercomputing Centre)
4344
"""
4445

4546
import copy
@@ -141,10 +142,11 @@ def extra_options(extra=None):
141142
#
142143
# INIT
143144
#
144-
def __init__(self, ec):
145+
def __init__(self, ec, logfile=None):
145146
"""
146147
Initialize the EasyBlock instance.
147148
:param ec: a parsed easyconfig file (EasyConfig instance)
149+
:param logfile: pass logfile from other EasyBlock. If not passed, create logfile (optional)
148150
"""
149151

150152
# keep track of original working directory, so we can go back there
@@ -214,7 +216,8 @@ def __init__(self, ec):
214216

215217
# logging
216218
self.log = None
217-
self.logfile = None
219+
self.logfile = logfile
220+
self.external_logfile = logfile is not None
218221
self.logdebug = build_option('debug')
219222
self.postmsg = '' # allow a post message to be set, which can be shown as last output
220223
self.current_step = None
@@ -303,11 +306,11 @@ def _init_log(self):
303306
if self.log is not None:
304307
return
305308

306-
self.logfile = get_log_filename(self.name, self.version, add_salt=True)
307-
fancylogger.logToFile(self.logfile, max_bytes=0)
309+
if self.logfile is None:
310+
self.logfile = get_log_filename(self.name, self.version, add_salt=True)
311+
fancylogger.logToFile(self.logfile, max_bytes=0)
308312

309313
self.log = fancylogger.getLogger(name=self.__class__.__name__, fname=False)
310-
311314
self.log.info(this_is_easybuild())
312315

313316
this_module = inspect.getmodule(self)
@@ -323,6 +326,9 @@ def close_log(self):
323326
"""
324327
Shutdown the logger.
325328
"""
329+
# only close log if we created a logfile
330+
if self.external_logfile:
331+
return
326332
self.log.info("Closing log for application name %s version %s" % (self.name, self.version))
327333
fancylogger.logToFile(self.logfile, enable=False)
328334

test/framework/easyblock.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
@author: Jens Timmerman (Ghent University)
2929
@author: Kenneth Hoste (Ghent University)
3030
@author: Maxime Boissonneault (Compute Canada)
31+
@author: Jan Andre Reuter (Juelich Supercomputing Centre)
3132
"""
3233
import os
3334
import re
@@ -2895,6 +2896,47 @@ def run_sanity_check_step(sanity_check_paths, enhance_sanity_check):
28952896
run_sanity_check_step({}, False)
28962897
run_sanity_check_step({}, True)
28972898

2899+
def test_create_easyblock_without_logfile(self):
2900+
"""
2901+
Test creating an EasyBlock without a logfile.
2902+
This represents scenarios found in Bundle and QuantumESPRESSO, where an EasyBlock is
2903+
created within another EasyBlock.
2904+
"""
2905+
self.contents = '\n'.join([
2906+
'easyblock = "ConfigureMake"',
2907+
'name = "pi"',
2908+
'version = "3.14"',
2909+
'homepage = "http://example.com"',
2910+
'description = "test easyconfig"',
2911+
'toolchain = SYSTEM',
2912+
])
2913+
self.writeEC()
2914+
# Ensure that the default case works as expected
2915+
eb = EasyBlock(EasyConfig(self.eb_file))
2916+
self.assertNotEqual(eb.log, None)
2917+
self.assertNotEqual(eb.logfile, None)
2918+
# Get reference to the actual log instance and ensure that it works
2919+
# This is NOT eb.log, which represents a separate logger with a separate name.
2920+
file_log = fancylogger.getLogger(name=None)
2921+
self.assertNotEqual(getattr(file_log, 'logtofile_%s' % eb.logfile), False)
2922+
2923+
# Now, create another EasyBlock by passing logfile from first EasyBlock.
2924+
eb_external_logfile = EasyBlock(EasyConfig(self.eb_file), logfile=eb.logfile)
2925+
self.assertNotEqual(eb_external_logfile.log, None)
2926+
self.assertTrue(eb_external_logfile.external_logfile)
2927+
self.assertEqual(eb_external_logfile.logfile, eb.logfile)
2928+
# Try to log something in it.
2929+
eb_external_logfile.log.info("Test message")
2930+
2931+
# Try to close EasyBlock with external logfile. This should not affect the logger.
2932+
eb_external_logfile.close_log()
2933+
self.assertNotEqual(getattr(file_log, 'logtofile_%s' % eb.logfile), False)
2934+
# Then close the log from creating EasyBlock. This should work as expected.
2935+
eb.close_log()
2936+
self.assertEqual(getattr(file_log, 'logtofile_%s' % eb.logfile), False)
2937+
2938+
os.remove(eb.logfile)
2939+
28982940

28992941
def suite():
29002942
""" return all the tests in this file """

0 commit comments

Comments
 (0)