diff --git a/fire/core.py b/fire/core.py index 763b3d13..6abc22a5 100644 --- a/fire/core.py +++ b/fire/core.py @@ -669,7 +669,16 @@ def _CallAndUpdateTrace(component, args, component_trace, treatment='class', fn = component.__call__ if treatment == 'callable' else component parse = _MakeParseFn(fn, metadata) (varargs, kwargs), consumed_args, remaining_args, capacity = parse(args) - component = fn(*varargs, **kwargs) + + if six.PY34: + import asyncio # pylint: disable=import-error + if asyncio.iscoroutinefunction(fn): + loop = asyncio.get_event_loop() + component = loop.run_until_complete(fn(*varargs, **kwargs)) + else: + component = fn(*varargs, **kwargs) + else: + component = fn(*varargs, **kwargs) if treatment == 'class': action = trace.INSTANTIATED_CLASS diff --git a/fire/fire_test.py b/fire/fire_test.py index 2c7a580b..1a6b9e35 100644 --- a/fire/fire_test.py +++ b/fire/fire_test.py @@ -265,6 +265,11 @@ def testFireKeywordArgsWithMissingPositionalArgs(self): fire.Fire(tc.Kwargs, command=['run', 'Hello', '--cell', 'ok']), ('Hello', None, {'cell': 'ok'})) + @unittest.skipUnless(six.PY34, 'Asyncio only available in Python 3.4+') + def testFireAsyncio(self): + self.assertEqual(fire.Fire(tc.py3.WithAsyncio, + command=['double', '--count', '5']), 10) + def testFireObject(self): self.assertEqual( fire.Fire(tc.WithDefaults(), command=['double', '--count', '5']), 10) diff --git a/fire/test_components_py3.py b/fire/test_components_py3.py index e714be30..43a102f7 100644 --- a/fire/test_components_py3.py +++ b/fire/test_components_py3.py @@ -14,7 +14,9 @@ # Lint as: python3 """This module has components that use Python 3 specific syntax.""" +import six +import asyncio import functools @@ -43,3 +45,10 @@ def lru_cache_in_class(self, arg1): @functools.lru_cache() def lru_cache_decorated(arg1): return arg1 + + +class WithAsyncio(object): + + @asyncio.coroutine + def double(self, count=0): + return 2 * count