summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-07-08 09:29:25 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-07-08 09:29:25 (GMT)
commit896a25ab30269369201401b50c66130911dd2238 (patch)
tree8b80add7a57b99a1e625585194cc5a8afc8a4bc3
parent630a4f63c539345a6432d6177931b5fcc2f18aa7 (diff)
downloadcpython-896a25ab30269369201401b50c66130911dd2238.zip
cpython-896a25ab30269369201401b50c66130911dd2238.tar.gz
cpython-896a25ab30269369201401b50c66130911dd2238.tar.bz2
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
-rw-r--r--Lib/asyncio/base_events.py6
-rw-r--r--Lib/asyncio/events.py9
-rw-r--r--Lib/asyncio/streams.py2
-rw-r--r--Lib/asyncio/tasks.py4
-rw-r--r--Lib/asyncio/test_utils.py2
-rw-r--r--Lib/test/test_asyncio/test_base_events.py24
-rw-r--r--Lib/test/test_asyncio/test_events.py14
-rw-r--r--Lib/test/test_asyncio/test_futures.py4
-rw-r--r--Lib/test/test_asyncio/test_tasks.py3
9 files changed, 63 insertions, 5 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 2230dc2..52c5517 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 b389cfb..1f5e582 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 a10b969..9bde218 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 8c7217b..befc296 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 ef3be23..6abcaf1 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 adba082..f6da7c3 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 beb6cec..b89416f 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -1969,8 +1969,12 @@ class AbstractEventLoopTests(unittest.TestCase):
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(
NotImplementedError, loop.call_at, f, f)
@@ -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 a6071ea..157adb7 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 eaef05b..afadc7c 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),
'<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():