diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2014-12-04 22:08:37 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2014-12-04 22:08:37 (GMT) |
commit | d5ea5d528a5bd356b1204ba8ac2bb9d27be0ac02 (patch) | |
tree | 57d44af2d2e27d4da49dad23be9b4cfef86afa71 | |
parent | 74aee426c166241c8c0f2a64d22e0b4b9e53443b (diff) | |
parent | e80bf0d4a996b3ecda2c2f3cbab10037b9fdcd5e (diff) | |
download | cpython-d5ea5d528a5bd356b1204ba8ac2bb9d27be0ac02.zip cpython-d5ea5d528a5bd356b1204ba8ac2bb9d27be0ac02.tar.gz cpython-d5ea5d528a5bd356b1204ba8ac2bb9d27be0ac02.tar.bz2 |
Merge 3.4 (asyncio)
-rw-r--r-- | Lib/asyncio/base_events.py | 4 | ||||
-rw-r--r-- | Lib/asyncio/futures.py | 3 | ||||
-rw-r--r-- | Lib/asyncio/tasks.py | 7 | ||||
-rw-r--r-- | Lib/asyncio/unix_events.py | 1 | ||||
-rw-r--r-- | Lib/test/test_asyncio/test_events.py | 35 |
5 files changed, 44 insertions, 6 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 40dd668..7c38b09 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -177,6 +177,7 @@ class BaseEventLoop(events.AbstractEventLoop): Return a task object. """ + self._check_closed() task = tasks.Task(coro, loop=self) if task._source_traceback: del task._source_traceback[-1] @@ -360,6 +361,7 @@ class BaseEventLoop(events.AbstractEventLoop): if (coroutines.iscoroutine(callback) or coroutines.iscoroutinefunction(callback)): raise TypeError("coroutines cannot be used with call_at()") + self._check_closed() if self._debug: self._assert_is_current_event_loop() timer = events.TimerHandle(when, callback, args, self) @@ -390,6 +392,7 @@ class BaseEventLoop(events.AbstractEventLoop): raise TypeError("coroutines cannot be used with call_soon()") if self._debug and check_loop: self._assert_is_current_event_loop() + self._check_closed() handle = events.Handle(callback, args, self) if handle._source_traceback: del handle._source_traceback[-1] @@ -426,6 +429,7 @@ class BaseEventLoop(events.AbstractEventLoop): if (coroutines.iscoroutine(callback) or coroutines.iscoroutinefunction(callback)): raise TypeError("coroutines cannot be used with run_in_executor()") + self._check_closed() if isinstance(callback, events.Handle): assert not args assert not isinstance(callback, events.TimerHandle) diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 19e7918..f46d008 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -135,6 +135,7 @@ class Future: _result = None _exception = None _loop = None + _source_traceback = None _blocking = False # proper use of future (yield vs yield from) @@ -155,8 +156,6 @@ class Future: self._callbacks = [] if self._loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1)) - else: - self._source_traceback = None def _format_callbacks(self): cb = self._callbacks diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index a2128c5..9aebffd 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -41,6 +41,10 @@ class Task(futures.Future): # all running event loops. {EventLoop: Task} _current_tasks = {} + # If False, don't log a message if the task is destroyed whereas its + # status is still pending + _log_destroy_pending = True + @classmethod def current_task(cls, loop=None): """Return the currently running task in an event loop or None. @@ -73,9 +77,6 @@ class Task(futures.Future): self._must_cancel = False self._loop.call_soon(self._step) self.__class__._all_tasks.add(self) - # If False, don't log a message if the task is destroyed whereas its - # status is still pending - self._log_destroy_pending = True # On Python 3.3 or older, objects with a destructor that are part of a # reference cycle are never destroyed. That's not the case any more on diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index efe06d4..d5db4d5 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -71,6 +71,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): or coroutines.iscoroutinefunction(callback)): raise TypeError("coroutines cannot be used with add_signal_handler()") self._check_signal(sig) + self._check_closed() try: # set_wakeup_fd() raises ValueError if this is not the # main thread. By calling it early we ensure that an diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index ea657fd..6644fbe 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -226,7 +226,8 @@ class EventLoopTestsMixin: def tearDown(self): # just in case if we have transport close callbacks - test_utils.run_briefly(self.loop) + if not self.loop.is_closed(): + test_utils.run_briefly(self.loop) self.loop.close() gc.collect() @@ -1434,6 +1435,38 @@ class EventLoopTestsMixin: with self.assertRaises(RuntimeError): self.loop.run_until_complete(coro) + def test_close(self): + self.loop.close() + + @asyncio.coroutine + def test(): + pass + + func = lambda: False + coro = test() + self.addCleanup(coro.close) + + # operation blocked when the loop is closed + with self.assertRaises(RuntimeError): + self.loop.run_forever() + with self.assertRaises(RuntimeError): + fut = asyncio.Future(loop=self.loop) + self.loop.run_until_complete(fut) + with self.assertRaises(RuntimeError): + self.loop.call_soon(func) + with self.assertRaises(RuntimeError): + self.loop.call_soon_threadsafe(func) + with self.assertRaises(RuntimeError): + self.loop.call_later(1.0, func) + with self.assertRaises(RuntimeError): + self.loop.call_at(self.loop.time() + .0, func) + with self.assertRaises(RuntimeError): + self.loop.run_in_executor(None, func) + with self.assertRaises(RuntimeError): + self.loop.create_task(coro) + with self.assertRaises(RuntimeError): + self.loop.add_signal_handler(signal.SIGTERM, func) + class SubprocessTestsMixin: |