From f9d2e0a3bd7ba2a693a892881f91cf53fa90cc71 Mon Sep 17 00:00:00 2001 From: John Snow Date: Tue, 6 Jun 2023 13:19:11 -0400 Subject: python: backport 'drop Python3.6 workarounds' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the minimum version is 3.7, drop some of the 3.6-specific hacks we've been carrying. A single remaining compatibility hack concerning 3.6's lack of @asynccontextmanager is addressed in the following commit. Signed-off-by: John Snow cherry picked from commit python-qemu-qmp@3e8e34e594cfc6b707e6f67959166acde4b421b8 Signed-off-by: John Snow Reviewed-by: Daniel P. Berrangé --- python/tests/protocol.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'python/tests/protocol.py') diff --git a/python/tests/protocol.py b/python/tests/protocol.py index 56c4d441f9..c254c77b17 100644 --- a/python/tests/protocol.py +++ b/python/tests/protocol.py @@ -8,7 +8,6 @@ import avocado from qemu.qmp import ConnectError, Runstate from qemu.qmp.protocol import AsyncProtocol, StateError -from qemu.qmp.util import asyncio_run, create_task class NullProtocol(AsyncProtocol[None]): @@ -124,7 +123,7 @@ def run_as_task(coro, allow_cancellation=False): if allow_cancellation: return raise - return create_task(_runner()) + return asyncio.create_task(_runner()) @contextmanager @@ -271,7 +270,7 @@ class TestBase(avocado.Test): msg=f"Expected state '{state.name}'", ) - self.runstate_watcher = create_task(_watcher()) + self.runstate_watcher = asyncio.create_task(_watcher()) # Kick the loop and force the task to block on the event. await asyncio.sleep(0) @@ -589,7 +588,8 @@ class SimpleSession(TestBase): async def testSmoke(self): with TemporaryDirectory(suffix='.qmp') as tmpdir: sock = os.path.join(tmpdir, type(self.proto).__name__ + ".sock") - server_task = create_task(self.server.start_server_and_accept(sock)) + server_task = asyncio.create_task( + self.server.start_server_and_accept(sock)) # give the server a chance to start listening [...] await asyncio.sleep(0) -- cgit 1.4.1 From 5d99044d09db0fa8c2b3294e301927118f9effc9 Mon Sep 17 00:00:00 2001 From: John Snow Date: Tue, 13 Aug 2024 09:35:30 -0400 Subject: python: backport 'Remove deprecated get_event_loop calls' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This method was deprecated in 3.12 because it ordinarily should not be used from coroutines; if there is not a currently running event loop, this automatically creates a new event loop - which is usually not what you want from code that would ever run in the bottom half. In our case, we do want this behavior in two places: (1) The synchronous shim, for convenience: this allows fully sync programs to use QEMUMonitorProtocol() without needing to set up an event loop beforehand. This is intentional to fully box in the async complexities into the legacy sync shim. (2) The qmp_tui shell; instead of relying on asyncio.run to create and run an asyncio program, we need to be able to pass the current asyncio loop to urwid setup functions. For convenience, again, we create one if one is not present to simplify the creation of the TUI appliance. The remaining user of get_event_loop() was in fact one of the erroneous users that should not have been using this function: if there's no running event loop inside of a coroutine, you're in big trouble :) Signed-off-by: John Snow cherry picked from commit python-qemu-qmp@aa1ff9907603a3033296027e1bd021133df86ef1 Signed-off-by: John Snow Reviewed-by: Daniel P. Berrangé --- python/qemu/qmp/legacy.py | 9 ++++++++- python/qemu/qmp/qmp_tui.py | 7 ++++++- python/tests/protocol.py | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'python/tests/protocol.py') diff --git a/python/qemu/qmp/legacy.py b/python/qemu/qmp/legacy.py index c8d0a29b56..735d42971e 100644 --- a/python/qemu/qmp/legacy.py +++ b/python/qemu/qmp/legacy.py @@ -86,7 +86,14 @@ class QEMUMonitorProtocol: "server argument should be False when passing a socket") self._qmp = QMPClient(nickname) - self._aloop = asyncio.get_event_loop() + + try: + self._aloop = asyncio.get_running_loop() + except RuntimeError: + # No running loop; since this is a sync shim likely to be + # used in fully sync programs, create one if neccessary. + self._aloop = asyncio.get_event_loop_policy().get_event_loop() + self._address = address self._timeout: Optional[float] = None diff --git a/python/qemu/qmp/qmp_tui.py b/python/qemu/qmp/qmp_tui.py index 53ea6c59a7..12bdc17c99 100644 --- a/python/qemu/qmp/qmp_tui.py +++ b/python/qemu/qmp/qmp_tui.py @@ -388,7 +388,12 @@ class App(QMPClient): screen = urwid.raw_display.Screen() screen.set_terminal_properties(256) - self.aloop = asyncio.get_event_loop() + try: + self.aloop = asyncio.get_running_loop() + except RuntimeError: + # No running asyncio event loop. Create one if necessary. + self.aloop = asyncio.get_event_loop_policy().get_event_loop() + self.aloop.set_debug(debug) # Gracefully handle SIGTERM and SIGINT signals diff --git a/python/tests/protocol.py b/python/tests/protocol.py index c254c77b17..e565802516 100644 --- a/python/tests/protocol.py +++ b/python/tests/protocol.py @@ -227,7 +227,7 @@ class TestBase(avocado.Test): Decorator; adds SetUp and TearDown to async tests. """ async def _wrapper(self, *args, **kwargs): - loop = asyncio.get_event_loop() + loop = asyncio.get_running_loop() loop.set_debug(True) await self._asyncSetUp() -- cgit 1.4.1