|
11 | 11 | # under the License.
|
12 | 12 |
|
13 | 13 | import asyncio
|
| 14 | +import contextvars |
14 | 15 | import threading
|
15 | 16 | import time
|
16 | 17 | import unittest
|
|
25 | 26 | to_asyncio_future,
|
26 | 27 | AddThreadSelectorEventLoop,
|
27 | 28 | )
|
28 |
| -from tornado.testing import AsyncTestCase, gen_test, setup_with_context_manager |
| 29 | +from tornado.testing import ( |
| 30 | + AsyncTestCase, |
| 31 | + gen_test, |
| 32 | + setup_with_context_manager, |
| 33 | + AsyncHTTPTestCase, |
| 34 | +) |
29 | 35 | from tornado.test.util import ignore_deprecation
|
| 36 | +from tornado.web import Application, RequestHandler |
30 | 37 |
|
31 | 38 |
|
32 | 39 | class AsyncIOLoopTest(AsyncTestCase):
|
@@ -261,3 +268,31 @@ def test_tornado_accessor(self):
|
261 | 268 | asyncio.set_event_loop_policy(self.AnyThreadEventLoopPolicy())
|
262 | 269 | self.assertIsInstance(self.executor.submit(IOLoop.current).result(), IOLoop)
|
263 | 270 | self.executor.submit(lambda: asyncio.get_event_loop().close()).result() # type: ignore
|
| 271 | + |
| 272 | + |
| 273 | +class SelectorThreadContextvarsTest(AsyncHTTPTestCase): |
| 274 | + ctx_value = "foo" |
| 275 | + test_endpoint = "/" |
| 276 | + tornado_test_ctx = contextvars.ContextVar("tornado_test_ctx", default="default") |
| 277 | + tornado_test_ctx.set(ctx_value) |
| 278 | + |
| 279 | + def get_app(self) -> Application: |
| 280 | + tornado_test_ctx = self.tornado_test_ctx |
| 281 | + |
| 282 | + class Handler(RequestHandler): |
| 283 | + async def get(self): |
| 284 | + # On the Windows platform, |
| 285 | + # when a asyncio.events.Handle is created |
| 286 | + # in the SelectorThread without providing a context, |
| 287 | + # it will copy the current thread's context, |
| 288 | + # which can lead to the loss of the main thread's context |
| 289 | + # when executing the handle. |
| 290 | + # Therefore, it is necessary to |
| 291 | + # save a copy of the main thread's context in the SelectorThread |
| 292 | + # for creating the handle. |
| 293 | + self.write(tornado_test_ctx.get()) |
| 294 | + |
| 295 | + return Application([(self.test_endpoint, Handler)]) |
| 296 | + |
| 297 | + def test_context_vars(self): |
| 298 | + self.assertEqual(self.ctx_value, self.fetch(self.test_endpoint).body.decode()) |
0 commit comments