Skip to content

Commit aca7d92

Browse files
authored
Merge pull request easybuilders#2638 from boegel/eb_as_library
flesh out setting up of configuration into dedicated 'set_up_configuration' function
2 parents 596c351 + 1c7e977 commit aca7d92

6 files changed

Lines changed: 250 additions & 104 deletions

File tree

easybuild/main.py

Lines changed: 8 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,17 @@
3939
import os
4040
import stat
4141
import sys
42-
import tempfile
4342
import traceback
4443

4544
# IMPORTANT this has to be the first easybuild import as it customises the logging
4645
# expect missing log output when this not the case!
47-
from easybuild.tools.build_log import EasyBuildError, init_logging, print_error, print_msg, print_warning, stop_logging
46+
from easybuild.tools.build_log import EasyBuildError, print_error, print_msg, stop_logging
4847

49-
import easybuild.tools.config as config
50-
import easybuild.tools.options as eboptions
51-
from easybuild.framework.easyblock import EasyBlock, build_and_install_one, inject_checksums
48+
from easybuild.framework.easyblock import build_and_install_one, inject_checksums
5249
from easybuild.framework.easyconfig import EASYCONFIGS_PKG_SUBDIR
5350
from easybuild.framework.easyconfig.easyconfig import verify_easyconfig_filename
5451
from easybuild.framework.easyconfig.style import cmdline_easyconfigs_style_check
55-
from easybuild.framework.easyconfig.tools import alt_easyconfig_paths, categorize_files_by_type, dep_graph
52+
from easybuild.framework.easyconfig.tools import categorize_files_by_type, dep_graph
5653
from easybuild.framework.easyconfig.tools import det_easyconfig_paths, dump_env_script, get_paths_for
5754
from easybuild.framework.easyconfig.tools import parse_easyconfigs, review_pr, run_contrib_checks, skip_available
5855
from easybuild.framework.easyconfig.tweak import obtain_ec_for, tweak
@@ -64,27 +61,16 @@
6461
from easybuild.tools.github import new_pr, merge_pr, update_pr
6562
from easybuild.tools.hooks import START, END, load_hooks, run_hook
6663
from easybuild.tools.modules import modules_tool
67-
from easybuild.tools.options import parse_external_modules_metadata, process_software_build_specs, use_color
68-
from easybuild.tools.robot import check_conflicts, det_robot_path, dry_run, resolve_dependencies, search_easyconfigs
64+
from easybuild.tools.options import set_up_configuration, use_color
65+
from easybuild.tools.robot import check_conflicts, dry_run, resolve_dependencies, search_easyconfigs
6966
from easybuild.tools.package.utilities import check_pkg_support
7067
from easybuild.tools.parallelbuild import submit_jobs
7168
from easybuild.tools.repository.repository import init_repository
7269
from easybuild.tools.testing import create_test_report, overall_test_report, regtest, session_state
73-
from easybuild.tools.version import this_is_easybuild
7470

7571
_log = None
7672

7773

78-
def log_start(eb_command_line, eb_tmpdir):
79-
"""Log startup info."""
80-
_log.info(this_is_easybuild())
81-
82-
# log used command line
83-
_log.info("Command line: %s" % (' '.join(eb_command_line)))
84-
85-
_log.info("Using %s as temporary directory" % eb_tmpdir)
86-
87-
8874
def find_easyconfigs_by_specs(build_specs, robot_path, try_to_generate, testing=False):
8975
"""Find easyconfigs by build specifications."""
9076
generated, ec_file = obtain_ec_for(build_specs, robot_path, None)
@@ -187,23 +173,6 @@ def run_contrib_style_checks(ecs, check_contrib, check_style):
187173
return check_contrib or check_style
188174

189175

190-
def check_root_usage(allow_use_as_root=False):
191-
"""
192-
Check whether we are running as root, and act accordingly
193-
194-
:param allow_use_as_root: allow use of EasyBuild as root (but do print a warning when doing so)
195-
"""
196-
if os.getuid() == 0:
197-
if allow_use_as_root:
198-
msg = "Using EasyBuild as root is NOT recommended, please proceed with care!\n"
199-
msg += "(this is only allowed because EasyBuild was configured with "
200-
msg += "--allow-use-as-root-and-accept-consequences)"
201-
print_warning(msg)
202-
else:
203-
raise EasyBuildError("You seem to be running EasyBuild with root privileges which is not wise, "
204-
"so let's end this here.")
205-
206-
207176
def clean_exit(logfile, tmpdir, testing, silent=False):
208177
"""Small utility function to perform a clean exit."""
209178
cleanup(logfile, tmpdir, testing, silent=silent)
@@ -221,63 +190,11 @@ def main(args=None, logfile=None, do_build=None, testing=False, modtool=None):
221190
# purposely session state very early, to avoid modules loaded by EasyBuild meddling in
222191
init_session_state = session_state()
223192

224-
# initialise options
225-
eb_go = eboptions.parse_options(args=args)
226-
options = eb_go.options
227-
orig_paths = eb_go.args
228-
229-
# set umask (as early as possible)
230-
if options.umask is not None:
231-
new_umask = int(options.umask, 8)
232-
old_umask = os.umask(new_umask)
193+
eb_go, cfg_settings = set_up_configuration(args=args, logfile=logfile, testing=testing)
194+
options, orig_paths = eb_go.options, eb_go.args
233195

234-
# set by option parsers via set_tmpdir
235-
eb_tmpdir = tempfile.gettempdir()
236-
237-
search_query = options.search or options.search_filename or options.search_short
238-
239-
# initialise logging for main
240196
global _log
241-
_log, logfile = init_logging(logfile, logtostdout=options.logtostdout,
242-
silent=(testing or options.terse or search_query), colorize=options.color)
243-
244-
# disallow running EasyBuild as root (by default)
245-
check_root_usage(allow_use_as_root=options.allow_use_as_root_and_accept_consequences)
246-
247-
# log startup info
248-
eb_cmd_line = eb_go.generate_cmd_line() + eb_go.args
249-
log_start(eb_cmd_line, eb_tmpdir)
250-
251-
if options.umask is not None:
252-
_log.info("umask set to '%s' (used to be '%s')" % (oct(new_umask), oct(old_umask)))
253-
254-
# process software build specifications (if any), i.e.
255-
# software name/version, toolchain name/version, extra patches, ...
256-
(try_to_generate, build_specs) = process_software_build_specs(options)
257-
258-
# determine robot path
259-
# --try-X, --dep-graph, --search use robot path for searching, so enable it with path of installed easyconfigs
260-
tweaked_ecs = try_to_generate and build_specs
261-
tweaked_ecs_paths, pr_path = alt_easyconfig_paths(eb_tmpdir, tweaked_ecs=tweaked_ecs, from_pr=options.from_pr)
262-
auto_robot = try_to_generate or options.check_conflicts or options.dep_graph or search_query
263-
robot_path = det_robot_path(options.robot_paths, tweaked_ecs_paths, pr_path, auto_robot=auto_robot)
264-
_log.debug("Full robot path: %s" % robot_path)
265-
266-
# configure & initialize build options
267-
config_options_dict = eb_go.get_options_by_section('config')
268-
build_options = {
269-
'build_specs': build_specs,
270-
'command_line': eb_cmd_line,
271-
'external_modules_metadata': parse_external_modules_metadata(options.external_modules_metadata),
272-
'pr_path': pr_path,
273-
'robot_path': robot_path,
274-
'silent': testing,
275-
'try_to_generate': try_to_generate,
276-
'valid_stops': [x[0] for x in EasyBlock.get_steps()],
277-
}
278-
# initialise the EasyBuild configuration & build options
279-
config.init(options, config_options_dict)
280-
config.init_build_options(build_options=build_options, cmdline_options=options)
197+
(build_specs, _log, logfile, robot_path, search_query, eb_tmpdir, try_to_generate, tweaked_ecs_paths) = cfg_settings
281198

282199
# load hook implementations (if any)
283200
hooks = load_hooks(options.hooks)

easybuild/tools/build_log.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
from vsc.utils import fancylogger
4242
from vsc.utils.exceptions import LoggedException
4343

44-
from easybuild.tools.version import VERSION
44+
from easybuild.tools.version import VERSION, this_is_easybuild
4545

4646

4747
# EasyBuild message prefix
@@ -204,6 +204,16 @@ def init_logging(logfile, logtostdout=False, silent=False, colorize=fancylogger.
204204
return log, logfile
205205

206206

207+
def log_start(log, eb_command_line, eb_tmpdir):
208+
"""Log startup info."""
209+
log.info(this_is_easybuild())
210+
211+
# log used command line
212+
log.info("Command line: %s", ' '.join(eb_command_line))
213+
214+
log.info("Using %s as temporary directory", eb_tmpdir)
215+
216+
207217
def stop_logging(logfile, logtostdout=False):
208218
"""Stop logging."""
209219
if logtostdout:
@@ -212,13 +222,6 @@ def stop_logging(logfile, logtostdout=False):
212222
fancylogger.logToFile(logfile, enable=False)
213223

214224

215-
def get_log(name=None):
216-
"""
217-
(NO LONGER SUPPORTED!) Generate logger object
218-
"""
219-
log.nosupport("Use of get_log function", '2.0')
220-
221-
222225
def print_msg(msg, log=None, silent=False, prefix=True, newline=True, stderr=False):
223226
"""
224227
Print a message.

easybuild/tools/config.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,13 +439,17 @@ def init_build_options(build_options=None, cmdline_options=None):
439439

440440
def build_option(key, **kwargs):
441441
"""Obtain value specified build option."""
442+
442443
build_options = BuildOptions()
443444
if key in build_options:
444445
return build_options[key]
445446
elif 'default' in kwargs:
446447
return kwargs['default']
447448
else:
448-
raise EasyBuildError("Undefined build option: %s", key)
449+
error_msg = "Undefined build option: '%s'. " % key
450+
error_msg += "Make sure you have set up the EasyBuild configuration using set_up_configuration() "
451+
error_msg += "(from easybuild.tools.options) in case you're not using EasyBuild via the 'eb' CLI."
452+
raise EasyBuildError(error_msg)
449453

450454

451455
def build_path():

easybuild/tools/options.py

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,18 @@
5353
from easybuild.framework.easyconfig import EASYCONFIGS_PKG_SUBDIR
5454
from easybuild.framework.easyconfig.easyconfig import HAVE_AUTOPEP8
5555
from easybuild.framework.easyconfig.format.pyheaderconfigobj import build_easyconfig_constants_dict
56-
from easybuild.framework.easyconfig.tools import get_paths_for
56+
from easybuild.framework.easyconfig.tools import alt_easyconfig_paths, get_paths_for
5757
from easybuild.tools import build_log, run # build_log should always stay there, to ensure EasyBuildLog
58-
from easybuild.tools.build_log import DEVEL_LOG_LEVEL, EasyBuildError, raise_easybuilderror
58+
from easybuild.tools.build_log import DEVEL_LOG_LEVEL, EasyBuildError
59+
from easybuild.tools.build_log import init_logging, log_start, print_warning, raise_easybuilderror
5960
from easybuild.tools.config import CONT_IMAGE_FORMATS, CONT_TYPES, DEFAULT_CONT_TYPE
6061
from easybuild.tools.config import DEFAULT_ALLOW_LOADED_MODULES, DEFAULT_FORCE_DOWNLOAD, DEFAULT_JOB_BACKEND
6162
from easybuild.tools.config import DEFAULT_LOGFILE_FORMAT, DEFAULT_MAX_FAIL_RATIO_PERMS, DEFAULT_MNS
6263
from easybuild.tools.config import DEFAULT_MODULE_SYNTAX, DEFAULT_MODULES_TOOL, DEFAULT_MODULECLASSES
6364
from easybuild.tools.config import DEFAULT_PATH_SUBDIRS, DEFAULT_PKG_RELEASE, DEFAULT_PKG_TOOL, DEFAULT_PKG_TYPE
6465
from easybuild.tools.config import DEFAULT_PNS, DEFAULT_PREFIX, DEFAULT_REPOSITORY, EBROOT_ENV_VAR_ACTIONS
6566
from easybuild.tools.config import ERROR, IGNORE, FORCE_DOWNLOAD_CHOICES, LOADED_MODULES_ACTIONS, WARN
66-
from easybuild.tools.config import get_pretend_installpath, mk_full_default_path
67+
from easybuild.tools.config import get_pretend_installpath, init, init_build_options, mk_full_default_path
6768
from easybuild.tools.configobj import ConfigObj, ConfigObjError
6869
from easybuild.tools.docs import FORMAT_TXT, FORMAT_RST
6970
from easybuild.tools.docs import avail_cfgfile_constants, avail_easyconfig_constants, avail_easyconfig_licenses
@@ -82,12 +83,14 @@
8283
from easybuild.tools.module_naming_scheme.utilities import avail_module_naming_schemes
8384
from easybuild.tools.modules import Lmod
8485
from easybuild.tools.ordereddict import OrderedDict
86+
from easybuild.tools.robot import det_robot_path
8587
from easybuild.tools.run import run_cmd
8688
from easybuild.tools.package.utilities import avail_package_naming_schemes
8789
from easybuild.tools.toolchain.compiler import DEFAULT_OPT_LEVEL, OPTARCH_MAP_CHAR, OPTARCH_SEP, Compiler
8890
from easybuild.tools.repository.repository import avail_repositories
8991
from easybuild.tools.version import this_is_easybuild
9092

93+
9194
try:
9295
from humanfriendly.terminal import terminal_supports_colors
9396
except ImportError:
@@ -1151,6 +1154,94 @@ def parse_options(args=None, with_include=True):
11511154
return eb_go
11521155

11531156

1157+
def check_root_usage(allow_use_as_root=False):
1158+
"""
1159+
Check whether we are running as root, and act accordingly
1160+
1161+
:param allow_use_as_root: allow use of EasyBuild as root (but do print a warning when doing so)
1162+
"""
1163+
if os.getuid() == 0:
1164+
if allow_use_as_root:
1165+
msg = "Using EasyBuild as root is NOT recommended, please proceed with care!\n"
1166+
msg += "(this is only allowed because EasyBuild was configured with "
1167+
msg += "--allow-use-as-root-and-accept-consequences)"
1168+
print_warning(msg)
1169+
else:
1170+
raise EasyBuildError("You seem to be running EasyBuild with root privileges which is not wise, "
1171+
"so let's end this here.")
1172+
1173+
1174+
def set_up_configuration(args=None, logfile=None, testing=False, silent=False):
1175+
"""
1176+
Set up EasyBuild configuration, by parsing configuration settings & initialising build options.
1177+
1178+
:param args: command line arguments to take into account when parsing the EasyBuild configuration settings
1179+
:param logfile: log file to use
1180+
:param testing: enable testing mode
1181+
:param silent: stay silent (no printing)
1182+
"""
1183+
1184+
# parse EasyBuild configuration settings
1185+
eb_go = parse_options(args=args)
1186+
options = eb_go.options
1187+
1188+
# tmpdir is set by option parser via set_tmpdir function
1189+
tmpdir = tempfile.gettempdir()
1190+
1191+
# set umask (as early as possible)
1192+
if options.umask is not None:
1193+
new_umask = int(options.umask, 8)
1194+
old_umask = os.umask(new_umask)
1195+
1196+
search_query = options.search or options.search_filename or options.search_short
1197+
1198+
# initialise logging for main
1199+
log, logfile = init_logging(logfile, logtostdout=options.logtostdout,
1200+
silent=(testing or options.terse or search_query or silent),
1201+
colorize=options.color)
1202+
1203+
# log startup info (must be done after setting up logger)
1204+
eb_cmd_line = eb_go.generate_cmd_line() + eb_go.args
1205+
log_start(log, eb_cmd_line, tmpdir)
1206+
1207+
# can't log umask setting before logger is set up...
1208+
if options.umask is not None:
1209+
log.info("umask set to '%s' (used to be '%s')", oct(new_umask), oct(old_umask))
1210+
1211+
# disallow running EasyBuild as root (by default)
1212+
check_root_usage(allow_use_as_root=options.allow_use_as_root_and_accept_consequences)
1213+
1214+
# process software build specifications (if any), i.e.
1215+
# software name/version, toolchain name/version, extra patches, ...
1216+
(try_to_generate, build_specs) = process_software_build_specs(options)
1217+
1218+
# determine robot path
1219+
# --try-X, --dep-graph, --search use robot path for searching, so enable it with path of installed easyconfigs
1220+
tweaked_ecs = try_to_generate and build_specs
1221+
tweaked_ecs_paths, pr_path = alt_easyconfig_paths(tmpdir, tweaked_ecs=tweaked_ecs, from_pr=options.from_pr)
1222+
auto_robot = try_to_generate or options.check_conflicts or options.dep_graph or search_query
1223+
robot_path = det_robot_path(options.robot_paths, tweaked_ecs_paths, pr_path, auto_robot=auto_robot)
1224+
log.debug("Full robot path: %s" % robot_path)
1225+
1226+
# configure & initialize build options
1227+
config_options_dict = eb_go.get_options_by_section('config')
1228+
build_options = {
1229+
'build_specs': build_specs,
1230+
'command_line': eb_cmd_line,
1231+
'external_modules_metadata': parse_external_modules_metadata(options.external_modules_metadata),
1232+
'pr_path': pr_path,
1233+
'robot_path': robot_path,
1234+
'silent': testing,
1235+
'try_to_generate': try_to_generate,
1236+
'valid_stops': [x[0] for x in EasyBlock.get_steps()],
1237+
}
1238+
# initialise the EasyBuild configuration & build options
1239+
init(options, config_options_dict)
1240+
init_build_options(build_options=build_options, cmdline_options=options)
1241+
1242+
return eb_go, (build_specs, log, logfile, robot_path, search_query, tmpdir, try_to_generate, tweaked_ecs_paths)
1243+
1244+
11541245
def process_software_build_specs(options):
11551246
"""
11561247
Create a dictionary with specified software build options.

0 commit comments

Comments
 (0)