https://github.com/python/cpython/commit/d89283b3e7591c0a6cac8f22efbb5862ba83c431
commit: d89283b3e7591c0a6cac8f22efbb5862ba83c431
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: asvetlov <[email protected]>
date: 2024-10-28T15:25:00+01:00
summary:

[3.12] gh-124594: Create and reuse the same context for the entire asyncio REPL 
session (GH-124595) (#124849)

* gh-124594: Create and reuse the same context for the entire asyncio REPL 
session (GH-124595)
(cherry picked from commit 67e01a430f4ecfcb540d6a29b347966ff4e53454)

Co-authored-by: Bartosz Sławecki <[email protected]>
Co-authored-by: Andrew Svetlov <[email protected]>


---------

Co-authored-by: Bartosz Sławecki <[email protected]>
Co-authored-by: Andrew Svetlov <[email protected]>

files:
A Misc/NEWS.d/next/Library/2024-09-26-13-43-39.gh-issue-124594.peYhsP.rst
M Lib/asyncio/__main__.py
M Lib/test/test_repl.py

diff --git a/Lib/asyncio/__main__.py b/Lib/asyncio/__main__.py
index 046558011513cb..29e528aeed754f 100644
--- a/Lib/asyncio/__main__.py
+++ b/Lib/asyncio/__main__.py
@@ -2,6 +2,7 @@
 import asyncio
 import code
 import concurrent.futures
+import contextvars
 import inspect
 import sys
 import threading
@@ -17,6 +18,7 @@ def __init__(self, locals, loop):
         super().__init__(locals)
         self.compile.compiler.flags |= ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
         self.loop = loop
+        self.context = contextvars.copy_context()
 
     def runcode(self, code):
         future = concurrent.futures.Future()
@@ -46,12 +48,12 @@ def callback():
                 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 ddb4aa68048df1..f2f18a2581cb13 100644
--- a/Lib/test/test_repl.py
+++ b/Lib/test/test_repl.py
@@ -146,5 +146,42 @@ def f():
         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+"\n")
+        user_input2 = "async def set_var(): var.set('ok')\n"
+        p.stdin.write(user_input2+"\n")
+        user_input3 = "await set_var()\n"
+        p.stdin.write(user_input3+"\n")
+        user_input4 = "print(f'toplevel contextvar test: {var.get()}')\n"
+        p.stdin.write(user_input4+"\n")
+        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 00000000000000..ac48bd84930745
--- /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.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to