rdobuilder 039007
From da9ce1c9d7d422e310d79d58a8b7ed07cbc781d1 Mon Sep 17 00:00:00 2001
ecb620
From: Lumir Balhar <lbalhar@redhat.com>
ecb620
Date: Thu, 9 Feb 2023 15:13:36 +0100
ecb620
Subject: [PATCH] RPM wheels
ecb620
MIME-Version: 1.0
ecb620
Content-Type: text/plain; charset=UTF-8
ecb620
Content-Transfer-Encoding: 8bit
ecb620
ecb620
Co-Authored-By: Miro HronĨok <miro@hroncok.cz>
ecb620
---
ecb620
 src/virtualenv/run/__init__.py                |  5 +++--
ecb620
 src/virtualenv/seed/embed/base_embed.py       | 16 +++++++++++++-
ecb620
 src/virtualenv/seed/embed/pip_invoke.py       |  1 +
ecb620
 .../seed/embed/via_app_data/via_app_data.py   |  1 +
ecb620
 src/virtualenv/seed/wheels/acquire.py         |  3 ++-
ecb620
 src/virtualenv/seed/wheels/embed/__init__.py  |  4 ++++
ecb620
 src/virtualenv/util/path/_system_wheels.py    | 22 +++++++++++++++++++
ecb620
 7 files changed, 48 insertions(+), 4 deletions(-)
ecb620
 create mode 100644 src/virtualenv/util/path/_system_wheels.py
ecb620
ecb620
diff --git a/src/virtualenv/run/__init__.py b/src/virtualenv/run/__init__.py
rdobuilder 039007
index 48647ec..80c9d4a 100644
ecb620
--- a/src/virtualenv/run/__init__.py
ecb620
+++ b/src/virtualenv/run/__init__.py
rdobuilder 039007
@@ -97,8 +97,9 @@ def build_parser_only(args=None):
ecb620
 
ecb620
 def handle_extra_commands(options):
ecb620
     if options.upgrade_embed_wheels:
ecb620
-        result = manual_upgrade(options.app_data, options.env)
ecb620
-        raise SystemExit(result)
ecb620
+        # result = manual_upgrade(options.app_data, options.env)
ecb620
+        logging.warning("virtualenv installed from the RPM package uses wheels from RPM packages as well. Updating them via virtualenv is not possible. The RPM packaged wheels are updated together with other RPM packages of the system.")
ecb620
+        raise SystemExit(1)
ecb620
 
ecb620
 
ecb620
 def load_app_data(args, parser, options):
ecb620
diff --git a/src/virtualenv/seed/embed/base_embed.py b/src/virtualenv/seed/embed/base_embed.py
rdobuilder 039007
index 864cc49..4586f40 100644
ecb620
--- a/src/virtualenv/seed/embed/base_embed.py
ecb620
+++ b/src/virtualenv/seed/embed/base_embed.py
rdobuilder 039007
@@ -5,8 +5,9 @@ from pathlib import Path
ecb620
 
rdobuilder 039007
 from virtualenv.seed.seeder import Seeder
rdobuilder 039007
 from virtualenv.seed.wheels import Version
ecb620
+from virtualenv.util.path._system_wheels import get_system_wheels_paths
ecb620
 
ecb620
-PERIODIC_UPDATE_ON_BY_DEFAULT = True
ecb620
+PERIODIC_UPDATE_ON_BY_DEFAULT = False
ecb620
 
ecb620
 
rdobuilder 039007
 class BaseEmbed(Seeder, ABC):
rdobuilder 039007
@@ -28,6 +29,15 @@ class BaseEmbed(Seeder, ABC):
rdobuilder 039007
 
ecb620
         if not self.distribution_to_versions():
ecb620
             self.enabled = False
rdobuilder 039007
+ 
ecb620
+        if "embed" in (self.pip_version, self.setuptools_version, self.wheel_version):
ecb620
+            raise RuntimeError(
ecb620
+                "Embedded wheels are not available if virtualenv "
ecb620
+                "is installed from the RPM package.\nEither install "
ecb620
+                "virtualenv from PyPI (via pip) or use 'bundle' "
ecb620
+                "version which uses the system-wide pip, setuptools "
ecb620
+                "and wheel wheels provided also by RPM packages."
ecb620
+            )
rdobuilder 039007
 
ecb620
     @classmethod
rdobuilder 039007
     def distributions(cls) -> dict[str, Version]:
rdobuilder 039007
@@ -112,6 +122,10 @@ class BaseEmbed(Seeder, ABC):
ecb620
             result += f" {distribution}{ver},"
ecb620
         return result[:-1] + ")"
ecb620
 
ecb620
+    def insert_system_wheels_paths(self, creator):
ecb620
+        system_wheels_paths = get_system_wheels_paths(creator.interpreter)
ecb620
+        self.extra_search_dir = list(system_wheels_paths) + self.extra_search_dir
ecb620
+
ecb620
 
ecb620
 __all__ = [
ecb620
     "BaseEmbed",
ecb620
diff --git a/src/virtualenv/seed/embed/pip_invoke.py b/src/virtualenv/seed/embed/pip_invoke.py
rdobuilder 039007
index 815753c..5423c9f 100644
ecb620
--- a/src/virtualenv/seed/embed/pip_invoke.py
ecb620
+++ b/src/virtualenv/seed/embed/pip_invoke.py
rdobuilder 039007
@@ -16,6 +16,7 @@ class PipInvoke(BaseEmbed):
ecb620
     def run(self, creator):
ecb620
         if not self.enabled:
ecb620
             return
ecb620
+        self.insert_system_wheels_paths(creator)
ecb620
         for_py_version = creator.interpreter.version_release_str
ecb620
         with self.get_pip_install_cmd(creator.exe, for_py_version) as cmd:
ecb620
             env = pip_wheel_env_run(self.extra_search_dir, self.app_data, self.env)
ecb620
diff --git a/src/virtualenv/seed/embed/via_app_data/via_app_data.py b/src/virtualenv/seed/embed/via_app_data/via_app_data.py
rdobuilder 039007
index 7e58bfc..e236319 100644
ecb620
--- a/src/virtualenv/seed/embed/via_app_data/via_app_data.py
ecb620
+++ b/src/virtualenv/seed/embed/via_app_data/via_app_data.py
rdobuilder 039007
@@ -39,6 +39,7 @@ class FromAppData(BaseEmbed):
ecb620
     def run(self, creator):
ecb620
         if not self.enabled:
ecb620
             return
ecb620
+        self.insert_system_wheels_paths(creator)
ecb620
         with self._get_seed_wheels(creator) as name_to_whl:
ecb620
             pip_version = name_to_whl["pip"].version_tuple if "pip" in name_to_whl else None
ecb620
             installer_class = self.installer_class(pip_version)
ecb620
diff --git a/src/virtualenv/seed/wheels/acquire.py b/src/virtualenv/seed/wheels/acquire.py
rdobuilder 039007
index 8b3ddd8..7a2a4e5 100644
ecb620
--- a/src/virtualenv/seed/wheels/acquire.py
ecb620
+++ b/src/virtualenv/seed/wheels/acquire.py
rdobuilder 039007
@@ -106,13 +106,14 @@ def find_compatible_in_house(distribution, version_spec, for_py_version, in_fold
ecb620
 
ecb620
 
ecb620
 def pip_wheel_env_run(search_dirs, app_data, env):
ecb620
+    from virtualenv.util.path._system_wheels import get_system_wheels_paths
ecb620
     env = env.copy()
ecb620
     env.update({"PIP_USE_WHEEL": "1", "PIP_USER": "0", "PIP_NO_INPUT": "1"})
ecb620
     wheel = get_wheel(
ecb620
         distribution="pip",
ecb620
         version=None,
ecb620
         for_py_version=f"{sys.version_info.major}.{sys.version_info.minor}",
ecb620
-        search_dirs=search_dirs,
ecb620
+        search_dirs=get_system_wheels_paths(sys),
ecb620
         download=False,
ecb620
         app_data=app_data,
ecb620
         do_periodic_update=False,
ecb620
diff --git a/src/virtualenv/seed/wheels/embed/__init__.py b/src/virtualenv/seed/wheels/embed/__init__.py
rdobuilder 039007
index f068efc..fc044f1 100644
ecb620
--- a/src/virtualenv/seed/wheels/embed/__init__.py
ecb620
+++ b/src/virtualenv/seed/wheels/embed/__init__.py
rdobuilder 039007
@@ -50,7 +50,11 @@ BUNDLE_SUPPORT = {
rdobuilder 039007
 MAX = "3.7"
ecb620
 
ecb620
 
ecb620
+# Redefined here because bundled wheels are removed in RPM build
ecb620
+BUNDLE_SUPPORT = None
ecb620
+
ecb620
 def get_embed_wheel(distribution, for_py_version):
ecb620
+    return None  # BUNDLE_SUPPORT == None anyway
ecb620
     path = BUNDLE_FOLDER / (BUNDLE_SUPPORT.get(for_py_version, {}) or BUNDLE_SUPPORT[MAX]).get(distribution)
ecb620
     return Wheel.from_path(path)
ecb620
 
ecb620
diff --git a/src/virtualenv/util/path/_system_wheels.py b/src/virtualenv/util/path/_system_wheels.py
ecb620
new file mode 100644
ecb620
index 0000000..f3fd9b1
ecb620
--- /dev/null
ecb620
+++ b/src/virtualenv/util/path/_system_wheels.py
ecb620
@@ -0,0 +1,22 @@
ecb620
+from pathlib import Path
ecb620
+from subprocess import check_output, CalledProcessError
ecb620
+
ecb620
+
ecb620
+def get_system_wheels_paths(interpreter):
ecb620
+    # ensurepip wheels
ecb620
+    # We need subprocess here to check ensurepip with the Python we are creating
ecb620
+    # a new virtual environment for
ecb620
+    executable = interpreter.executable
ecb620
+    try:
ecb620
+        ensurepip_path = check_output((executable, "-u", "-c", 'import ensurepip; print(ensurepip.__path__[0])'), universal_newlines=True)
ecb620
+        ensurepip_path = Path(ensurepip_path.strip()) / "_bundled"
ecb620
+    except CalledProcessError:
ecb620
+        pass
ecb620
+    else:
ecb620
+        if ensurepip_path.is_dir():
ecb620
+            yield ensurepip_path
ecb620
+
ecb620
+    # Standard wheels path
ecb620
+    wheels_dir = Path("/usr/share/python-wheels")
ecb620
+    if wheels_dir.exists():
ecb620
+        yield wheels_dir
ecb620
-- 
rdobuilder 039007
2.46.2
ecb620