Skip to content

Commit cb8b421

Browse files
authored
Merge pull request #4781 from Flamefire/disable-robot
Add support for `--disable-robot`
2 parents 0eb76dd + 3a29ef3 commit cb8b421

3 files changed

Lines changed: 31 additions & 11 deletions

File tree

easybuild/base/generaloption.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ class ExtOption(CompleterOption):
185185
- set default to None if no option passed,
186186
- set to default if option without value passed,
187187
- set to value if option with value passed
188+
- store_or_False: Same as store_or_None, but set to False instead of None
189+
- Additionally supports --disable-
188190
189191
Types:
190192
- strlist, strtuple : convert comma-separated string in a list resp. tuple of strings
@@ -196,14 +198,15 @@ class ExtOption(CompleterOption):
196198

197199
ENABLE = 'enable' # do nothing
198200
DISABLE = 'disable' # inverse action
201+
STORE_OR_FALSE = 'store_or_False'
199202

200203
EXTOPTION_EXTRA_OPTIONS = ('date', 'datetime', 'regex', 'add', 'add_first', 'add_flex',)
201-
EXTOPTION_STORE_OR = ('store_or_None', 'help') # callback type
204+
EXTOPTION_STORE_OR = ('store_or_None', STORE_OR_FALSE, 'help') # callback type
202205
EXTOPTION_LOG = ('store_debuglog', 'store_infolog', 'store_warninglog',)
203206
EXTOPTION_HELP = ('shorthelp', 'confighelp', 'help')
204207

205208
ACTIONS = Option.ACTIONS + EXTOPTION_EXTRA_OPTIONS + EXTOPTION_STORE_OR + EXTOPTION_LOG + EXTOPTION_HELP
206-
STORE_ACTIONS = Option.STORE_ACTIONS + EXTOPTION_EXTRA_OPTIONS + EXTOPTION_LOG + ('store_or_None',)
209+
STORE_ACTIONS = Option.STORE_ACTIONS + EXTOPTION_EXTRA_OPTIONS + EXTOPTION_LOG + ('store_or_None', STORE_OR_FALSE)
207210
TYPED_ACTIONS = Option.TYPED_ACTIONS + EXTOPTION_EXTRA_OPTIONS + EXTOPTION_STORE_OR
208211
ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + EXTOPTION_EXTRA_OPTIONS
209212

@@ -232,7 +235,9 @@ def store_or(option, opt_str, value, parser, *args, **kwargs): # pylint: disabl
232235
"""Callback for supporting options with optional values."""
233236
# see http://stackoverflow.com/questions/1229146/parsing-empty-options-in-python
234237
# ugly code, optparse is crap
235-
if parser.rargs and not parser.rargs[0].startswith('-'):
238+
if option.store_or == self.STORE_OR_FALSE and opt_str.startswith("--%s-" % self.DISABLE):
239+
val = False
240+
elif parser.rargs and not parser.rargs[0].startswith('-'):
236241
val = option.check_value(opt_str, parser.rargs.pop(0))
237242
else:
238243
val = kwargs.get('orig_default', None)
@@ -250,11 +255,7 @@ def store_or(option, opt_str, value, parser, *args, **kwargs): # pylint: disabl
250255
'orig_default': copy.deepcopy(self.default),
251256
}
252257
self.action = 'callback' # act as callback
253-
254-
if self.store_or in self.EXTOPTION_STORE_OR:
255-
self.default = None
256-
else:
257-
self.log.raiseException("_set_attrs: unknown store_or %s" % self.store_or, exception=ValueError)
258+
self.default = False if self.action == self.STORE_OR_FALSE else None
258259

259260
def process(self, opt, value, values, parser):
260261
"""Handle option-as-value issues before actually processing option."""
@@ -1219,6 +1220,8 @@ def add_group_parser(self, opt_dict, description, prefix=None, otherdefaults=Non
12191220
if action in self.parser.option_class.BOOLEAN_ACTIONS:
12201221
args.append("--%s-%s" % (self.parser.option_class.ENABLE, opt_name))
12211222
args.append("--%s-%s" % (self.parser.option_class.DISABLE, opt_name))
1223+
elif action == self.parser.option_class.STORE_OR_FALSE:
1224+
args.append("--%s-%s" % (self.parser.option_class.DISABLE, opt_name))
12221225

12231226
# force passed_kwargs as final nameds
12241227
nameds.update(passed_kwargs)

easybuild/tools/options.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def basic_options(self):
293293
'rebuild': ("Rebuild software, even if module already exists (don't skip OS dependencies checks)",
294294
None, 'store_true', False),
295295
'robot': ("Enable dependency resolution, optionally consider additional paths to search for easyconfigs",
296-
'pathlist', 'store_or_None', [], 'r', {'metavar': '[PATH[%sPATH]]' % os.pathsep}),
296+
'pathlist', 'store_or_False', [], 'r', {'metavar': '[PATH[%sPATH]]' % os.pathsep}),
297297
'robot-paths': ("Additional paths to consider by robot for easyconfigs (--robot paths get priority)",
298298
'pathlist', 'add_flex', self.default_robot_paths, {'metavar': 'PATH[%sPATH]' % os.pathsep}),
299299
'search-paths': ("Additional locations to consider in --search (next to --robot and --robot-paths paths)",
@@ -1327,7 +1327,9 @@ def _postprocess_config(self):
13271327
if self.options.pretend:
13281328
self.options.installpath = get_pretend_installpath()
13291329

1330-
if self.options.robot is not None:
1330+
if self.options.robot is False:
1331+
self.options.robot = None # Set to None as-if not specified
1332+
elif self.options.robot is not None:
13311333
# if a single path is specified to --robot/-r, it must be an existing directory;
13321334
# this is required since an argument to --robot is optional,
13331335
# which makes it susceptible to 'eating' the following argument/option;

test/framework/options.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3429,10 +3429,25 @@ def test_robot(self):
34293429
't/toy/toy-0.0-deps.eb',
34303430
'g/gzip/gzip-1.4-GCC-4.6.3.eb',
34313431
]
3432+
re_template = r'^\s\*\s\[[xF ]\]\s%s'
34323433
for ecfile in ecfiles:
3433-
ec_regex = re.compile(r'^\s\*\s\[[xF ]\]\s%s' % os.path.join(test_ecs_path, ecfile), re.M)
3434+
ec_regex = re.compile(re_template % os.path.join(test_ecs_path, ecfile), re.M)
34343435
self.assertRegex(outtxt, ec_regex)
34353436

3437+
# Check for disabling --robot
3438+
args.append('--disable-robot')
3439+
# Enabled on cmdline before and via option, but should be disabled
3440+
os.environ['EASYBUILD_ROBOT'] = self.test_prefix
3441+
with self.mocked_stdout_stderr():
3442+
outtxt = self.eb_main(args, raise_error=True)
3443+
for ecfile in ecfiles:
3444+
ec_regex = re.compile(re_template % os.path.join(test_ecs_path, ecfile), re.M)
3445+
# Only the EC passed would be build but not the dependencies
3446+
if os.path.basename(ecfile) == os.path.basename(eb_file):
3447+
self.assertRegex(outtxt, ec_regex)
3448+
else:
3449+
self.assertNotRegex(outtxt, ec_regex)
3450+
34363451
def test_robot_path_check(self):
34373452
"""Test path check for --robot"""
34383453
empty_file = os.path.join(self.test_prefix, 'empty')

0 commit comments

Comments
 (0)