Группа :: Development/Python3
Пакет: python3-module-virtualenv
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: python3-module-virtualenv-20.24.3-alt.patch
Скачать
Скачать
src/virtualenv/seed/embed/base_embed.py | 2 +-
src/virtualenv/seed/wheels/embed/__init__.py | 117 ++++++++++++++++++++-
tests/integration/test_run_int.py | 4 +
tests/integration/test_zipapp.py | 5 +
.../seed/embed/test_bootstrap_link_via_app_data.py | 3 +
tests/unit/seed/wheels/test_acquire_find_wheel.py | 20 ++++
6 files changed, 148 insertions(+), 3 deletions(-)
diff --git a/src/virtualenv/seed/embed/base_embed.py b/src/virtualenv/seed/embed/base_embed.py
index 5ff2c84..ac18334 100644
--- a/src/virtualenv/seed/embed/base_embed.py
+++ b/src/virtualenv/seed/embed/base_embed.py
@@ -6,7 +6,7 @@ from pathlib import Path
from virtualenv.seed.seeder import Seeder
from virtualenv.seed.wheels import Version
-PERIODIC_UPDATE_ON_BY_DEFAULT = True
+PERIODIC_UPDATE_ON_BY_DEFAULT = False
class BaseEmbed(Seeder, metaclass=ABCMeta):
diff --git a/src/virtualenv/seed/wheels/embed/__init__.py b/src/virtualenv/seed/wheels/embed/__init__.py
index 0d87e4b..e883c03 100644
--- a/src/virtualenv/seed/wheels/embed/__init__.py
+++ b/src/virtualenv/seed/wheels/embed/__init__.py
@@ -2,9 +2,14 @@ from __future__ import annotations
from pathlib import Path
+from operator import attrgetter
+import re
+import sys
+import sysconfig
+import subprocess
+
from virtualenv.seed.wheels.util import Wheel
-BUNDLE_FOLDER = Path(__file__).absolute().parent
BUNDLE_SUPPORT = {
"3.7": {
"pip": "pip-23.2.1-py3-none-any.whl",
@@ -40,8 +45,116 @@ BUNDLE_SUPPORT = {
MAX = "3.7"
+def get_bundle_folder(for_py_version=None):
+ """Return path of the system seed wheels"""
+ global _BUNDLE_FOLDER_CACHE
+
+ try:
+ return _BUNDLE_FOLDER_CACHE[for_py_version]
+ except KeyError:
+ pass
+
+ version_pattern = r"^\d+\.\d+$"
+ if for_py_version and not re.match(version_pattern, for_py_version):
+ raise ValueError(
+ f"Unsupported value for for_py_version: '{for_py_version}', "
+ f"expected regex: '{version_pattern}'"
+ )
+ if for_py_version is None:
+ for_py_version_major = str(sys.version_info.major)
+ else:
+ for_py_version_major = for_py_version[0]
+
+ # assume all system Pythons were configured with the same "scripts" path
+ system_python = Path(sysconfig.get_path(name="scripts")) / (
+ f"python{for_py_version_major}"
+ )
+ cmd = [
+ system_python,
+ "-c",
+ (
+ "import os, sys, system_seed_wheels;"
+ "sys.stdout.write(os.path.dirname(system_seed_wheels.__file__))"
+ ),
+ ]
+ try:
+ _BUNDLE_FOLDER_CACHE[for_py_version] = Path(
+ subprocess.check_output(cmd, text=True)
+ )
+ return _BUNDLE_FOLDER_CACHE[for_py_version]
+ except subprocess.CalledProcessError as e:
+ raise RuntimeError(
+ "Cannot find the folder with system seed wheels. "
+ "Please, install system-seed-wheels package if "
+ f"it has support for your Python interpreter: '{system_python}'"
+ ) from e
+
+
+class BundleSupport:
+ SEED_NAMES = ("pip", "setuptools", "wheel")
+
+ def __init__(self, for_py_version=None):
+ self._system_seed_wheels = None
+ if for_py_version is None:
+ self.for_py_version = "{}.{}".format(*sys.version_info[0:2])
+ else:
+ self.for_py_version = for_py_version
+ self.wheels_dir = get_bundle_folder(for_py_version)
+
+ def discover_wheel(self, distribution):
+ """based on virtualenv.seed.wheels.util.discover_wheels"""
+ wheels = []
+ for filename in self.wheels_dir.iterdir():
+ wheel = Wheel.from_path(filename)
+ if wheel and wheel.distribution == distribution:
+ wheels.append(wheel)
+ sorted_wheels = sorted(
+ wheels,
+ key=attrgetter("version_tuple", "distribution"),
+ reverse=True,
+ )
+ if not sorted_wheels:
+ raise RuntimeError(
+ f"Wheel for distribution: '{distribution}' not found on path: "
+ f"'{self.wheels_dir}'"
+ )
+ return sorted_wheels[0].name
+
+ @property
+ def system_seed_wheels(self):
+ if self._system_seed_wheels is None:
+ wheels_names = {}
+ for distr in self.SEED_NAMES:
+ wheels_names[distr] = self.discover_wheel(distr)
+ self._system_seed_wheels = {
+ self.for_py_version: dict(wheels_names)
+ }
+
+ return self._system_seed_wheels
+
+ def __getitem__(self, key):
+ return self.system_seed_wheels[self.for_py_version]
+
+ def get(self, key, default=None):
+ return self.system_seed_wheels[self.for_py_version]
+
+ def items(self):
+ return self.system_seed_wheels.items()
+
+ def keys(self):
+ return self.system_seed_wheels.keys()
+
+
+_BUNDLE_FOLDER_CACHE = {}
+# defined only for self tests, which only check the current interpreter
+BUNDLE_FOLDER = get_bundle_folder()
+BUNDLE_SUPPORT = BundleSupport()
+
+
def get_embed_wheel(distribution, for_py_version):
- path = BUNDLE_FOLDER / (BUNDLE_SUPPORT.get(for_py_version, {}) or BUNDLE_SUPPORT[MAX]).get(distribution)
+ path = get_bundle_folder(for_py_version) / (
+ BundleSupport(for_py_version).get(for_py_version, {})
+ ).get(distribution)
return Wheel.from_path(path)
diff --git a/tests/integration/test_run_int.py b/tests/integration/test_run_int.py
index e1dc6d3..bb459c7 100644
--- a/tests/integration/test_run_int.py
+++ b/tests/integration/test_run_int.py
@@ -1,5 +1,6 @@
from __future__ import annotations
+import os
from typing import TYPE_CHECKING
import pytest
@@ -12,6 +13,9 @@ if TYPE_CHECKING:
from pathlib import Path
+@pytest.mark.skipif(
+ "NO_INTERNET" in os.environ, reason="Requires internet connection",
+)
@pytest.mark.skipif(IS_PYPY, reason="setuptools distutils patching does not work")
def test_app_data_pinning(tmp_path: Path) -> None:
version = "23.1"
diff --git a/tests/integration/test_zipapp.py b/tests/integration/test_zipapp.py
index 5bcddf5..ed47de1 100644
--- a/tests/integration/test_zipapp.py
+++ b/tests/integration/test_zipapp.py
@@ -1,5 +1,6 @@
from __future__ import annotations
+import os
import shutil
import subprocess
from contextlib import suppress
@@ -14,6 +15,10 @@ from virtualenv.run import cli_run
HERE = Path(__file__).parent
CURRENT = PythonInfo.current_system()
+pytestmark = pytest.mark.skipif(
+ "NO_INTERNET" in os.environ, reason="Requires internet connection",
+)
+
@pytest.fixture(scope="session")
def zipapp_build_env(tmp_path_factory):
diff --git a/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py b/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py
index 7db52e1..16895a5 100644
--- a/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py
+++ b/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py
@@ -25,6 +25,9 @@ if TYPE_CHECKING:
@pytest.mark.slow()
@pytest.mark.parametrize("copies", [False, True] if fs_supports_symlink() else [True])
+@pytest.mark.skipif(
+ "NO_INTERNET" in os.environ, reason="Requires internet connection"
+)
def test_seed_link_via_app_data(tmp_path, coverage_env, current_fastest, copies):
current = PythonInfo.current_system()
bundle_ver = BUNDLE_SUPPORT[current.version_release_str]
diff --git a/tests/unit/seed/wheels/test_acquire_find_wheel.py b/tests/unit/seed/wheels/test_acquire_find_wheel.py
index 7822849..a13466e 100644
--- a/tests/unit/seed/wheels/test_acquire_find_wheel.py
+++ b/tests/unit/seed/wheels/test_acquire_find_wheel.py
@@ -27,3 +27,23 @@ def test_find_exact(for_py_version):
def test_find_bad_spec():
with pytest.raises(ValueError, match="bad"):
find_compatible_in_house("setuptools", "bad", MAX, BUNDLE_FOLDER)
+
+
+# ALT tests
+def test_find_python2():
+ """Python2 is not supported"""
+ with pytest.raises(FileNotFoundError):
+ get_embed_wheel("setuptools", "2.7")
+
+
+def test_find_python4():
+ """Future Python4 is not yet supported"""
+ with pytest.raises(FileNotFoundError):
+ get_embed_wheel("setuptools", "4.0")
+
+
+def test_wrong_version():
+ """Python version format"""
+ with pytest.raises(ValueError) as e:
+ get_embed_wheel("setuptools", "123")
+ assert "Unsupported value for for_py_version:" in str(e.value)