Esempio n. 1
0
 def can_create(cls, interpreter):
     """By default all built-in methods assume that if we can describe it we can create it"""
     # first we must be able to describe it
     if cls.can_describe(interpreter):
         sources = []
         can_copy = True
         can_symlink = fs_supports_symlink()
         for src in cls.sources(interpreter):
             if src.exists:
                 if can_copy and not src.can_copy:
                     can_copy = False
                     logging.debug("%s cannot copy %s", cls.__name__, src)
                 if can_symlink and not src.can_symlink:
                     can_symlink = False
                     logging.debug("%s cannot symlink %s", cls.__name__,
                                   src)
                 if not (can_copy or can_symlink):
                     break
             else:
                 logging.debug("%s missing %s", cls.__name__, src)
                 break
             sources.append(src)
         else:
             return Meta(sources, can_copy, can_symlink)
     return None
Esempio n. 2
0
 def add_parser_arguments(cls, parser, interpreter, app_data):
     super().add_parser_arguments(parser, interpreter, app_data)
     can_symlink = app_data.transient is False and fs_supports_symlink()
     sym = "" if can_symlink else "not supported - "
     parser.add_argument(
         "--symlink-app-data",
         dest="symlink_app_data",
         action="store_true" if can_symlink else "store_false",
         help=
         f"{sym} symlink the python packages from the app-data folder (requires seed pip>=19.3)",
         default=False,
     )
Esempio n. 3
0
 def add_parser_arguments(cls, parser, interpreter):
     super(FromAppData, cls).add_parser_arguments(parser, interpreter)
     parser.add_argument(
         "--clear-app-data",
         dest="clear_app_data",
         action="store_true",
         help="clear the app data folder of seed images ({})".format((default_data_dir() / "seed-v1").path),
         default=False,
     )
     can_symlink = fs_supports_symlink()
     parser.add_argument(
         "--symlink-app-data",
         dest="symlink_app_data",
         action="store_true" if can_symlink else "store_false",
         help="{} symlink the python packages from the app-data folder (requires seed pip>=19.3)".format(
             "" if can_symlink else "not supported - "
         ),
         default=False,
     )
Esempio n. 4
0
class PathRef(object):
    FS_SUPPORTS_SYMLINK = fs_supports_symlink()
    FS_CASE_SENSITIVE = fs_is_case_sensitive()

    def __init__(self, src):
        self.src = src
        self.exists = src.exists()
        self._can_read = None if self.exists else False
        self._can_copy = None if self.exists else False
        self._can_symlink = None if self.exists else False

    def __repr__(self):
        return "{}(src={})".format(self.__class__.__name__, self.src)

    @property
    def can_read(self):
        if self._can_read is None:
            if self.src.is_file():
                try:
                    with self.src.open("rb"):
                        self._can_read = True
                except OSError:
                    self._can_read = False
            else:
                self._can_read = os.access(ensure_text(str(self.src)), os.R_OK)
        return self._can_read

    @property
    def can_copy(self):
        if self._can_copy is None:
            self._can_copy = self.can_read
        return self._can_copy

    @property
    def can_symlink(self):
        if self._can_symlink is None:
            self._can_symlink = self.FS_SUPPORTS_SYMLINK and self.can_read
        return self._can_symlink

    @abstractmethod
    def run(self, creator, symlinks):
        raise NotImplementedError
Esempio n. 5
0

@pytest.mark.parametrize(
    "creator, method, isolated",
    [
        pytest.param(
            *i,
            marks=pytest.mark.xfail(
                reason="https://bitbucket.org/pypy/pypy/issues/3159/pypy36-730-venv-fails-with-copies-on-linux",
                strict=True,
            )
        )
        if _VENV_BUG_ON and i[0] == "venv" and i[1] == "copies"
        else i
        for i in product(
            CURRENT_CREATORS, (["copies"] + (["symlinks"] if fs_supports_symlink() else [])), ["isolated", "global"]
        )
    ],
)
def test_create_no_seed(python, creator, isolated, system, coverage_env, special_name_dir, method):
    dest = special_name_dir
    cmd = [
        "-v",
        "-v",
        "-p",
        ensure_text(python),
        ensure_text(str(dest)),
        "--without-pip",
        "--activators",
        "",
        "--creator",
import pytest

from virtualenv.discovery.py_info import PythonInfo
from virtualenv.info import fs_supports_symlink
from virtualenv.run import cli_run
from virtualenv.seed.embed.wheels import BUNDLE_SUPPORT
from virtualenv.seed.embed.wheels.acquire import BUNDLE_FOLDER
from virtualenv.util.six import ensure_text
from virtualenv.util.subprocess import Popen


@pytest.mark.slow
@pytest.mark.timeout(timeout=120)
@pytest.mark.parametrize("copies",
                         [False, True] if fs_supports_symlink() else [True])
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]
    create_cmd = [
        ensure_text(
            str(tmp_path / "en v")
        ),  # space in the name to ensure generated scripts work when path has space
        "--seeder",
        "app-data",
        "--extra-search-dir",
        ensure_text(str(BUNDLE_FOLDER)),
        "--download",
        "--pip",
        bundle_ver["pip"].split("-")[1],
Esempio n. 7
0
def test_satisfy_not_version(spec):
    parsed_spec = PythonSpec.from_string_spec("{}{}".format(CURRENT.implementation, spec))
    matches = CURRENT.satisfies(parsed_spec, True)
    assert matches is False


def test_py_info_cached_error(mocker, tmp_path, session_app_data):
    spy = mocker.spy(cached_py_info, "_run_subprocess")
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(tmp_path), session_app_data)
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(tmp_path), session_app_data)
    assert spy.call_count == 1


@pytest.mark.skipif(not fs_supports_symlink(), reason="symlink is not supported")
def test_py_info_cached_symlink_error(mocker, tmp_path, session_app_data):
    spy = mocker.spy(cached_py_info, "_run_subprocess")
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(tmp_path), session_app_data)
    symlinked = tmp_path / "a"
    symlinked.symlink_to(tmp_path)
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(symlinked), session_app_data)
    assert spy.call_count == 2


def test_py_info_cache_clear(mocker, tmp_path, session_app_data):
    spy = mocker.spy(cached_py_info, "_run_subprocess")
    result = PythonInfo.from_exe(sys.executable, session_app_data)
    assert result is not None
Esempio n. 8
0
 def can_create(cls, interpreter):
     if interpreter.has_venv:
         return Meta(can_symlink=fs_supports_symlink(), can_copy=True)
     return None
Esempio n. 9
0
    parsed_spec = PythonSpec.from_string_spec("{}{}".format(
        CURRENT.implementation, spec))
    matches = CURRENT.satisfies(parsed_spec, True)
    assert matches is False


def test_py_info_cached_error(mocker, tmp_path, session_app_data):
    spy = mocker.spy(cached_py_info, "_run_subprocess")
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(tmp_path), session_app_data)
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(tmp_path), session_app_data)
    assert spy.call_count == 1


@pytest.mark.skipif(not fs_supports_symlink(),
                    reason="symlink is not supported")
def test_py_info_cached_symlink_error(mocker, tmp_path, session_app_data):
    spy = mocker.spy(cached_py_info, "_run_subprocess")
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(tmp_path), session_app_data)
    symlinked = tmp_path / "a"
    symlinked.symlink_to(tmp_path)
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(symlinked), session_app_data)
    assert spy.call_count == 2


def test_py_info_cache_clear(mocker, tmp_path, session_app_data):
    spy = mocker.spy(cached_py_info, "_run_subprocess")
    assert PythonInfo.from_exe(sys.executable, session_app_data) is not None
Esempio n. 10
0
                and CURRENT.pypy_version_info[0:2] == [7, 3]
                and CURRENT.platform == "linux")


@pytest.mark.parametrize(
    "creator, method, isolated",
    [
        pytest.param(
            *i,
            marks=pytest.mark.xfail(
                reason=
                "https://bitbucket.org/pypy/pypy/issues/3159/pypy36-730-venv-fails-with-copies-on-linux",
                strict=True,
            )) if _VENV_BUG_ON and i[0] == "venv" and i[1] == "copies" else i
        for i in product(CURRENT_CREATORS, (
            ["copies"] + (["symlinks"] if fs_supports_symlink() else [])
        ), ["isolated", "global"])
    ],
)
def test_create_no_seed(python, creator, isolated, system, coverage_env,
                        special_name_dir, method):
    dest = special_name_dir
    cmd = [
        "-v",
        "-v",
        "-p",
        ensure_text(python),
        ensure_text(str(dest)),
        "--without-pip",
        "--activators",
        "",
Esempio n. 11
0
class PathRef(object):
    """Base class that checks if a file reference can be symlink/copied"""

    FS_SUPPORTS_SYMLINK = fs_supports_symlink()
    FS_CASE_SENSITIVE = fs_is_case_sensitive()

    def __init__(self, src, must_symlink, must_copy):
        self.must_symlink = must_symlink
        self.must_copy = must_copy
        self.src = src
        try:
            self.exists = src.exists()
        except OSError:
            self.exists = False
        self._can_read = None if self.exists else False
        self._can_copy = None if self.exists else False
        self._can_symlink = None if self.exists else False
        if self.must_copy is True and self.must_symlink is True:
            raise ValueError("can copy and symlink at the same time")

    def __repr__(self):
        return "{}(src={})".format(self.__class__.__name__, self.src)

    @property
    def can_read(self):
        if self._can_read is None:
            if self.src.is_file():
                try:
                    with self.src.open("rb"):
                        self._can_read = True
                except OSError:
                    self._can_read = False
            else:
                self._can_read = os.access(ensure_text(str(self.src)), os.R_OK)
        return self._can_read

    @property
    def can_copy(self):
        if self._can_copy is None:
            if self.must_symlink:
                self._can_copy = self.can_symlink
            else:
                self._can_copy = self.can_read
        return self._can_copy

    @property
    def can_symlink(self):
        if self._can_symlink is None:
            if self.must_copy:
                self._can_symlink = self.can_copy
            else:
                self._can_symlink = self.FS_SUPPORTS_SYMLINK and self.can_read
        return self._can_symlink

    @abstractmethod
    def run(self, creator, symlinks):
        raise NotImplementedError

    def method(self, symlinks):
        if self.must_symlink:
            return symlink
        if self.must_copy:
            return copy
        return symlink if symlinks else copy
Esempio n. 12
0
 def __init__(self):
     super(ViaGlobalRefMeta, self).__init__()
     self.copy_error = None
     self.symlink_error = None
     if not fs_supports_symlink():
         self.symlink = "the filesystem does not supports symlink"
Esempio n. 13
0
def has_symlink_support(tmp_path_factory):
    return fs_supports_symlink()
import sys
from stat import S_IREAD, S_IRGRP, S_IROTH, S_IWUSR

import pytest

from virtualenv.discovery.py_info import PythonInfo
from virtualenv.info import fs_supports_symlink
from virtualenv.run import cli_run
from virtualenv.seed.embed.wheels import BUNDLE_SUPPORT
from virtualenv.seed.embed.wheels.acquire import BUNDLE_FOLDER
from virtualenv.util.six import ensure_text
from virtualenv.util.subprocess import Popen


@pytest.mark.slow
@pytest.mark.parametrize("copies", [False, True] if fs_supports_symlink() else [True])
def test_base_bootstrap_link_via_app_data(tmp_path, coverage_env, current_fastest, copies):
    current = PythonInfo.current_system()
    bundle_ver = BUNDLE_SUPPORT[current.version_release_str]
    create_cmd = [
        ensure_text(str(tmp_path / "en v")),  # space in the name to ensure generated scripts work when path has space
        "--seeder",
        "app-data",
        "--extra-search-dir",
        ensure_text(str(BUNDLE_FOLDER)),
        "--download",
        "--pip",
        bundle_ver["pip"].split("-")[1],
        "--setuptools",
        bundle_ver["setuptools"].split("-")[1],
        "--clear-app-data",
Esempio n. 15
0
 def __init__(self):
     super().__init__()
     self.copy_error = None
     self.symlink_error = None
     if not fs_supports_symlink():
         self.symlink_error = "the filesystem does not supports symlink"
Esempio n. 16
0
class PathRef(metaclass=ABCMeta):
    """Base class that checks if a file reference can be symlink/copied"""

    FS_SUPPORTS_SYMLINK = fs_supports_symlink()
    FS_CASE_SENSITIVE = fs_is_case_sensitive()

    def __init__(self, src, must=RefMust.NA, when=RefWhen.ANY):
        self.must = must
        self.when = when
        self.src = src
        try:
            self.exists = src.exists()
        except OSError:
            self.exists = False
        self._can_read = None if self.exists else False
        self._can_copy = None if self.exists else False
        self._can_symlink = None if self.exists else False

    def __repr__(self):
        return f"{self.__class__.__name__}(src={self.src})"

    @property
    def can_read(self):
        if self._can_read is None:
            if self.src.is_file():
                try:
                    with self.src.open("rb"):
                        self._can_read = True
                except OSError:
                    self._can_read = False
            else:
                self._can_read = os.access(str(self.src), os.R_OK)
        return self._can_read

    @property
    def can_copy(self):
        if self._can_copy is None:
            if self.must == RefMust.SYMLINK:
                self._can_copy = self.can_symlink
            else:
                self._can_copy = self.can_read
        return self._can_copy

    @property
    def can_symlink(self):
        if self._can_symlink is None:
            if self.must == RefMust.COPY:
                self._can_symlink = self.can_copy
            else:
                self._can_symlink = self.FS_SUPPORTS_SYMLINK and self.can_read
        return self._can_symlink

    @abstractmethod
    def run(self, creator, symlinks):  # noqa: U100
        raise NotImplementedError

    def method(self, symlinks):
        if self.must == RefMust.SYMLINK:
            return symlink
        if self.must == RefMust.COPY:
            return copy
        return symlink if symlinks else copy