Verified Commit 800c1361 authored by Raphaël Bleuse's avatar Raphaël Bleuse
Browse files

Handle error cases of scheduler options loading

parent 23871f65
......@@ -40,20 +40,49 @@ def get_scheduler_by_name(name, *, options):
return cls(options)
# TODO: correct handling of error path
def _scheduler_options(string):
"""Convert JSON-encoded scheduler options into a dict."""
string = string.strip()
if string.startswith('@'):
# classic text stream of the file containing the options
json_file = open(string[1:], mode='rt', encoding='utf-8')
else:
# encapsulate the whole JSON string in a text stream
json_file = io.StringIO(string)
with json_file:
options = json.load(json_file)
return options
class _JsonStoreAction(argparse.Action):
"""
Decode and store the JSON-encoded value of a single argument.
If the argument's value starts with a '@', the path to a JSON file is
expected.
Otherwise, a valid JSON string is expected.
"""
def __init__(self, option_strings, dest, nargs=None, **kwargs):
if nargs is not None:
raise ValueError('nargs is not allowed')
super().__init__(option_strings, dest, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
try:
rawcontent = values.strip()
if rawcontent.startswith('@'):
# classic text stream of the file containing the options
json_file = open(rawcontent[1:], mode='rt', encoding='utf-8')
else:
# encapsulate the whole JSON string in a text stream
json_file = io.StringIO(rawcontent)
with json_file:
decoded_content = json.load(json_file)
setattr(namespace, self.dest, decoded_content)
except OSError as err:
# raised by open()
raise argparse.ArgumentError(
self,
f'unable to read \'{err.filename}\': {err.strerror.lower()}'
) from None
except json.JSONDecodeError:
# raised by json.load(), subclass of ValueError
raise argparse.ArgumentError(self, 'invalid JSON object') from None
except ValueError:
# raised by open() or json.load()
raise argparse.ArgumentError(
self,
'incorrect encoding (expected utf-8)'
) from None
def _build_parser():
......@@ -90,11 +119,11 @@ def _build_parser():
parser.add_argument(
'-o', '--scheduler-options',
default={},
type=_scheduler_options,
help='options forwarded to the scheduler, '
action=_JsonStoreAction,
help='options forwarded to the scheduler (default: empty dict), '
'either a JSON string (e.g., \'{"option": "value"}\') '
'or an @-prefixed JSON file containing the options (e.g., \'@options.json\')',
metavar='OPTIONS',
'or a @-prefixed JSON file containing the options (e.g., \'@options.json\')',
metavar='[@]OPTIONS',
)
parser.add_argument(
'scheduler',
......@@ -156,6 +185,7 @@ def main(args=None):
logging.basicConfig(level=logging.INFO)
parser = _build_parser()
arguments = parser.parse_args(args)
logging.debug(f'parsed arguments: {vars(arguments)}')
# instantiate scheduler
_abort_on_ambiguous_scheduler_name(arguments.scheduler)
scheduler = get_scheduler_by_name(arguments.scheduler, options=arguments.scheduler_options)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment