Skip to content

Commit

Permalink
fix: error parsing multiple args in declarative hook #106
Browse files Browse the repository at this point in the history
  • Loading branch information
robcxyz committed Dec 3, 2022
1 parent 08bae60 commit 6181275
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 54 deletions.
31 changes: 25 additions & 6 deletions tackle/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ def evaluate_args(
TODO: This needs to be re-thought. Right now we parse the inputs without regard
for the types of the argument mapping. What could be better is if we know the types
of the arg mapping ahead of time and then try to assemble the most logical mapping
afterwards. So if the mapping consists of a [str, list], then the if the first
afterwards. So if the mapping consists of a [str, list], then if the first
args are strs then we can ignore the list part. Right now it would just join all
the strings together if they are part of last arg mapping.
TODO: Improve error handling.
Expand All @@ -548,6 +548,9 @@ def evaluate_args(
- Single types then into unions?
- If type cannot be infered (ie Any) then do ast as literal
"""
# Flag to inform if we are at end of args and need to pop the rest
pop_all: bool = False

hook_args: list = Hook.__fields__['args'].default
for i, v in enumerate(args):
# Iterate over the input args
Expand All @@ -560,19 +563,23 @@ def evaluate_args(
elif Hook.__fields__[hook_args[i]].type_ == str:
# Was parsed on spaces so reconstructed.
value = ' '.join(args[i:])
pop_all = True
elif Hook.__fields__[hook_args[i]].type_ in (bool, float, int):
# TODO: Incomplete
value = args[i]
elif isinstance(Hook.__fields__[hook_args[i]], list):
# If list then all the remaining items
value = args[i:]
pop_all = True
elif isinstance(v, str):
# Make assumption the rest of the args can be reconstructed as above
value = ' '.join(args[i:])
pop_all = True
elif isinstance(v, (bool, float, int)):
# TODO: Incomplete
if len(args[i:]) > 1:
value = args[i:]
pop_all = True
else:
value = args[i]
else:
Expand All @@ -585,7 +592,10 @@ def evaluate_args(
) from None
value = args[i]
hook_dict[hook_args[i]] = value
args.pop(0)
if pop_all:
args.clear()
else:
args.pop(0)
return
else:
# The hooks arguments are indexed
Expand Down Expand Up @@ -899,13 +909,22 @@ def find_run_hook_method(
elif arg == 'help':
# Exit 0
run_help(context=context, hook=hook)
elif 'args' in hook.__fields__:
evaluate_args(args, arg_dict, Hook=hook, context=context)
else:
# elif 'args' not in hook.__fields__:
elif hook.__fields__['args'].default == []: # noqa
hook_name = hook.identifier.split('.')[-1]
if hook_name == '':
msg = "default hook"
else:
msg = f"hook='{hook_name}'"
raise exceptions.UnknownInputArgumentException(
"Can't find the ", context=context
f"The {msg} was supplied the arg='{arg}' and does not take any "
"arguments. Exiting.",
context=context,
) from None

if 'args' in hook.__fields__:
evaluate_args(args, arg_dict, Hook=hook, context=context)

try:
Hook = hook(**kwargs, **arg_dict)
except ValidationError as e:
Expand Down
38 changes: 0 additions & 38 deletions tests/cli/fixtures/help.yaml

This file was deleted.

3 changes: 3 additions & 0 deletions tests/cli/fixtures/input.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<-:
foo: str
args: ['foo']
2 changes: 0 additions & 2 deletions tests/cli/fixtures/tackle-help.yaml

This file was deleted.

5 changes: 1 addition & 4 deletions tests/cli/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,8 @@ def test_cli_parse_args_empty(mocker, change_curdir_fixtures):


@pytest.mark.parametrize("input_string", PRINTS)
def test_cli_parse_args_print_option(
mocker, change_curdir_fixtures, capsys, input_string
):
def test_cli_parse_args_print_option(change_curdir_fixtures, capsys, input_string):
"""When no arg is given we should find the closest tackle file."""
mocker.patch("tackle.main.tackle", autospec=True, return_value={})
main([input_string])
assert '{"stuff": "things"}' in capsys.readouterr().out

Expand Down
4 changes: 3 additions & 1 deletion tests/cli/test_cli_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@

COMMANDS = [
(['global-kwarg.yaml', '--key_a', '"stuff and things"'], 'stuff and things'),
(['input.yaml', 'bar', 'baz', '-pf', 'yaml'], 'foo: bar baz'),
]


@pytest.mark.parametrize("command,expected_output", COMMANDS)
def test_cli_commands(change_curdir_fixtures, command, expected_output, capsys):
"""Assert output comes out of cli."""
main(command)
assert expected_output in capsys.readouterr().out
output = capsys.readouterr().out
assert expected_output in output


def test_cli_command_find_in_parent(chdir_fixture, capsys):
Expand Down
7 changes: 7 additions & 0 deletions tests/parser/functions/test_functions_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,10 @@ def test_function_model_extraction_in_directory(
output = capsys.readouterr().out

assert json.loads(output) == expected_output


def test_function_cli_multiple_args(change_curdir_fixtures, capsys):
main(['supplied-args-param-str.yaml', 'foo', 'bing', 'bang', '-pf', 'yaml'])
output = capsys.readouterr().out

assert 'bar: bing bang' in output
4 changes: 2 additions & 2 deletions tests/parser/functions/test_functions_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def test_parser_functions_exceptions_try_in_default(chdir):


def test_parser_functions_raises_unknown_arg(change_curdir_fixtures):
with pytest.raises(exceptions.UnknownArgumentException):
with pytest.raises(exceptions.UnknownInputArgumentException):
tackle("cli-default-hook-no-context.yaml", 'NOT_HERE')


Expand All @@ -31,7 +31,7 @@ def test_parser_functions_raises_unknown_flags(change_curdir_fixtures):


def test_parser_functions_raises_unknown_arg_hook(change_curdir_fixtures):
with pytest.raises(exceptions.UnknownArgumentException):
with pytest.raises(exceptions.UnknownInputArgumentException):
tackle("cli-hook-no-context.yaml", 'run', 'NOT_HERE')


Expand Down
2 changes: 1 addition & 1 deletion tests/parser/functions/test_functions_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,5 @@ def test_function_cli_tackle_help_with_arg(chdir):
def test_function_cli_tackle_arg_error(chdir):
"""Check that when we give a bad key, even with help we get an exception."""
chdir(os.path.join('fixtures', 'a-tackle'))
with pytest.raises(exceptions.UnknownArgumentException):
with pytest.raises(exceptions.UnknownInputArgumentException):
tackle('bad-key', 'help')

0 comments on commit 6181275

Please sign in to comment.