8000 Support asyncio coroutines · shader/python-fire@e4cb72a · GitHub
[go: up one dir, main page]

Skip to content

Commit e4cb72a

Browse files
robweisscopybara-github
authored andcommitted
Support asyncio coroutines
COPYBARA_INTEGRATE_REVIEW=google#127 from robweiss:run_coroutines 56bea93 PiperOrigin-RevId: 347872801 Change-Id: I17407ac8c3cb7b29026bd7d78729747a3a9875cf
1 parent 3be260e commit e4cb72a

File tree

4 files changed

+34
-2
lines changed

4 files changed

+34
-2
lines changed

fire/core.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ def main(argv):
7474
from fire.console import console_io
7575
import six
7676

77+
if six.PY34:
78+
import asyncio # pylint: disable=g-import-not-at-top,import-error # pytype: disable=import-error
79+
7780

7881
def Fire(component=None, command=None, name=None):
7982
"""This function, Fire, is the main entrypoint for Python Fire.
@@ -669,7 +672,13 @@ def _CallAndUpdateTrace(component, args, component_trace, treatment='class',
669672
fn = component.__call__ if treatment == 'callable' else component
670673
parse = _MakeParseFn(fn, metadata)
671674
(varargs, kwargs), consumed_args, remaining_args, capacity = parse(args)
672-
component = fn(*varargs, **kwargs)
675+
676+
# Call the function.
677+
if inspectutils.IsCoroutineFunction(fn):
678+
loop = asyncio.get_event_loop()
679+
component = loop.run_until_complete(fn(*varargs, **kwargs))
680+
else:
681+
component = fn(*varargs, **kwargs)
673682

674683
if treatment == 'class':
675684
action = trace.INSTANTIATED_CLASS

fire/fire_test.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,11 @@ def testHelpKwargsDecorator(self):
721721
with self.assertRaisesFireExit(0):
722722
fire.Fire(tc.decorated_method, command=['--help'])
723723

724+
@testutils.skipIf(six.PY2, 'Asyncio not available in Python 2.')
725+
def testFireAsyncio(self):
726+
self.assertEqual(fire.Fire(tc.py3.WithAsyncio,
727+
command=['double', '--count', '10']), 20)
728+
724729

725730
if __name__ == '__main__':
726731
testutils.main()

fire/inspectutils.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
import six
2828

29+
if six.PY34:
30+
import asyncio # pylint: disable=g-import-not-at-top,import-error # pytype: disable=import-error
31+
2932

3033
class FullArgSpec(object):
3134
"""The arguments of a function, as in Python 3's inspect.FullArgSpec."""
@@ -250,7 +253,7 @@ def GetFileAndLine(component):
250253
try:
251254
unused_code, lineindex = inspect.findsource(component)
252255
lineno = lineindex + 1
253-
except IOError:
256+
except (IOError, IndexError):
254257
lineno = None
255258

256259
return filename, lineno
@@ -360,3 +363,10 @@ def GetClassAttrsDict(component):
360363
class_attr.name: class_attr
361364
for class_attr in class_attrs_list
362365
}
366+
367+
368+
def IsCoroutineFunction(fn):
369+
try:
370+
return six.PY34 and asyncio.iscoroutinefunction(fn)
371+
except: # pylint: disable=bare-except
372+
return False

fire/test_components_py3.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# Lint as: python3
1616
"""This module has components that use Python 3 specific syntax."""
1717

18+
import asyncio
1819
import functools
1920
from typing import Tuple
2021

@@ -49,6 +50,13 @@ def lru_cache_decorated(arg1):
4950
return arg1
5051

5152

53+
class WithAsyncio(object):
54+
55+
@asyncio.coroutine
56+
def double(self, count=0):
57+
return 2 * count
58+
59+
5260
class WithTypes(object):
5361
"""Class with functions that have default arguments and types."""
5462

0 commit comments

Comments
 (0)
0