All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Daniel P. Berrangé" <berrange@redhat.com>
To: "Richard W.M. Jones" <rjones@redhat.com>
Cc: jsnow@redhat.com, crosa@redhat.com, qemu-devel@nongnu.org,
	mhroncok@redhat.com
Subject: Re: [PATCH] python: Replace asyncio.get_event_loop for Python 3.14
Date: Tue, 15 Jul 2025 12:19:39 +0100	[thread overview]
Message-ID: <aHY5S17NO42FanTs@redhat.com> (raw)
In-Reply-To: <20250715105113.623604-1-rjones@redhat.com>

On Tue, Jul 15, 2025 at 11:51:10AM +0100, Richard W.M. Jones wrote:
> In Python 3.14, no asyncio event loop gets generated automatically.
> Instead create one when we need it.  This should work with Python 3.13
> as well.  This is a mechanical change as suggested here:
> 
> https://bugzilla.redhat.com/show_bug.cgi?id=2375004#c4
> 
> See-also: https://docs.python.org/3.14/whatsnew/3.14.html#id7
> Thanks: Miro Hrončok
> Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
> ---
>  python/qemu/qmp/legacy.py  | 5 ++++-
>  python/qemu/qmp/qmp_tui.py | 5 ++++-
>  python/qemu/qmp/util.py    | 5 ++++-
>  python/tests/protocol.py   | 5 ++++-
>  4 files changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/python/qemu/qmp/legacy.py b/python/qemu/qmp/legacy.py
> index 22a2b5616e..e11d05afbd 100644
> --- a/python/qemu/qmp/legacy.py
> +++ b/python/qemu/qmp/legacy.py
> @@ -86,7 +86,10 @@ def __init__(self,
>                  "server argument should be False when passing a socket")
>  
>          self._qmp = QMPClient(nickname)
> -        self._aloop = asyncio.get_event_loop()
> +        try:
> +            self._aloop = asyncio.get_event_loop()
> +        except RuntimeError:
> +            self._aloop = asyncio.new_event_loop()
>          self._address = address
>          self._timeout: Optional[float] = None
>

The usage contract of QEMUMonitorProtocol is sufficiently ill
defined that we probably have to expect the caller might have
arranged for a specific event loop to be set against the
thread, so the try/except dance is likely required.


> diff --git a/python/qemu/qmp/qmp_tui.py b/python/qemu/qmp/qmp_tui.py
> index 2d9ebbd20b..84c5da4e66 100644
> --- a/python/qemu/qmp/qmp_tui.py
> +++ b/python/qemu/qmp/qmp_tui.py
> @@ -377,7 +377,10 @@ def run(self, debug: bool = False) -> None:
>          screen = urwid.raw_display.Screen()
>          screen.set_terminal_properties(256)
>  
> -        self.aloop = asyncio.get_event_loop()
> +        try:
> +            self.aloop = asyncio.get_event_loop()
> +        except RuntimeError:
> +            self.aloop = asyncio.new_event_loop()
>          self.aloop.set_debug(debug)
>  
>          # Gracefully handle SIGTERM and SIGINT signals

I'm somewhat inclined to say that this "App" class should
always use asyncio.new_event_loop, as the usge model is
for running a self contained QMP application. I don't
expect we should need to integrate with code that has
set an event loop against the thread.

> diff --git a/python/qemu/qmp/util.py b/python/qemu/qmp/util.py
> index ca6225e9cd..8f9f849a5f 100644
> --- a/python/qemu/qmp/util.py
> +++ b/python/qemu/qmp/util.py
> @@ -160,7 +160,10 @@ def asyncio_run(coro: Coroutine[Any, Any, T], *, debug: bool = False) -> T:
>          return asyncio.run(coro, debug=debug)
>  
>      # Python 3.6
> -    loop = asyncio.get_event_loop()
> +    try:
> +        loop = asyncio.get_event_loop()
> +    except RuntimeError:
> +        loop = asyncio.new_event_loop()
>      loop.set_debug(debug)
>      ret = loop.run_until_complete(coro)
>      loop.close()

This change is not requred as this code path only runs with
Python <= 3.6. In fact it is dead code given we only support
python >= 3.9.

I'm prepping a patch to kill all py 3.6 compat code.

> diff --git a/python/tests/protocol.py b/python/tests/protocol.py
> index 56c4d441f9..aa7c0e4397 100644
> --- a/python/tests/protocol.py
> +++ b/python/tests/protocol.py
> @@ -228,7 +228,10 @@ def async_test(async_test_method):
>          Decorator; adds SetUp and TearDown to async tests.
>          """
>          async def _wrapper(self, *args, **kwargs):
> -            loop = asyncio.get_event_loop()
> +            try:
> +                loop = asyncio.get_event_loop()
> +            except RuntimeError:
> +                loop = asyncio.new_event_loop()
>              loop.set_debug(True)

For the usage model here we should exclusively use
asyncio.new_event_loop(). This is a test decorator
so it is impossible for an existing event loop to be
set against the thread.

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



      parent reply	other threads:[~2025-07-15 11:21 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-15 10:51 [PATCH] python: Replace asyncio.get_event_loop for Python 3.14 Richard W.M. Jones
2025-07-15 10:54 ` Miro Hrončok
2025-07-15 10:56   ` Richard W.M. Jones
2025-07-15 11:19 ` Daniel P. Berrangé [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aHY5S17NO42FanTs@redhat.com \
    --to=berrange@redhat.com \
    --cc=crosa@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=mhroncok@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rjones@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.