All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	"Thomas Huth" <thuth@redhat.com>,
	"Daniel Berrange" <berrange@redhat.com>,
	"Eduardo Habkost" <ehabkost@redhat.com>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Wainer dos Santos Moschetta" <wainersm@redhat.com>,
	"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
	"Willian Rampazzo" <willianr@redhat.com>,
	"Cleber Rosa" <crosa@redhat.com>, "John Snow" <jsnow@redhat.com>
Subject: [PULL 04/32] python/aqmp: add asyncio compatibility wrappers
Date: Mon, 27 Sep 2021 15:24:45 -0400	[thread overview]
Message-ID: <20210927192513.744199-5-jsnow@redhat.com> (raw)
In-Reply-To: <20210927192513.744199-1-jsnow@redhat.com>

Python 3.6 does not have all of the goodies that Python 3.7 does, and we
need to support both. Add some compatibility wrappers needed for this
purpose.

(Note: Python 3.6 is EOL December 2021.)

Signed-off-by: John Snow <jsnow@redhat.com>
Message-id: 20210915162955.333025-5-jsnow@redhat.com
Signed-off-by: John Snow <jsnow@redhat.com>
---
 python/qemu/aqmp/util.py | 89 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 python/qemu/aqmp/util.py

diff --git a/python/qemu/aqmp/util.py b/python/qemu/aqmp/util.py
new file mode 100644
index 00000000000..28acd995dbf
--- /dev/null
+++ b/python/qemu/aqmp/util.py
@@ -0,0 +1,89 @@
+"""
+Miscellaneous Utilities
+
+This module provides asyncio utilities and compatibility wrappers for
+Python 3.6 to provide some features that otherwise become available in
+Python 3.7+.
+"""
+
+import asyncio
+import sys
+from typing import (
+    Any,
+    Coroutine,
+    Optional,
+    TypeVar,
+)
+
+
+T = TypeVar('T')
+
+
+# -------------------------------
+# Section: Compatibility Wrappers
+# -------------------------------
+
+
+def create_task(coro: Coroutine[Any, Any, T],
+                loop: Optional[asyncio.AbstractEventLoop] = None
+                ) -> 'asyncio.Future[T]':
+    """
+    Python 3.6-compatible `asyncio.create_task` wrapper.
+
+    :param coro: The coroutine to execute in a task.
+    :param loop: Optionally, the loop to create the task in.
+
+    :return: An `asyncio.Future` object.
+    """
+    if sys.version_info >= (3, 7):
+        if loop is not None:
+            return loop.create_task(coro)
+        return asyncio.create_task(coro)  # pylint: disable=no-member
+
+    # Python 3.6:
+    return asyncio.ensure_future(coro, loop=loop)
+
+
+def is_closing(writer: asyncio.StreamWriter) -> bool:
+    """
+    Python 3.6-compatible `asyncio.StreamWriter.is_closing` wrapper.
+
+    :param writer: The `asyncio.StreamWriter` object.
+    :return: `True` if the writer is closing, or closed.
+    """
+    if sys.version_info >= (3, 7):
+        return writer.is_closing()
+
+    # Python 3.6:
+    transport = writer.transport
+    assert isinstance(transport, asyncio.WriteTransport)
+    return transport.is_closing()
+
+
+async def wait_closed(writer: asyncio.StreamWriter) -> None:
+    """
+    Python 3.6-compatible `asyncio.StreamWriter.wait_closed` wrapper.
+
+    :param writer: The `asyncio.StreamWriter` to wait on.
+    """
+    if sys.version_info >= (3, 7):
+        await writer.wait_closed()
+        return
+
+    # Python 3.6
+    transport = writer.transport
+    assert isinstance(transport, asyncio.WriteTransport)
+
+    while not transport.is_closing():
+        await asyncio.sleep(0)
+
+    # This is an ugly workaround, but it's the best I can come up with.
+    sock = transport.get_extra_info('socket')
+
+    if sock is None:
+        # Our transport doesn't have a socket? ...
+        # Nothing we can reasonably do.
+        return
+
+    while sock.fileno() != -1:
+        await asyncio.sleep(0)
-- 
2.31.1



  parent reply	other threads:[~2021-09-27 19:32 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-27 19:24 [PULL 00/32] Python patches John Snow
2021-09-27 19:24 ` [PULL 01/32] python/aqmp: add asynchronous QMP (AQMP) subpackage John Snow
2021-09-27 19:24 ` [PULL 02/32] python/aqmp: add error classes John Snow
2021-09-27 19:24 ` [PULL 03/32] python/pylint: Add exception for TypeVar names ('T') John Snow
2021-09-27 19:24 ` John Snow [this message]
2021-09-27 19:24 ` [PULL 05/32] python/aqmp: add generic async message-based protocol support John Snow
2021-09-27 19:24 ` [PULL 06/32] python/aqmp: add runstate state machine to AsyncProtocol John Snow
2021-09-27 19:24 ` [PULL 07/32] python/aqmp: Add logging utility helpers John Snow
2021-09-27 19:24 ` [PULL 08/32] python/aqmp: add logging to AsyncProtocol John Snow
2021-09-27 19:24 ` [PULL 09/32] python/aqmp: add AsyncProtocol.accept() method John Snow
2021-09-27 19:24 ` [PULL 10/32] python/aqmp: add configurable read buffer limit John Snow
2021-09-27 19:24 ` [PULL 11/32] python/aqmp: add _cb_inbound and _cb_outbound logging hooks John Snow
2021-09-27 19:24 ` [PULL 12/32] python/aqmp: add AsyncProtocol._readline() method John Snow
2021-09-27 19:24 ` [PULL 13/32] python/aqmp: add QMP Message format John Snow
2021-09-27 19:24 ` [PULL 14/32] python/aqmp: add well-known QMP object models John Snow
2021-09-27 19:24 ` [PULL 15/32] python/aqmp: add QMP event support John Snow
2021-09-27 19:24 ` [PULL 16/32] python/pylint: disable too-many-function-args John Snow
2021-09-27 19:24 ` [PULL 17/32] python/aqmp: add QMP protocol support John Snow
2021-09-27 19:24 ` [PULL 18/32] python/pylint: disable no-member check John Snow
2021-09-27 19:25 ` [PULL 19/32] python/aqmp: Add message routing to QMP protocol John Snow
2021-09-27 19:25 ` [PULL 20/32] python/aqmp: add execute() interfaces John Snow
2021-09-27 19:25 ` [PULL 21/32] python/aqmp: add _raw() execution interface John Snow
2021-09-27 19:25 ` [PULL 22/32] python/aqmp: add asyncio_run compatibility wrapper John Snow
2021-09-27 19:25 ` [PULL 23/32] python/aqmp: add scary message John Snow
2021-09-27 19:25 ` [PULL 24/32] python: bump avocado to v90.0 John Snow
2021-09-27 19:25 ` [PULL 25/32] python/aqmp: add AsyncProtocol unit tests John Snow
2021-09-27 19:25 ` [PULL 26/32] python/aqmp: add LineProtocol tests John Snow
2021-09-27 19:25 ` [PULL 27/32] python/aqmp: Add Coverage.py support John Snow
2021-09-27 19:25 ` [PULL 28/32] python: Add dependencies for AQMP TUI John Snow
2021-09-27 19:25 ` [PULL 29/32] python/aqmp-tui: Add " John Snow
2021-09-27 19:25 ` [PULL 30/32] python: Add entry point for aqmp-tui John Snow
2021-09-27 19:25 ` [PULL 31/32] python: add optional pygments dependency John Snow
2021-09-27 19:25 ` [PULL 32/32] python/aqmp-tui: Add syntax highlighting John Snow
2021-09-28 14:37 ` [PULL 00/32] Python patches Peter Maydell

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=20210927192513.744199-5-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=alex.bennee@linaro.org \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=crosa@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=f4bug@amsat.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=thuth@redhat.com \
    --cc=wainersm@redhat.com \
    --cc=willianr@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.