diff --git a/fire/core.py b/fire/core.py index 6367262d..820f57f4 100644 --- a/fire/core.py +++ b/fire/core.py @@ -725,7 +725,18 @@ def _MakeParseFn(fn, metadata): required_kwonly = set(fn_spec.kwonlyargs) - set(fn_spec.kwonlydefaults) def _ParseFn(args): - """Parses the list of `args` into (varargs, kwargs), remaining_args.""" + """Parses the list of `args` into (varargs, kwargs), consumed_args, remaining_args.""" + + skip_parse = metadata.get(decorators.PASS_THROUGH, False) + + if skip_parse: + kwargs = {} + remaining_kwargs = [] + remaining_args = [] + varargs = consumed_args = args[:] + capacity = False + return (varargs, kwargs), consumed_args, remaining_args, capacity + kwargs, remaining_kwargs, remaining_args = _ParseKeywordArgs(args, fn_spec) # Note: _ParseArgs modifies kwargs. @@ -757,8 +768,16 @@ def _ParseFn(args): varargs = parsed_args + varargs remaining_args += remaining_kwargs - consumed_args = args[:len(args) - len(remaining_args)] - return (varargs, kwargs), consumed_args, remaining_args, capacity + sorted_remaining_args = [] + consumed_args = [] + for arg in args: + if arg in remaining_args: + sorted_remaining_args.append(arg) + remaining_args.remove(arg) + else: + consumed_args.append(arg) + + return (varargs, kwargs), consumed_args, sorted_remaining_args, capacity return _ParseFn @@ -992,4 +1011,4 @@ def _ParseValue(value, index, arg, metadata): elif default is not None: parse_fn = default - return parse_fn(value) + return parse_fn(value) \ No newline at end of file diff --git a/fire/decorators.py b/fire/decorators.py index b2e9b322..dccb31e2 100644 --- a/fire/decorators.py +++ b/fire/decorators.py @@ -27,6 +27,14 @@ FIRE_METADATA = 'FIRE_METADATA' FIRE_PARSE_FNS = 'FIRE_PARSE_FNS' ACCEPTS_POSITIONAL_ARGS = 'ACCEPTS_POSITIONAL_ARGS' +PASS_THROUGH = 'PASS_THROUGH' + + +def PassThrough(fn): + """Set a flag to tell Fire to pass original args to decorated fn. + """ + _SetMetadata(fn, PASS_THROUGH, True) + return fn def SetParseFn(fn, *arguments): diff --git a/fire/decorators_test.py b/fire/decorators_test.py index cc7d6203..40066b2e 100644 --- a/fire/decorators_test.py +++ b/fire/decorators_test.py @@ -90,6 +90,13 @@ def example7(self, arg1, arg2=None, *varargs, **kwargs): # pylint: disable=keyw return arg1, arg2, varargs, kwargs +class PassThroughArgs(object): + + @decorators.PassThrough + def example8(self, *args): + return args + + class FireDecoratorsTest(testutils.BaseTestCase): def testSetParseFnsNamedArgs(self): @@ -169,6 +176,11 @@ def testSetParseFn(self): command=['example7', '1', '--arg2=2', '3', '4', '--kwarg=5']), ('1', '2', ('3', '4'), {'kwarg': '5'})) + def testPassThrough(self): + command = ['example8', 'test', '1', '--arg2=2', '3', '4', '--kwarg=5', '--flag'] + self.assertEqual( + core.Fire(PassThroughArgs, command=command), tuple(command[1:])) + if __name__ == '__main__': testutils.main()