mirror of
https://github.com/python/cpython.git
synced 2024-11-28 20:33:54 +08:00
GH-95097: fix asyncio.run
for tasks without uncancel
method (#95211)
Co-authored-by: Thomas Grainger <tagrain@gmail.com>
This commit is contained in:
parent
bceb197947
commit
54f48844d1
@ -118,10 +118,11 @@ class Runner:
|
|||||||
events.set_event_loop(self._loop)
|
events.set_event_loop(self._loop)
|
||||||
return self._loop.run_until_complete(task)
|
return self._loop.run_until_complete(task)
|
||||||
except exceptions.CancelledError:
|
except exceptions.CancelledError:
|
||||||
if self._interrupt_count > 0 and task.uncancel() == 0:
|
if self._interrupt_count > 0:
|
||||||
raise KeyboardInterrupt()
|
uncancel = getattr(task, "uncancel", None)
|
||||||
else:
|
if uncancel is not None and uncancel() == 0:
|
||||||
raise # CancelledError
|
raise KeyboardInterrupt()
|
||||||
|
raise # CancelledError
|
||||||
finally:
|
finally:
|
||||||
if (sigint_handler is not None
|
if (sigint_handler is not None
|
||||||
and signal.getsignal(signal.SIGINT) is sigint_handler
|
and signal.getsignal(signal.SIGINT) is sigint_handler
|
||||||
|
@ -5,10 +5,9 @@ import re
|
|||||||
import signal
|
import signal
|
||||||
import threading
|
import threading
|
||||||
import unittest
|
import unittest
|
||||||
|
from test.test_asyncio import utils as test_utils
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
from test.test_asyncio import utils as test_utils
|
|
||||||
|
|
||||||
|
|
||||||
def tearDownModule():
|
def tearDownModule():
|
||||||
@ -210,6 +209,54 @@ class RunTests(BaseTest):
|
|||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
self.assertTrue(policy.set_event_loop.called)
|
self.assertTrue(policy.set_event_loop.called)
|
||||||
|
|
||||||
|
def test_asyncio_run_without_uncancel(self):
|
||||||
|
# See https://github.com/python/cpython/issues/95097
|
||||||
|
class Task:
|
||||||
|
def __init__(self, loop, coro, **kwargs):
|
||||||
|
self._task = asyncio.Task(coro, loop=loop, **kwargs)
|
||||||
|
|
||||||
|
def cancel(self, *args, **kwargs):
|
||||||
|
return self._task.cancel(*args, **kwargs)
|
||||||
|
|
||||||
|
def add_done_callback(self, *args, **kwargs):
|
||||||
|
return self._task.add_done_callback(*args, **kwargs)
|
||||||
|
|
||||||
|
def remove_done_callback(self, *args, **kwargs):
|
||||||
|
return self._task.remove_done_callback(*args, **kwargs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _asyncio_future_blocking(self):
|
||||||
|
return self._task._asyncio_future_blocking
|
||||||
|
|
||||||
|
def result(self, *args, **kwargs):
|
||||||
|
return self._task.result(*args, **kwargs)
|
||||||
|
|
||||||
|
def done(self, *args, **kwargs):
|
||||||
|
return self._task.done(*args, **kwargs)
|
||||||
|
|
||||||
|
def cancelled(self, *args, **kwargs):
|
||||||
|
return self._task.cancelled(*args, **kwargs)
|
||||||
|
|
||||||
|
def exception(self, *args, **kwargs):
|
||||||
|
return self._task.exception(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_loop(self, *args, **kwargs):
|
||||||
|
return self._task.get_loop(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
interrupt_self()
|
||||||
|
await asyncio.Event().wait()
|
||||||
|
|
||||||
|
def new_event_loop():
|
||||||
|
loop = self.new_loop()
|
||||||
|
loop.set_task_factory(Task)
|
||||||
|
return loop
|
||||||
|
|
||||||
|
asyncio.set_event_loop_policy(TestPolicy(new_event_loop))
|
||||||
|
with self.assertRaises(asyncio.CancelledError):
|
||||||
|
asyncio.run(main())
|
||||||
|
|
||||||
|
|
||||||
class RunnerTests(BaseTest):
|
class RunnerTests(BaseTest):
|
||||||
|
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
Fix :func:`asyncio.run` for :class:`asyncio.Task` implementations without :meth:`~asyncio.Task.uncancel` method. Patch by Kumar Aditya.
|
Loading…
Reference in New Issue
Block a user