summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/asyncio/__main__.py6
-rw-r--r--Lib/test/test_repl.py37
-rw-r--r--Misc/NEWS.d/next/Library/2024-09-26-13-43-39.gh-issue-124594.peYhsP.rst1
3 files changed, 42 insertions, 2 deletions
diff --git a/Lib/asyncio/__main__.py b/Lib/asyncio/__main__.py
index 5120140..95c636f 100644
--- a/Lib/asyncio/__main__.py
+++ b/Lib/asyncio/__main__.py
@@ -1,6 +1,7 @@
import ast
import asyncio
import concurrent.futures
+import contextvars
import inspect
import os
import site
@@ -22,6 +23,7 @@ class AsyncIOInteractiveConsole(InteractiveColoredConsole):
self.compile.compiler.flags |= ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
self.loop = loop
+ self.context = contextvars.copy_context()
def runcode(self, code):
global return_code
@@ -55,12 +57,12 @@ class AsyncIOInteractiveConsole(InteractiveColoredConsole):
return
try:
- repl_future = self.loop.create_task(coro)
+ repl_future = self.loop.create_task(coro, context=self.context)
futures._chain_future(repl_future, future)
except BaseException as exc:
future.set_exception(exc)
- loop.call_soon_threadsafe(callback)
+ loop.call_soon_threadsafe(callback, context=self.context)
try:
return future.result()
diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py
index 7a7285a..e764e60 100644
--- a/Lib/test/test_repl.py
+++ b/Lib/test/test_repl.py
@@ -291,5 +291,42 @@ class TestInteractiveModeSyntaxErrors(unittest.TestCase):
self.assertEqual(traceback_lines, expected_lines)
+class TestAsyncioREPLContextVars(unittest.TestCase):
+ def test_toplevel_contextvars_sync(self):
+ user_input = dedent("""\
+ from contextvars import ContextVar
+ var = ContextVar("var", default="failed")
+ var.set("ok")
+ """)
+ p = spawn_repl("-m", "asyncio")
+ p.stdin.write(user_input)
+ user_input2 = dedent("""
+ print(f"toplevel contextvar test: {var.get()}")
+ """)
+ p.stdin.write(user_input2)
+ output = kill_python(p)
+ self.assertEqual(p.returncode, 0)
+ expected = "toplevel contextvar test: ok"
+ self.assertIn(expected, output, expected)
+
+ def test_toplevel_contextvars_async(self):
+ user_input = dedent("""\
+ from contextvars import ContextVar
+ var = ContextVar('var', default='failed')
+ """)
+ p = spawn_repl("-m", "asyncio")
+ p.stdin.write(user_input)
+ user_input2 = "async def set_var(): var.set('ok')\n"
+ p.stdin.write(user_input2)
+ user_input3 = "await set_var()\n"
+ p.stdin.write(user_input3)
+ user_input4 = "print(f'toplevel contextvar test: {var.get()}')\n"
+ p.stdin.write(user_input4)
+ output = kill_python(p)
+ self.assertEqual(p.returncode, 0)
+ expected = "toplevel contextvar test: ok"
+ self.assertIn(expected, output, expected)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2024-09-26-13-43-39.gh-issue-124594.peYhsP.rst b/Misc/NEWS.d/next/Library/2024-09-26-13-43-39.gh-issue-124594.peYhsP.rst
new file mode 100644
index 0000000..ac48bd8
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-09-26-13-43-39.gh-issue-124594.peYhsP.rst
@@ -0,0 +1 @@
+All :mod:`asyncio` REPL prompts run in the same :class:`context <contextvars.Context>`. Contributed by Bartosz SÅ‚awecki.