Skip to content

Commit fd59db9

Browse files
author
Vasileios Karakasis
authored
Merge pull request #2392 from ekouts/bugfix/var_options_type
[bugfix] Automatically convert numeric configuration parameters when set from the command line or the environment
2 parents b04eae5 + c527277 commit fd59db9

File tree

6 files changed

+38
-36
lines changed

6 files changed

+38
-36
lines changed

reframe/core/pipeline.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,8 +1518,7 @@ def _clone_to_stagedir(self, url):
15181518
self.logger.debug(f'Cloning URL {url} into stage directory')
15191519
osext.git_clone(
15201520
self.sourcesdir, self._stagedir,
1521-
# FIXME: cast to float explicitly due to GH #2246
1522-
timeout=float(rt.runtime().get_option('general/0/git_timeout'))
1521+
timeout=rt.runtime().get_option('general/0/git_timeout')
15231522
)
15241523

15251524
@final

reframe/frontend/argparse.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def __getattr__(self, name):
8282
if name not in self.__option_map:
8383
return ret
8484

85-
envvar, _, action = self.__option_map[name]
85+
envvar, _, action, arg_type = self.__option_map[name]
8686
if ret is None and envvar is not None:
8787
# Try the environment variable
8888
envvar, *delim = envvar.split(maxsplit=2)
@@ -99,6 +99,14 @@ def __getattr__(self, name):
9999
raise ValueError(
100100
f'environment variable {envvar!r} not a boolean'
101101
) from None
102+
elif action == 'store' and arg_type != str:
103+
try:
104+
ret = arg_type(ret)
105+
except ValueError as err:
106+
raise ValueError(
107+
f'cannot convert environment variable {envvar!r} '
108+
f'to {arg_type.__name__!r}'
109+
) from err
102110

103111
return ret
104112

@@ -107,7 +115,7 @@ def update_config(self, site_config):
107115
namespace'''
108116
errors = []
109117
for option, spec in self.__option_map.items():
110-
_, confvar, action = spec
118+
confvar, action = spec[1:3]
111119
if action == 'version' or confvar is None:
112120
continue
113121

@@ -174,7 +182,8 @@ def add_argument(self, *flags, **kwargs):
174182
self._option_map[opt_name] = (
175183
kwargs.get('envvar', None),
176184
kwargs.get('configvar', None),
177-
kwargs.get('action', 'store')
185+
kwargs.get('action', 'store'),
186+
kwargs.get('type', str)
178187
)
179188
# Remove envvar and configvar keyword arguments and force dest
180189
# argument, even if we guessed it, in order to guard against changes

reframe/frontend/cli.py

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -391,11 +391,11 @@ def main():
391391
run_options.add_argument(
392392
'--max-retries', metavar='NUM', action='store', default=0,
393393
help='Set the maximum number of times a failed regression test '
394-
'may be retried (default: 0)'
394+
'may be retried (default: 0)', type=int
395395
)
396396
run_options.add_argument(
397397
'--maxfail', metavar='NUM', action='store', default=sys.maxsize,
398-
help='Exit after first NUM failures'
398+
help='Exit after first NUM failures', type=int
399399
)
400400
run_options.add_argument(
401401
'--mode', action='store', help='Execution mode to use'
@@ -527,8 +527,10 @@ def main():
527527
dest='git_timeout',
528528
envvar='RFM_GIT_TIMEOUT',
529529
configvar='general/git_timeout',
530+
action='store',
530531
help=('Timeout in seconds when checking if the url is a '
531-
'valid repository.')
532+
'valid repository.'),
533+
type=float
532534
)
533535
argparser.add_argument(
534536
dest='graylog_server',
@@ -568,7 +570,8 @@ def main():
568570
envvar='RFM_PIPELINE_TIMEOUT',
569571
configvar='general/pipeline_timeout',
570572
action='store',
571-
help='Timeout for advancing the pipeline'
573+
help='Timeout for advancing the pipeline',
574+
type=float
572575
)
573576
argparser.add_argument(
574577
dest='remote_detect',
@@ -1172,26 +1175,14 @@ def module_unuse(*paths):
11721175
parsed_job_options.append(f'--{optstr} {valstr}')
11731176

11741177
exec_policy.sched_options = parsed_job_options
1175-
try:
1176-
max_retries = int(options.max_retries)
1177-
except ValueError:
1178-
raise errors.ConfigError(
1179-
f'--max-retries is not a valid integer: {max_retries}'
1180-
) from None
1181-
1182-
try:
1183-
max_failures = int(options.maxfail)
1184-
if max_failures < 0:
1185-
raise errors.ConfigError(
1186-
f'--maxfail should be a non-negative integer: '
1187-
f'{options.maxfail!r}'
1188-
)
1189-
except ValueError:
1178+
if options.maxfail < 0:
11901179
raise errors.ConfigError(
1191-
f'--maxfail is not a valid integer: {options.maxfail!r}'
1192-
) from None
1180+
f'--maxfail should be a non-negative integer: '
1181+
f'{options.maxfail!r}'
1182+
)
11931183

1194-
runner = Runner(exec_policy, printer, max_retries, max_failures)
1184+
runner = Runner(exec_policy, printer, options.max_retries,
1185+
options.maxfail)
11951186
try:
11961187
time_start = time.time()
11971188
session_info['time_start'] = time.strftime(

reframe/frontend/executors/policies.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,6 @@ def exit(self):
339339
'general/0/pipeline_timeout'
340340
)
341341

342-
# FIXME: Always convert due to #GH 2246
343-
if timeout is not None:
344-
timeout = float(timeout)
345-
346342
self._advance_all(self._current_tasks, timeout)
347343
if self._pipeline_statistics:
348344
num_retired = len(self._retired_tasks)

unittests/test_argparser.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ def extended_parser():
103103
dest='keep_stage_files', action='store_true',
104104
envvar='RFM_KEEP_STAGE_FILES', configvar='general/keep_stage_files'
105105
)
106+
parser.add_argument(
107+
'--git-timeout', envvar='RFM_GIT_TIMEOUT', action='store',
108+
configvar='general/git_timeout', type=float
109+
)
106110
foo_options.add_argument(
107111
'--timestamp', action='store',
108112
envvar='RFM_TIMESTAMP_DIRS', configvar='general/timestamp_dirs'
@@ -154,7 +158,8 @@ def test_option_with_config(default_exec_ctx, extended_parser, tmp_path):
154158
'RFM_TIMESTAMP': '%F',
155159
'RFM_NON_DEFAULT_CRAYPE': 'yes',
156160
'RFM_MODULES_PRELOAD': 'a,b,c',
157-
'RFM_KEEP_STAGE_FILES': 'no'
161+
'RFM_KEEP_STAGE_FILES': 'no',
162+
'RFM_GIT_TIMEOUT': '0.3'
158163
}):
159164
site_config = rt.runtime().site_config
160165
options = extended_parser.parse_args(
@@ -167,6 +172,7 @@ def test_option_with_config(default_exec_ctx, extended_parser, tmp_path):
167172
assert site_config.get('systems/0/prefix') == str(tmp_path)
168173
assert site_config.get('general/0/colorize') is False
169174
assert site_config.get('general/0/keep_stage_files') is False
175+
assert site_config.get('general/0/git_timeout') == 0.3
170176

171177
# Defaults specified in parser override those in configuration file
172178
assert site_config.get('systems/0/stagedir') == '/foo'
@@ -175,8 +181,9 @@ def test_option_with_config(default_exec_ctx, extended_parser, tmp_path):
175181
def test_option_envvar_conversion_error(default_exec_ctx, extended_parser):
176182
with rt.temp_environment(variables={
177183
'RFM_NON_DEFAULT_CRAYPE': 'foo',
184+
'RFM_GIT_TIMEOUT': 'non-float'
178185
}):
179186
site_config = rt.runtime().site_config
180187
options = extended_parser.parse_args(['--nocolor'])
181188
errors = options.update_config(site_config)
182-
assert len(errors) == 1
189+
assert len(errors) == 2

unittests/test_cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -781,8 +781,8 @@ def test_maxfail_invalid_option(run_reframe):
781781
)
782782
assert 'Traceback' not in stdout
783783
assert 'Traceback' not in stderr
784-
assert "--maxfail is not a valid integer: 'foo'" in stdout
785-
assert returncode == 1
784+
assert "--maxfail: invalid int value: 'foo'" in stderr
785+
assert returncode == 2
786786

787787

788788
def test_maxfail_negative(run_reframe):
@@ -793,7 +793,7 @@ def test_maxfail_negative(run_reframe):
793793
)
794794
assert 'Traceback' not in stdout
795795
assert 'Traceback' not in stderr
796-
assert "--maxfail should be a non-negative integer: '-2'" in stdout
796+
assert "--maxfail should be a non-negative integer: -2" in stdout
797797
assert returncode == 1
798798

799799

0 commit comments

Comments
 (0)