]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
asyncio: sync with Tulip
authorVictor Stinner <victor.stinner@gmail.com>
Tue, 8 Jul 2014 09:29:25 +0000 (11:29 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Tue, 8 Jul 2014 09:29:25 +0000 (11:29 +0200)
- 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

Lib/asyncio/base_events.py
Lib/asyncio/events.py
Lib/asyncio/streams.py
Lib/asyncio/tasks.py
Lib/asyncio/test_utils.py
Lib/test/test_asyncio/test_base_events.py
Lib/test/test_asyncio/test_events.py
Lib/test/test_asyncio/test_futures.py
Lib/test/test_asyncio/test_tasks.py

index 2230dc2c9cc4b54345a60cd3df5cd74b4b6c4a5c..52c5517b2f8a33d7c58832cffd6124a59627fb1a 100644 (file)
@@ -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."""
index b389cfb0889abcdf7004e66790c2df4b44e0f6f7..1f5e5824e51eb2ce0083f5439aaf9ad827abe440 100644 (file)
@@ -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):
index a10b969c990ab323e69ff5016d06f92f21c73f97..9bde218bfa4983c73f5ec1f25bc00cb4fca637ff 100644 (file)
@@ -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:
index 8c7217b702b43adcee66c6861cffe9b259cf67f6..befc2967c71b13d7fe73a41294c642ebce5353d4 100644 (file)
@@ -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
index ef3be236de320bcb7432385cf85f24b40863fe52..6abcaf1d37970a5de2ce0b8bb3ea140683a1a882 100644 (file)
@@ -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
index adba082b5e9155b582bf94c81699deaff8112cbb..f6da7c375ef2418cf7214b44d695d5d7cdb05f55 100644 (file)
@@ -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
index beb6cecf2dd34c442bb8663d78d29877d6e59647..b89416fb5769045293c6b9235e821bda9bb75ae4 100644 (file)
@@ -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):
index a6071ea76ba8baf1518a21c2d02b2582742285bc..157adb7f7d94e2d1111ec7a4683f5f7efe8e0a67 100644 (file)
@@ -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
index eaef05b50dd81e26ddc28e643ffa390d8326bf21..afadc7c1ed58ef6b2665779bb237ea768ddad30e 100644 (file)
@@ -233,6 +233,9 @@ class TaskTests(test_utils.TestCase):
         self.assertRegex(repr(task),
                          '<Task .* wait_for=%s>' % re.escape(repr(fut)))
 
+        fut.set_result(None)
+        self.loop.run_until_complete(task)
+
     def test_task_basics(self):
         @asyncio.coroutine
         def outer():