diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index b68590b..db50674 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -28,19 +28,7 @@ SUBPARSER_ALIASES = { } -def parse_subparser_arguments(arguments, unparsed_arguments, subparsers): - remaining_subparser_arguments = [] - - for subparser_name, subparser in reversed(subparsers.items()): - if subparser_name not in arguments.keys(): - continue - - subparser = subparsers[subparser_name] - unused_parsed, remaining = subparser.parse_known_args( - [argument for argument in unparsed_arguments if argument != subparser_name] - ) - remaining_subparser_arguments.append(remaining) - +def get_unparsable_arguments(remaining_subparser_arguments): # Determine the remaining arguments that no subparsers have consumed. if remaining_subparser_arguments: remaining_arguments = [ @@ -128,7 +116,20 @@ def parse_subparser_arguments(unparsed_arguments, subparsers): # Now ask each subparser, one by one, to greedily consume arguments, from last to first. This # allows subparsers to consume arguments before their parent subparsers do. - remaining_arguments = parse_subparser_arguments(arguments, unparsed_arguments, subparsers) + remaining_subparser_arguments = [] + + for subparser_name, subparser in reversed(subparsers.items()): + if subparser_name not in arguments.keys(): + continue + + subparser = subparsers[subparser_name] + unused_parsed, remaining = subparser.parse_known_args( + [argument for argument in unparsed_arguments if argument != subparser_name] + ) + remaining_subparser_arguments.append(remaining) + + if remaining_subparser_arguments: + remaining_arguments = get_unparsable_arguments(remaining_subparser_arguments) # Special case: If "borg" is present in the arguments, consume all arguments after (+1) the # "borg" action. diff --git a/tests/unit/commands/test_arguments.py b/tests/unit/commands/test_arguments.py index c532022..ef8fd1e 100644 --- a/tests/unit/commands/test_arguments.py +++ b/tests/unit/commands/test_arguments.py @@ -178,19 +178,32 @@ def test_parse_subparser_arguments_raises_error_when_no_subparser_is_specified() @pytest.mark.parametrize( - 'arguments, unparsed_arguments, subparsers, expected_remaining_arguments', - [ + 'arguments, expected', + [ ( - {'action': flexmock()}, - ['--verbosity', 'lots'], - {'action': flexmock(parse_known_args=lambda arguments: (flexmock(), ['--verbosity', 'lots']))}, - ['--verbosity', 'lots'], + ( + ('--latest', 'archive', 'prune', 'extract', 'list', '--test-flag'), + ('--latest', 'archive', 'check', 'extract', 'list', '--test-flag'), + ('prune', 'check', 'list', '--test-flag'), + ('prune', 'check', 'extract', '--test-flag'), + ), + [ + '--test-flag', + ], ), + ( + ( + ('--latest', 'archive', 'prune', 'extract', 'list'), + ('--latest', 'archive', 'check', 'extract', 'list'), + ('prune', 'check', 'list'), + ('prune', 'check', 'extract'), + ), + [], + ), + ((), []), ], ) -def test_get_remaining_arguments_returns_expected_remaining_arguments( - arguments, unparsed_arguments, subparsers, expected_remaining_arguments +def test_get_unparsable_arguments_returns_remaining_arguments_that_no_subparser_can_parse( + arguments, expected ): - remaining_arguments = module.get_remaining_arguments(arguments, unparsed_arguments, subparsers) - - assert remaining_arguments == expected_remaining_arguments \ No newline at end of file + assert module.get_unparsable_arguments(arguments) == expected