diff options
author | Yury Selivanov <yury@magic.io> | 2016-11-03 22:09:24 (GMT) |
---|---|---|
committer | Yury Selivanov <yury@magic.io> | 2016-11-03 22:09:24 (GMT) |
commit | 491a912659a4aeb57c400f37b8059fa1ef7bed73 (patch) | |
tree | 94ffc1eb512bff47d248fef0d3ad10d7a8dffbbb /Lib | |
parent | 9e80eeb22dde9740dada6d750e4dcb1712d070ab (diff) | |
download | cpython-491a912659a4aeb57c400f37b8059fa1ef7bed73.zip cpython-491a912659a4aeb57c400f37b8059fa1ef7bed73.tar.gz cpython-491a912659a4aeb57c400f37b8059fa1ef7bed73.tar.bz2 |
Issue #28600: Optimize loop.call_soon().
Run expensive type checks only in debug mode. In addition, stop
supporting passing handles to loop.run_in_executor.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/asyncio/base_events.py | 40 | ||||
-rw-r--r-- | Lib/asyncio/events.py | 1 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_base_events.py | 36 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_events.py | 7 |
4 files changed, 27 insertions, 57 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index b3e318e..ddf041d 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -528,12 +528,10 @@ class BaseEventLoop(events.AbstractEventLoop): Absolute time corresponds to the event loop's time() method. """ - if (coroutines.iscoroutine(callback) - or coroutines.iscoroutinefunction(callback)): - raise TypeError("coroutines cannot be used with call_at()") self._check_closed() if self._debug: self._check_thread() + self._check_callback(callback, 'call_at') timer = events.TimerHandle(when, callback, args, self) if timer._source_traceback: del timer._source_traceback[-1] @@ -551,18 +549,27 @@ class BaseEventLoop(events.AbstractEventLoop): Any positional arguments after the callback will be passed to the callback when it is called. """ + self._check_closed() if self._debug: self._check_thread() + self._check_callback(callback, 'call_soon') handle = self._call_soon(callback, args) if handle._source_traceback: del handle._source_traceback[-1] return handle + def _check_callback(self, callback, method): + if (coroutines.iscoroutine(callback) or + coroutines.iscoroutinefunction(callback)): + raise TypeError( + "coroutines cannot be used with {}()".format(method)) + if not callable(callback): + raise TypeError( + 'a callable object was expected by {}(), got {!r}'.format( + method, callback)) + + def _call_soon(self, callback, args): - if (coroutines.iscoroutine(callback) - or coroutines.iscoroutinefunction(callback)): - raise TypeError("coroutines cannot be used with call_soon()") - self._check_closed() handle = events.Handle(callback, args, self) if handle._source_traceback: del handle._source_traceback[-1] @@ -588,6 +595,9 @@ class BaseEventLoop(events.AbstractEventLoop): def call_soon_threadsafe(self, callback, *args): """Like call_soon(), but thread-safe.""" + self._check_closed() + if self._debug: + self._check_callback(callback, 'call_soon_threadsafe') handle = self._call_soon(callback, args) if handle._source_traceback: del handle._source_traceback[-1] @@ -595,21 +605,9 @@ class BaseEventLoop(events.AbstractEventLoop): return handle def run_in_executor(self, executor, func, *args): - if (coroutines.iscoroutine(func) - or coroutines.iscoroutinefunction(func)): - raise TypeError("coroutines cannot be used with run_in_executor()") self._check_closed() - if isinstance(func, events.Handle): - assert not args - assert not isinstance(func, events.TimerHandle) - warnings.warn( - "Passing Handle to loop.run_in_executor() is deprecated", - DeprecationWarning) - if func._cancelled: - f = self.create_future() - f.set_result(None) - return f - func, args = func._callback, func._args + if self._debug: + self._check_callback(func, 'run_in_executor') if executor is None: executor = self._default_executor if executor is None: diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 3a33646..b89b4b2 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -82,7 +82,6 @@ class Handle: '_source_traceback', '_repr', '__weakref__') def __init__(self, callback, args, loop): - assert not isinstance(callback, Handle), 'A Handle is not a callback' self._loop = loop self._callback = callback self._args = args diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index a9aba0f..3913125 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -235,6 +235,11 @@ class BaseEventLoopTests(test_utils.TestCase): self.assertIsInstance(h, asyncio.Handle) self.assertIn(h, self.loop._ready) + def test_call_soon_non_callable(self): + self.loop.set_debug(True) + with self.assertRaisesRegex(TypeError, 'a callable object'): + self.loop.call_soon(1) + def test_call_later(self): def cb(): pass @@ -341,47 +346,21 @@ class BaseEventLoopTests(test_utils.TestCase): # check disabled if debug mode is disabled test_thread(self.loop, False, create_loop=True) - def test_run_once_in_executor_handle(self): - def cb(): - pass - - self.assertRaises( - AssertionError, self.loop.run_in_executor, - None, asyncio.Handle(cb, (), self.loop), ('',)) - self.assertRaises( - AssertionError, self.loop.run_in_executor, - None, asyncio.TimerHandle(10, cb, (), self.loop)) - - def test_run_once_in_executor_cancelled(self): - def cb(): - pass - h = asyncio.Handle(cb, (), self.loop) - h.cancel() - - with self.assertWarnsRegex(DeprecationWarning, "Passing Handle"): - f = self.loop.run_in_executor(None, h) - self.assertIsInstance(f, asyncio.Future) - self.assertTrue(f.done()) - self.assertIsNone(f.result()) - def test_run_once_in_executor_plain(self): def cb(): pass - h = asyncio.Handle(cb, (), self.loop) f = asyncio.Future(loop=self.loop) executor = mock.Mock() executor.submit.return_value = f self.loop.set_default_executor(executor) - with self.assertWarnsRegex(DeprecationWarning, "Passing Handle"): - res = self.loop.run_in_executor(None, h) + res = self.loop.run_in_executor(None, cb) self.assertIs(f, res) executor = mock.Mock() executor.submit.return_value = f - with self.assertWarnsRegex(DeprecationWarning, "Passing Handle"): - res = self.loop.run_in_executor(executor, h) + res = self.loop.run_in_executor(executor, cb) self.assertIs(f, res) self.assertTrue(executor.submit.called) @@ -1666,6 +1645,7 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase): def simple_coroutine(): pass + self.loop.set_debug(True) coro_func = simple_coroutine coro_obj = coro_func() self.addCleanup(coro_obj.close) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 7df926f..d8946e3 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2249,13 +2249,6 @@ class HandleTests(test_utils.TestCase): h.cancel() self.assertTrue(h._cancelled) - def test_handle_from_handle(self): - def callback(*args): - return args - h1 = asyncio.Handle(callback, (), loop=self.loop) - self.assertRaises( - AssertionError, asyncio.Handle, h1, (), self.loop) - def test_callback_with_exception(self): def callback(): raise ValueError() |