import asyncioimport inspectfrom .case import TestCaseclass IsolatedAsyncioTestCase(TestCase):# Names intentionally have a long prefix# to reduce a chance of clashing with user-defined attributes# from inherited test case## The class doesn't call loop.run_until_complete(self.setUp()) and family# but uses a different approach:# 1. create a long-running task that reads self.setUp()# awaitable from queue along with a future# 2. await the awaitable object passing in and set the result# into the future object# 3. Outer code puts the awaitable and the future object into a queue# with waiting for the future# The trick is necessary because every run_until_complete() call# creates a new task with embedded ContextVar context.# To share contextvars between setUp(), test and tearDown() we need to execute# them inside the same task.# Note: the test case modifies event loop policy if the policy was not instantiated# yet.# asyncio.get_event_loop_policy() creates a default policy on demand but never# returns None# I believe this is not an issue in user level tests but python itself for testing# should reset a policy in every test module# by calling asyncio.set_event_loop_policy(None) in tearDownModule()def __init__(self, methodName='runTest'):super().__init__(methodName)self._asyncioTestLoop = Noneself._asyncioCallsQueue = Noneasync def asyncSetUp(self):passasync def asyncTearDown(self):passdef addAsyncCleanup(self, func, /, *args, **kwargs):# A trivial trampoline to addCleanup()# the function exists because it has a different semantics# and signature:# addCleanup() accepts regular functions# but addAsyncCleanup() accepts coroutines## We intentionally don't add inspect.iscoroutinefunction() check# for func argument because there is no way# to check for async function reliably:# 1. It can be "async def func()" iself# 2. Class can implement "async def __call__()" method# 3. Regular "def func()" that returns awaitable objectself.addCleanup(*(func, *args), **kwargs)def _callSetUp(self):self.setUp()self._callAsync(self.asyncSetUp)def _callTestMethod(self, method):self._callMaybeAsync(method)def _callTearDown(self):self._callAsync(self.asyncTearDown)self.tearDown()def _callCleanup(self, function, *args, **kwargs):self._callMaybeAsync(function, *args, **kwargs)def _callAsync(self, func, /, *args, **kwargs):assert self._asyncioTestLoop is not Noneret = func(*args, **kwargs)assert inspect.isawaitable(ret)fut = self._asyncioTestLoop.create_future()self._asyncioCallsQueue.put_nowait((fut, ret))return self._asyncioTestLoop.run_until_complete(fut)def _callMaybeAsync(self, func, /, *args, **kwargs):assert self._asyncioTestLoop is not Noneret = func(*args, **kwargs)if inspect.isawaitable(ret):fut = self._asyncioTestLoop.create_future()self._asyncioCallsQueue.put_nowait((fut, ret))return self._asyncioTestLoop.run_until_complete(fut)else:return retasync def _asyncioLoopRunner(self, fut):self._asyncioCallsQueue = queue = asyncio.Queue()fut.set_result(None)while True:query = await queue.get()queue.task_done()if query is None:returnfut, awaitable = querytry:ret = await awaitableif not fut.cancelled():fut.set_result(ret)except asyncio.CancelledError:raiseexcept Exception as ex:if not fut.cancelled():fut.set_exception(ex)def _setupAsyncioLoop(self):assert self._asyncioTestLoop is Noneloop = asyncio.new_event_loop()asyncio.set_event_loop(loop)loop.set_debug(True)self._asyncioTestLoop = loopfut = loop.create_future()self._asyncioCallsTask = loop.create_task(self._asyncioLoopRunner(fut))loop.run_until_complete(fut)def _tearDownAsyncioLoop(self):assert self._asyncioTestLoop is not Noneloop = self._asyncioTestLoopself._asyncioTestLoop = Noneself._asyncioCallsQueue.put_nowait(None)loop.run_until_complete(self._asyncioCallsQueue.join())try:# cancel all tasksto_cancel = asyncio.all_tasks(loop)if not to_cancel:returnfor task in to_cancel:task.cancel()loop.run_until_complete(asyncio.gather(*to_cancel, loop=loop, return_exceptions=True))for task in to_cancel:if task.cancelled():continueif task.exception() is not None:loop.call_exception_handler({'message': 'unhandled exception during test shutdown','exception': task.exception(),'task': task,})# shutdown asyncgensloop.run_until_complete(loop.shutdown_asyncgens())finally:asyncio.set_event_loop(None)loop.close()def run(self, result=None):self._setupAsyncioLoop()try:return super().run(result)finally:self._tearDownAsyncioLoop()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。