Example #1
0
def test_discover_ok(tmp_path, monkeypatch, suffix, impl, version, arch, into,
                     caplog, session_app_data):
    caplog.set_level(logging.DEBUG)
    folder = tmp_path / into
    folder.mkdir(parents=True, exist_ok=True)
    name = f"{impl}{version}"
    if arch:
        name += f"-{arch}"
    name += suffix
    dest = folder / name
    os.symlink(CURRENT.executable, str(dest))
    pyvenv = Path(CURRENT.executable).parents[1] / "pyvenv.cfg"
    if pyvenv.exists():
        (folder / pyvenv.name).write_text(pyvenv.read_text())
    inside_folder = str(tmp_path)
    base = CURRENT.discover_exe(session_app_data, inside_folder)
    found = base.executable
    dest_str = str(dest)
    if not fs_is_case_sensitive():
        found = found.lower()
        dest_str = dest_str.lower()
    assert found == dest_str
    assert len(caplog.messages) >= 1, caplog.text
    assert "get interpreter info via cmd: " in caplog.text

    dest.rename(dest.parent / (dest.name + "-1"))
    CURRENT._cache_exe_discovery.clear()
    with pytest.raises(RuntimeError):
        CURRENT.discover_exe(session_app_data, inside_folder)
Example #2
0
def test_python_path(monkeypatch, tmp_path, python_path_on):
    result = cli_run([ensure_text(str(tmp_path)), "--without-pip", "--activators", ""])
    monkeypatch.chdir(tmp_path)
    case_sensitive = fs_is_case_sensitive()

    def _get_sys_path(flag=None):
        cmd = [str(result.creator.exe)]
        if flag:
            cmd.append(flag)
        cmd.extend(["-c", "import json; import sys; print(json.dumps(sys.path))"])
        return [i if case_sensitive else i.lower() for i in json.loads(subprocess.check_output(cmd))]

    monkeypatch.delenv(str("PYTHONPATH"), raising=False)
    base = _get_sys_path()

    # note the value result.creator.interpreter.system_stdlib cannot be set, as that would disable our custom site.py
    python_paths = [
        str(Path(result.creator.interpreter.prefix)),
        str(Path(result.creator.interpreter.system_stdlib) / "b"),
        str(result.creator.purelib / "a"),
        str(result.creator.purelib),
        str(result.creator.bin_dir),
        str(tmp_path / "base"),
        str(tmp_path / "base_sep") + os.sep,
        "name",
        "name{}".format(os.sep),
        str(tmp_path.parent / (ensure_text(tmp_path.name) + "_suffix")),
        ".",
        "..",
        "",
    ]
    python_path_env = os.pathsep.join(ensure_str(i) for i in python_paths)
    monkeypatch.setenv(str("PYTHONPATH"), python_path_env)

    extra_all = _get_sys_path(None if python_path_on else "-E")
    if python_path_on:
        assert extra_all[0] == ""  # the cwd is always injected at start as ''
        extra_all = extra_all[1:]
        assert base[0] == ""
        base = base[1:]

        assert not (set(base) - set(extra_all))  # all base paths are present
        abs_python_paths = list(OrderedDict((os.path.abspath(ensure_text(i)), None) for i in python_paths).keys())
        abs_python_paths = [i if case_sensitive else i.lower() for i in abs_python_paths]

        extra_as_python_path = extra_all[: len(abs_python_paths)]
        assert abs_python_paths == extra_as_python_path  # python paths are there at the start

        non_python_path = extra_all[len(abs_python_paths) :]
        assert non_python_path == [i for i in base if i not in extra_as_python_path]
    else:
        assert base == extra_all
Example #3
0
def test_get_site_packages(tmp_path):
    case_sensitive = fs_is_case_sensitive()
    session = cli_run([ensure_text(str(tmp_path))])
    env_site_packages = [str(session.creator.purelib), str(session.creator.platlib)]
    out = subprocess.check_output(
        [str(session.creator.exe), "-c", r"import site; print(site.getsitepackages())"],
        universal_newlines=True,
    )
    site_packages = ast.literal_eval(out)

    if not case_sensitive:
        env_site_packages = [x.lower() for x in env_site_packages]
        site_packages = [x.lower() for x in site_packages]

    for env_site_package in env_site_packages:
        assert env_site_package in site_packages
Example #4
0
 def generate_names(self):
     impls = OrderedDict()
     if self.implementation:
     
         impls[self.implementation] = False
         if fs_is_case_sensitive():
             impls[self.implementation.lower()] = False
             impls[self.implementation.upper()] = False
     impls["python"] = True  
     version = self.major, self.minor, self.micro
     try:
         version = version[: version.index(None)]
     except ValueError:
         pass
     for impl, match in impls.items():
         for at in range(len(version), -1, -1):
             cur_ver = version[0:at]
             spec = "{}{}".format(impl, ".".join(str(i) for i in cur_ver))
             yield spec, match
Example #5
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
Example #6
0
    def _possible_base(self):
        possible_base = OrderedDict()
        basename = os.path.splitext(os.path.basename(self.executable))[0].rstrip(digits)
        possible_base[basename] = None
        possible_base[self.implementation] = None
        # python is always the final option as in practice is used by multiple implementation as exe name
        if "python" in possible_base:
            del possible_base["python"]
        possible_base["python"] = None
        for base in possible_base:
            lower = base.lower()
            yield lower
            from virtualenv.info import fs_is_case_sensitive

            if fs_is_case_sensitive():
                if base != lower:
                    yield base
                upper = base.upper()
                if upper != base:
                    yield upper
Example #7
0
 def generate_names(self):
     impls = OrderedDict()
     if self.implementation:
         # first consider implementation as it is
         impls[self.implementation] = False
         if fs_is_case_sensitive():
             # for case sensitive file systems consider lower and upper case versions too
             # trivia: MacBooks and all pre 2018 Windows-es were case insensitive by default
             impls[self.implementation.lower()] = False
             impls[self.implementation.upper()] = False
     impls["python"] = True  # finally consider python as alias, implementation must match now
     version = self.major, self.minor, self.micro
     try:
         version = version[: version.index(None)]
     except ValueError:
         pass
     for impl, match in impls.items():
         for at in range(len(version), -1, -1):
             cur_ver = version[0:at]
             spec = f"{impl}{'.'.join(str(i) for i in cur_ver)}"
             yield spec, match
Example #8
0
def test_discover_ok(tmp_path, monkeypatch, suffix, impl, version, arch, into, caplog):
    caplog.set_level(logging.DEBUG)
    folder = tmp_path / into
    folder.mkdir(parents=True, exist_ok=True)
    dest = folder / "{}{}".format(impl, version, arch, suffix)
    os.symlink(CURRENT.executable, str(dest))
    inside_folder = str(tmp_path)
    base = CURRENT.discover_exe(inside_folder)
    found = base.executable
    dest_str = str(dest)
    if not fs_is_case_sensitive():
        found = found.lower()
        dest_str = dest_str.lower()
    assert found == dest_str
    assert len(caplog.messages) >= 1, caplog.text
    assert "get interpreter info via cmd: " in caplog.text

    dest.rename(dest.parent / (dest.name + "-1"))
    CURRENT._cache_exe_discovery.clear()
    with pytest.raises(RuntimeError):
        CURRENT.discover_exe(inside_folder)
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
Example #10
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