summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorYury Selivanov <yselivanov@sprymix.com>2015-06-24 14:32:22 (GMT)
committerYury Selivanov <yselivanov@sprymix.com>2015-06-24 14:32:22 (GMT)
commit8f1c99321bfe72d21b01bad71293a7daa1c9e73f (patch)
treeef5c6e72f6bf848363e740a3cf2dd1f83cf9b10c /Lib
parent3bdbcedfd948bf66a3e2bdaf8180c8e7a262db5f (diff)
parent29a602a1409cc3f6e64a29865ad9d3624bddd35e (diff)
downloadcpython-8f1c99321bfe72d21b01bad71293a7daa1c9e73f.zip
cpython-8f1c99321bfe72d21b01bad71293a7daa1c9e73f.tar.gz
cpython-8f1c99321bfe72d21b01bad71293a7daa1c9e73f.tar.bz2
Issue #24400: Fix CoroWrapper for 'async def' coroutines
Diffstat (limited to 'Lib')
-rw-r--r--Lib/asyncio/coroutines.py50
-rw-r--r--Lib/test/test_asyncio/test_pep492.py25
-rw-r--r--Lib/test/test_asyncio/test_tasks.py3
3 files changed, 66 insertions, 12 deletions
diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py
index 4fc46a5..896cc56 100644
--- a/Lib/asyncio/coroutines.py
+++ b/Lib/asyncio/coroutines.py
@@ -103,9 +103,6 @@ class CoroWrapper:
def __iter__(self):
return self
- if _PY35:
- __await__ = __iter__ # make compatible with 'await' expression
-
def __next__(self):
return self.gen.send(None)
@@ -143,10 +140,28 @@ class CoroWrapper:
def gi_code(self):
return self.gen.gi_code
+ if _PY35:
+
+ __await__ = __iter__ # make compatible with 'await' expression
+
+ @property
+ def cr_running(self):
+ return self.gen.cr_running
+
+ @property
+ def cr_code(self):
+ return self.gen.cr_code
+
+ @property
+ def cr_frame(self):
+ return self.gen.cr_frame
+
def __del__(self):
# Be careful accessing self.gen.frame -- self.gen might not exist.
gen = getattr(self, 'gen', None)
frame = getattr(gen, 'gi_frame', None)
+ if frame is None:
+ frame = getattr(gen, 'cr_frame', None)
if frame is not None and frame.f_lasti == -1:
msg = '%r was never yielded from' % self
tb = getattr(self, '_source_traceback', ())
@@ -233,28 +248,43 @@ def iscoroutine(obj):
def _format_coroutine(coro):
assert iscoroutine(coro)
+ coro_name = None
if isinstance(coro, CoroWrapper):
func = coro.func
+ coro_name = coro.__qualname__
else:
func = coro
- coro_name = events._format_callback(func, ())
- filename = coro.gi_code.co_filename
+ if coro_name is None:
+ coro_name = events._format_callback(func, ())
+
+ try:
+ coro_code = coro.gi_code
+ except AttributeError:
+ coro_code = coro.cr_code
+
+ try:
+ coro_frame = coro.gi_frame
+ except AttributeError:
+ coro_frame = coro.cr_frame
+
+ filename = coro_code.co_filename
if (isinstance(coro, CoroWrapper)
- and not inspect.isgeneratorfunction(coro.func)):
+ and not inspect.isgeneratorfunction(coro.func)
+ and coro.func is not None):
filename, lineno = events._get_function_source(coro.func)
- if coro.gi_frame is None:
+ if coro_frame is None:
coro_repr = ('%s done, defined at %s:%s'
% (coro_name, filename, lineno))
else:
coro_repr = ('%s running, defined at %s:%s'
% (coro_name, filename, lineno))
- elif coro.gi_frame is not None:
- lineno = coro.gi_frame.f_lineno
+ elif coro_frame is not None:
+ lineno = coro_frame.f_lineno
coro_repr = ('%s running at %s:%s'
% (coro_name, filename, lineno))
else:
- lineno = coro.gi_code.co_firstlineno
+ lineno = coro_code.co_firstlineno
coro_repr = ('%s done, defined at %s:%s'
% (coro_name, filename, lineno))
diff --git a/Lib/test/test_asyncio/test_pep492.py b/Lib/test/test_asyncio/test_pep492.py
index aa0e2a2..82bb995 100644
--- a/Lib/test/test_asyncio/test_pep492.py
+++ b/Lib/test/test_asyncio/test_pep492.py
@@ -119,7 +119,7 @@ class CoroutineTests(BaseTest):
self.assertEqual(coro.send(None), 'spam')
coro.close()
- def test_async_ded_coroutines(self):
+ def test_async_def_coroutines(self):
async def bar():
return 'spam'
async def foo():
@@ -134,5 +134,28 @@ class CoroutineTests(BaseTest):
data = self.loop.run_until_complete(foo())
self.assertEqual(data, 'spam')
+ @mock.patch('asyncio.coroutines.logger')
+ def test_async_def_wrapped(self, m_log):
+ async def foo():
+ pass
+ async def start():
+ foo_coro = foo()
+ self.assertRegex(
+ repr(foo_coro),
+ r'<CoroWrapper .*\.foo running at .*pep492.*>')
+
+ with support.check_warnings((r'.*foo.*was never',
+ RuntimeWarning)):
+ foo_coro = None
+ support.gc_collect()
+ self.assertTrue(m_log.error.called)
+ message = m_log.error.call_args[0][0]
+ self.assertRegex(message,
+ r'CoroWrapper.*foo.*was never')
+
+ self.loop.set_debug(True)
+ self.loop.run_until_complete(start())
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py
index 6541df7..251192a 100644
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -1715,7 +1715,8 @@ class TaskTests(test_utils.TestCase):
self.assertTrue(m_log.error.called)
message = m_log.error.call_args[0][0]
func_filename, func_lineno = test_utils.get_function_source(coro_noop)
- regex = (r'^<CoroWrapper %s\(\) .* at %s:%s, .*> '
+
+ regex = (r'^<CoroWrapper %s\(?\)? .* at %s:%s, .*> '
r'was never yielded from\n'
r'Coroutine object created at \(most recent call last\):\n'
r'.*\n'