From 2d99d93d11e7908a51fde8de27b7a3584d23cf46 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 20 Nov 2014 15:03:52 +0100 Subject: asyncio: Coroutine objects are now rejected with a TypeError by the following functions: * add_signal_handler() * call_at() * call_later() * call_soon() * call_soon_threadsafe() * run_in_executor() Fix also the error message of add_signal_handler() (fix the name of the function). --- Lib/asyncio/base_events.py | 11 +++++++---- Lib/asyncio/unix_events.py | 5 +++-- Lib/test/test_asyncio/test_base_events.py | 26 +++++++++++++++----------- Lib/test/test_asyncio/test_unix_events.py | 14 ++++++++++---- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index b6b7123..40dd668 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -357,7 +357,8 @@ class BaseEventLoop(events.AbstractEventLoop): Absolute time corresponds to the event loop's time() method. """ - if coroutines.iscoroutinefunction(callback): + if (coroutines.iscoroutine(callback) + or coroutines.iscoroutinefunction(callback)): raise TypeError("coroutines cannot be used with call_at()") if self._debug: self._assert_is_current_event_loop() @@ -384,7 +385,8 @@ class BaseEventLoop(events.AbstractEventLoop): return handle def _call_soon(self, callback, args, check_loop): - if coroutines.iscoroutinefunction(callback): + if (coroutines.iscoroutine(callback) + or coroutines.iscoroutinefunction(callback)): raise TypeError("coroutines cannot be used with call_soon()") if self._debug and check_loop: self._assert_is_current_event_loop() @@ -421,8 +423,9 @@ class BaseEventLoop(events.AbstractEventLoop): return handle def run_in_executor(self, executor, callback, *args): - if coroutines.iscoroutinefunction(callback): - raise TypeError("Coroutines cannot be used with run_in_executor()") + if (coroutines.iscoroutine(callback) + or coroutines.iscoroutinefunction(callback)): + raise TypeError("coroutines cannot be used with run_in_executor()") if isinstance(callback, events.Handle): assert not args assert not isinstance(callback, events.TimerHandle) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index e49212e..efe06d4 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -67,8 +67,9 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): Raise ValueError if the signal number is invalid or uncatchable. Raise RuntimeError if there is a problem setting up the handler. """ - if coroutines.iscoroutinefunction(callback): - raise TypeError("coroutines cannot be used with call_soon()") + if (coroutines.iscoroutine(callback) + or coroutines.iscoroutinefunction(callback)): + raise TypeError("coroutines cannot be used with add_signal_handler()") self._check_signal(sig) try: # set_wakeup_fd() raises ValueError if this is not the diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index d61a64c..0aa0117 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1107,19 +1107,23 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase): def test_call_coroutine(self): @asyncio.coroutine - def coroutine_function(): + def simple_coroutine(): pass - with self.assertRaises(TypeError): - self.loop.call_soon(coroutine_function) - with self.assertRaises(TypeError): - self.loop.call_soon_threadsafe(coroutine_function) - with self.assertRaises(TypeError): - self.loop.call_later(60, coroutine_function) - with self.assertRaises(TypeError): - self.loop.call_at(self.loop.time() + 60, coroutine_function) - with self.assertRaises(TypeError): - self.loop.run_in_executor(None, coroutine_function) + coro_func = simple_coroutine + coro_obj = coro_func() + self.addCleanup(coro_obj.close) + for func in (coro_func, coro_obj): + with self.assertRaises(TypeError): + self.loop.call_soon(func) + with self.assertRaises(TypeError): + self.loop.call_soon_threadsafe(func) + with self.assertRaises(TypeError): + self.loop.call_later(60, func) + with self.assertRaises(TypeError): + self.loop.call_at(self.loop.time() + 60, func) + with self.assertRaises(TypeError): + self.loop.run_in_executor(None, func) @mock.patch('asyncio.base_events.logger') def test_log_slow_callbacks(self, m_logger): diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 2f3fa18..b6ad018 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -65,15 +65,21 @@ class SelectorEventLoopSignalTests(test_utils.TestCase): @mock.patch('asyncio.unix_events.signal') def test_add_signal_handler_coroutine_error(self, m_signal): + m_signal.NSIG = signal.NSIG @asyncio.coroutine def simple_coroutine(): yield from [] - self.assertRaises( - TypeError, - self.loop.add_signal_handler, - signal.SIGINT, simple_coroutine) + # callback must not be a coroutine function + coro_func = simple_coroutine + coro_obj = coro_func() + self.addCleanup(coro_obj.close) + for func in (coro_func, coro_obj): + self.assertRaisesRegex( + TypeError, 'coroutines cannot be used with add_signal_handler', + self.loop.add_signal_handler, + signal.SIGINT, func) @mock.patch('asyncio.unix_events.signal') def test_add_signal_handler(self, m_signal): -- cgit v0.12