From: Victor Stinner Date: Tue, 8 Jul 2014 09:29:25 +0000 (+0200) Subject: asyncio: sync with Tulip X-Git-Tag: v3.4.2rc1~250 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=896a25ab30269369201401b50c66130911dd2238;p=thirdparty%2FPython%2Fcpython.git asyncio: sync with Tulip - Tulip issue 185: Add a create_task() method to event loops. The create_task() method can be overriden in custom event loop to implement their own task class. For example, greenio and Pulsar projects use their own task class. The create_task() method is now preferred over creating directly task using the Task class. - tests: fix a warning - fix typo in the name of a test function - Update AbstractEventLoop: add new event loop methods; update also the unit test --- diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 2230dc2c9cc4..52c5517b2f8a 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -151,6 +151,12 @@ class BaseEventLoop(events.AbstractEventLoop): % (self.__class__.__name__, self.is_running(), self.is_closed(), self.get_debug())) + def create_task(self, coro): + """Schedule a coroutine object. + + Return a task object.""" + return tasks.Task(coro, loop=self) + def _make_socket_transport(self, sock, protocol, waiter=None, *, extra=None, server=None): """Create socket transport.""" diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index b389cfb0889a..1f5e5824e51e 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -200,6 +200,10 @@ class AbstractEventLoop: """Return whether the event loop is currently running.""" raise NotImplementedError + def is_closed(self): + """Returns True if the event loop was closed.""" + raise NotImplementedError + def close(self): """Close the loop. @@ -225,6 +229,11 @@ class AbstractEventLoop: def time(self): raise NotImplementedError + # Method scheduling a coroutine object: create a task. + + def create_task(self, coro): + raise NotImplementedError + # Methods for interacting with threads. def call_soon_threadsafe(self, callback, *args): diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index a10b969c990a..9bde218bfa49 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -213,7 +213,7 @@ class StreamReaderProtocol(FlowControlMixin, protocols.Protocol): res = self._client_connected_cb(self._stream_reader, self._stream_writer) if coroutines.iscoroutine(res): - tasks.Task(res, loop=self._loop) + self._loop.create_task(res) def connection_lost(self, exc): if exc is None: diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 8c7217b702b4..befc2967c71b 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -505,7 +505,9 @@ def async(coro_or_future, *, loop=None): raise ValueError('loop argument must agree with Future') return coro_or_future elif coroutines.iscoroutine(coro_or_future): - task = Task(coro_or_future, loop=loop) + if loop is None: + loop = events.get_event_loop() + task = loop.create_task(coro_or_future) if task._source_traceback: del task._source_traceback[-1] return task diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py index ef3be236de32..6abcaf1d3797 100644 --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -48,7 +48,7 @@ def run_briefly(loop): def once(): pass gen = once() - t = tasks.Task(gen, loop=loop) + t = loop.create_task(gen) # Don't log a warning if the task is not done after run_until_complete(). # It occurs if the loop is stopped or if a task raises a BaseException. t._log_destroy_pending = False diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index adba082b5e91..f6da7c375ef2 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -12,6 +12,7 @@ from test.support import IPV6_ENABLED import asyncio from asyncio import base_events +from asyncio import events from asyncio import constants from asyncio import test_utils @@ -526,6 +527,29 @@ class BaseEventLoopTests(test_utils.TestCase): PYTHONASYNCIODEBUG='1') self.assertEqual(stdout.rstrip(), b'False') + def test_create_task(self): + class MyTask(asyncio.Task): + pass + + @asyncio.coroutine + def test(): + pass + + class EventLoop(base_events.BaseEventLoop): + def create_task(self, coro): + return MyTask(coro, loop=loop) + + loop = EventLoop() + self.set_event_loop(loop) + + coro = test() + task = asyncio.async(coro, loop=loop) + self.assertIsInstance(task, MyTask) + + # make warnings quiet + task._log_destroy_pending = False + coro.close() + class MyProto(asyncio.Protocol): done = None diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index beb6cecf2dd3..b89416fb5769 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1968,8 +1968,12 @@ class AbstractEventLoopTests(unittest.TestCase): NotImplementedError, loop.stop) self.assertRaises( NotImplementedError, loop.is_running) + self.assertRaises( + NotImplementedError, loop.is_closed) self.assertRaises( NotImplementedError, loop.close) + self.assertRaises( + NotImplementedError, loop.create_task, None) self.assertRaises( NotImplementedError, loop.call_later, None, None) self.assertRaises( @@ -2027,6 +2031,16 @@ class AbstractEventLoopTests(unittest.TestCase): mock.sentinel) self.assertRaises( NotImplementedError, loop.subprocess_exec, f) + self.assertRaises( + NotImplementedError, loop.set_exception_handler, f) + self.assertRaises( + NotImplementedError, loop.default_exception_handler, f) + self.assertRaises( + NotImplementedError, loop.call_exception_handler, f) + self.assertRaises( + NotImplementedError, loop.get_debug) + self.assertRaises( + NotImplementedError, loop.set_debug, f) class ProtocolsAbsTests(unittest.TestCase): diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py index a6071ea76ba8..157adb7f7d94 100644 --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -301,12 +301,12 @@ class FutureTests(test_utils.TestCase): def test_future_exception_never_retrieved(self, m_log): self.loop.set_debug(True) - def memroy_error(): + def memory_error(): try: raise MemoryError() except BaseException as exc: return exc - exc = memroy_error() + exc = memory_error() future = asyncio.Future(loop=self.loop) source_traceback = future._source_traceback diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index eaef05b50dd8..afadc7c1ed58 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -233,6 +233,9 @@ class TaskTests(test_utils.TestCase): self.assertRegex(repr(task), '' % re.escape(repr(fut))) + fut.set_result(None) + self.loop.run_until_complete(task) + def test_task_basics(self): @asyncio.coroutine def outer():