All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Snow <jsnow@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Cleber Rosa" <crosa@redhat.com>, "Ani Sinha" <ani@anisinha.ca>,
	"Warner Losh" <imp@bsdimp.com>,
	"Alex Bennée" <alex.bennee@linaro.org>,
	"Reinoud Zandijk" <reinoud@netbsd.org>,
	"Thomas Huth" <thuth@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"John Snow" <jsnow@redhat.com>, "Ryo ONODERA" <ryoon@netbsd.org>,
	"Kyle Evans" <kevans@freebsd.org>,
	"Beraldo Leal" <bleal@redhat.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Wainer dos Santos Moschetta" <wainersm@redhat.com>,
	"Philippe Mathieu-Daudé" <philmd@linaro.org>
Subject: [RFC PATCH v2 07/10] mkvenv: work around broken pip installations on Debian 10
Date: Fri, 14 Apr 2023 01:54:46 -0400	[thread overview]
Message-ID: <20230414055449.4028284-8-jsnow@redhat.com> (raw)
In-Reply-To: <20230414055449.4028284-1-jsnow@redhat.com>

This is a workaround intended for Debian 10, where the debian-patched
pip does not function correctly if accessed from within a virtual
environment.

We don't support Debian 10 any longer, but it's possible that this bug
might appear on other derivative platforms and this workaround may prove
useful.

RFC, a note from Paolo:

"BTW, another way to repair Debian 10's pip is to create a symbolic link
to sys.base_prefix + '/share/python-wheels' in sys.prefix +
'/share/python-wheels'. Since this is much faster, perhaps it can be
done unconditionally [...] ?"

I was slightly apprehensive about this as it felt "hackier", but it is
indeed a lot less code and much faster. It's probably low-risk. Should
we do that instead, or should we just scrap any fix at all under the
premise that Debian 10 support is dropped anyway?

Signed-off-by: John Snow <jsnow@redhat.com>
---
 python/scripts/mkvenv.py | 61 +++++++++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 17 deletions(-)

diff --git a/python/scripts/mkvenv.py b/python/scripts/mkvenv.py
index 317697a953..6e1a979355 100644
--- a/python/scripts/mkvenv.py
+++ b/python/scripts/mkvenv.py
@@ -103,27 +103,25 @@ def need_ensurepip() -> bool:
     return True
 
 
-def check_ensurepip(with_pip: bool) -> None:
+def check_ensurepip(prefix: str = '', suggest_remedy: bool = False) -> None:
     """
     Check that we have ensurepip.
 
     Raise a fatal exception with a helpful hint if it isn't available.
     """
-    if not with_pip:
-        return
-
     if not find_spec("ensurepip"):
         msg = ("Python's ensurepip module is not found.\n"
 
                "It's normally part of the Python standard library, "
                "maybe your distribution packages it separately?\n"
 
-               "Either install ensurepip, or alleviate the need for it in the "
-               "first place by installing pip and setuptools for "
-               f"'{sys.executable}'.\n"
-
-               "(Hint: Debian puts ensurepip in its python3-venv package.)")
-        raise Ouch(msg)
+               "(Debian puts ensurepip in its python3-venv package.)\n")
+        if suggest_remedy:
+            msg += (
+                "Either install ensurepip, or alleviate the need for it in the "
+                "first place by installing pip and setuptools for "
+                f"'{sys.executable}'.\n")
+        raise Ouch(prefix + msg)
 
     # ensurepip uses pyexpat, which can also go missing on us:
     if not find_spec("pyexpat"):
@@ -132,12 +130,13 @@ def check_ensurepip(with_pip: bool) -> None:
                "It's normally part of the Python standard library, "
                "maybe your distribution packages it separately?\n"
 
-               "Either install pyexpat, or alleviate the need for it in the "
-               "first place by installing pip and setuptools for "
-               f"'{sys.executable}'.\n\n"
-
-               "(Hint: NetBSD's pkgsrc debundles this to e.g. 'py310-expat'.)")
-        raise Ouch(msg)
+               "(NetBSD's pkgsrc debundles this to e.g. 'py310-expat'.)\n")
+        if suggest_remedy:
+            msg += (
+                "Either install pyexpat, or alleviate the need for it in the "
+                "first place by installing pip and setuptools for "
+                f"'{sys.executable}'.\n")
+        raise Ouch(prefix + msg)
 
 
 def make_venv(  # pylint: disable=too-many-arguments
@@ -169,7 +168,8 @@ def make_venv(  # pylint: disable=too-many-arguments
         with_pip = True if not system_site_packages else need_ensurepip()
         logger.debug("with_pip unset, choosing %s", with_pip)
 
-    check_ensurepip(with_pip)
+    if with_pip:
+        check_ensurepip(suggest_remedy=True)
 
     if symlinks is None:
         # Default behavior of standard venv CLI
@@ -349,6 +349,31 @@ def _get_entry_points() -> Iterator[Dict[str, str]]:
         logger.debug("wrote '%s'", script_path)
 
 
+def checkpip():
+    """
+    Debian10 has a pip that's broken when used inside of a virtual environment.
+
+    We try to detect and correct that case here.
+    """
+    try:
+        import pip._internal
+        logger.debug("pip appears to be working correctly.")
+        return
+    except ModuleNotFoundError as exc:
+        if exc.name == 'pip._internal':
+            # Uh, fair enough. They did say "internal".
+            # Let's just assume it's fine.
+            return
+        logger.warning("pip appears to be malfunctioning: %s", str(exc))
+
+    check_ensurepip("pip appears to be non-functional, and ")
+
+    logging.debug("Attempting to repair pip ...")
+    subprocess.run((sys.executable, '-m', 'ensurepip'),
+                   stdout=subprocess.DEVNULL, check=True)
+    logging.debug("Pip is now (hopefully) repaired!")
+
+
 def post_venv_setup(bin_path: str, packages: Sequence[str] = ()) -> None:
     """
     This is intended to be run *inside the venv* after it is created.
@@ -358,6 +383,8 @@ def post_venv_setup(bin_path: str, packages: Sequence[str] = ()) -> None:
                  bin_path, packages)
     generate_console_scripts(python_path, bin_path, packages)
 
+    # Test for a broken pip (Debian 10 or derivative?) and fix it if needed
+    checkpip()
 
 def main() -> int:
     """CLI interface to make_qemu_venv. See module docstring."""
-- 
2.39.2



  parent reply	other threads:[~2023-04-14  5:56 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-14  5:54 [RFC PATCH v2 00/10] configure: create a python venv and install meson John Snow
2023-04-14  5:54 ` [RFC PATCH v2 01/10] python: add mkvenv.py John Snow
2023-04-14  5:54 ` [RFC PATCH v2 02/10] tests: add python3-venv dependency John Snow
2023-04-14 14:17   ` Philippe Mathieu-Daudé
2023-04-14  5:54 ` [RFC PATCH v2 03/10] mkvenv: Add better error message for missing pyexapt module John Snow
2023-04-14  5:54 ` [RFC PATCH v2 04/10] tests/vm: Configure netbsd to use Python 3.10 John Snow
2023-04-14  5:54 ` [RFC PATCH v2 05/10] tests/vm: add py310-expat to NetBSD John Snow
2023-04-14  5:54 ` [RFC PATCH v2 06/10] mkvenv: generate console entry shims from inside the venv John Snow
2023-04-14  5:54 ` John Snow [this message]
2023-04-14  5:54 ` [RFC PATCH v2 08/10] configure: create a python venv unconditionally John Snow
2023-04-14  5:54 ` [RFC PATCH v2 09/10] configure: remove --meson=; install meson to the pyvenv John Snow
2023-04-14  5:54 ` [RFC PATCH v2 10/10] tests: Use configure-provided pyvenv for tests John Snow

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=20230414055449.4028284-8-jsnow@redhat.com \
    --to=jsnow@redhat.com \
    --cc=alex.bennee@linaro.org \
    --cc=ani@anisinha.ca \
    --cc=bleal@redhat.com \
    --cc=crosa@redhat.com \
    --cc=imp@bsdimp.com \
    --cc=kevans@freebsd.org \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=reinoud@netbsd.org \
    --cc=ryoon@netbsd.org \
    --cc=thuth@redhat.com \
    --cc=wainersm@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.