Exemple #1
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
Exemple #2
0
 def sources(cls, interpreter):
     for src in super(PyPy2Posix, cls).sources(interpreter):
         yield src
     host_lib = Path(interpreter.system_prefix) / "lib"
     if host_lib.exists():
         yield PathRefToDest(host_lib, dest=lambda self, _: self.lib)
Exemple #3
0
from collections import defaultdict
from contextlib import contextmanager
from copy import copy
from shutil import copy2
from zipfile import ZipFile

import six

from virtualenv.info import IS_ZIPAPP
from virtualenv.util.path import Path
from virtualenv.util.subprocess import Popen, subprocess
from virtualenv.util.zipapp import ensure_file_on_disk

from . import BUNDLE_SUPPORT, MAX

BUNDLE_FOLDER = Path(os.path.abspath(__file__)).parent


def get_wheels(for_py_version, wheel_cache_dir, extra_search_dir, download, packages):
    # not all wheels are compatible with all python versions, so we need to py version qualify it
    processed = copy(packages)
    # 1. acquire from bundle
    acquire_from_bundle(processed, for_py_version, wheel_cache_dir)
    # 2. acquire from extra search dir
    acquire_from_dir(processed, for_py_version, wheel_cache_dir, extra_search_dir)
    # 3. download from the internet
    if download and processed:
        download_wheel(processed, for_py_version, wheel_cache_dir)

    # in the end just get the wheels
    wheels = _get_wheels(wheel_cache_dir, packages)
Exemple #4
0
from ast import literal_eval
from collections import OrderedDict
from textwrap import dedent

from six import add_metaclass

from virtualenv.discovery.cached_py_info import LogCmd
from virtualenv.info import WIN_CPYTHON_2
from virtualenv.util.path import Path, safe_delete
from virtualenv.util.six import ensure_str, ensure_text
from virtualenv.util.subprocess import run_cmd
from virtualenv.version import __version__

from .pyenv_cfg import PyEnvCfg

HERE = Path(os.path.abspath(__file__)).parent
DEBUG_SCRIPT = HERE / "debug.py"


class CreatorMeta(object):
    def __init__(self):
        self.error = None


@add_metaclass(ABCMeta)
class Creator(object):
    """A class that given a python Interpreter creates a virtual environment"""
    def __init__(self, options, interpreter):
        """Construct a new virtual environment creator.

        :param options: the CLI option as parsed from :meth:`add_parser_arguments`
Exemple #5
0
 def sources(cls, interpreter):
     for src in super(Pypy2Windows, cls).sources(interpreter):
         yield src
     yield PathRefToDest(Path(interpreter.system_prefix) / "libs", dest=lambda self, s: self.dest / s.name)
Exemple #6
0
 def stdlib(self):
     if self._stdlib is None:
         self._stdlib = Path(
             self.interpreter.sysconfig_path("stdlib",
                                             config_var=self._config_vars))
     return self._stdlib
        return False
    host_include_marker = getattr(builtin_classs, "host_include_marker", None)
    if host_include_marker is None:
        return False
    marker = host_include_marker(CURRENT)
    return not marker.exists()


@pytest.mark.xfail(
    condition=bool(os.environ.get(str("CI_RUN"))),
    strict=False,
    reason=
    "did not manage to setup CI to run with VC 14.1 C++ compiler, but passes locally",
)
@pytest.mark.skipif(
    not Path(CURRENT.system_include).exists()
    and not builtin_shows_marker_missing(),
    reason="Building C-Extensions requires header files with host python",
)
@pytest.mark.parametrize("creator",
                         list(i for i in CREATOR_CLASSES.keys()
                              if i != "builtin"))
def test_can_build_c_extensions(creator, tmp_path, coverage_env):
    env, greet = tmp_path / "env", str(tmp_path / "greet")
    shutil.copytree(str(Path(__file__).parent.resolve() / "greet"), greet)
    session = cli_run(
        ["--creator", creator, "--seeder", "app-data",
         str(env), "-vvv"])
    coverage_env()
    cmd = [
        str(session.creator.script("pip")),
Exemple #8
0
def _load_pypi_info(name):
    return PythonInfo._from_json(
        (Path(__file__).parent / "{}.json".format(name)).read_text())
Exemple #9
0
@pytest.mark.parametrize("case", ["mixed", "lower", "upper"])
def test_discovery_via_path(monkeypatch, case, tmp_path, caplog, session_app_data):
    caplog.set_level(logging.DEBUG)
    current = PythonInfo.current_system(session_app_data)
    core = "somethingVeryCryptic{}".format(".".join(str(i) for i in current.version_info[0:3]))
    name = "somethingVeryCryptic"
    if case == "lower":
        name = name.lower()
    elif case == "upper":
        name = name.upper()
    exe_name = "{}{}{}".format(name, current.version_info.major, ".exe" if sys.platform == "win32" else "")
    target = tmp_path / current.distutils_install["scripts"]
    target.mkdir(parents=True)
    executable = target / exe_name
    os.symlink(sys.executable, ensure_text(str(executable)))
    pyvenv_cfg = Path(sys.executable).parents[1] / "pyvenv.cfg"
    if pyvenv_cfg.exists():
        (target / pyvenv_cfg.name).write_bytes(pyvenv_cfg.read_bytes())
    new_path = os.pathsep.join([str(target)] + os.environ.get(str("PATH"), str("")).split(os.pathsep))
    monkeypatch.setenv(str("PATH"), new_path)
    interpreter = get_interpreter(core)

    assert interpreter is not None


def test_discovery_via_path_not_found(tmp_path, monkeypatch):
    monkeypatch.setenv(str("PATH"), str(tmp_path))
    interpreter = get_interpreter(uuid4().hex)
    assert interpreter is None

Exemple #10
0
def system(session_app_data):
    return get_env_debug_info(Path(CURRENT.system_executable), DEBUG_SCRIPT,
                              session_app_data)
 def _executables(cls, interpreter):
     host = Path(interpreter.system_executable)
     for path in (host.parent / n
                  for n in ("python.exe", "pythonw.exe", host.name)):
         yield host, [path.name]
Exemple #12
0
import sys

import pytest
from testing import path
from testing.py_info import read_fixture

from virtualenv.util.path import Path

# Allows to import from `testing` into test submodules.
sys.path.append(str(Path(__file__).parent))


@pytest.fixture
def py_info(py_info_name):
    return read_fixture(py_info_name)


@pytest.fixture
def mock_files(mocker):
    return lambda paths, files: path.mock_files(mocker, paths, files)


@pytest.fixture
def mock_pypy_libs(mocker):
    return lambda pypy, libs: path.mock_pypy_libs(mocker, pypy, libs)
Exemple #13
0
from __future__ import absolute_import, unicode_literals

import shutil
import subprocess
import sys

import pytest
import six

from virtualenv.discovery.py_info import PythonInfo
from virtualenv.run import run_via_cli
from virtualenv.util.path import Path

HERE = Path(__file__).parent
CURRENT = PythonInfo.current_system()


@pytest.fixture(scope="session")
def zipapp_build_env(tmp_path_factory):
    create_env_path = None
    if sys.version_info[0:2] >= (3, 5) and CURRENT.implementation != "PyPy":
        exe = CURRENT.executable  # guaranteed to contain a recent enough pip (tox.ini)
    else:
        create_env_path = tmp_path_factory.mktemp("zipapp-create-env")
        exe, found = None, False
        # prefer CPython as builder as pypy is slow
        for impl in ["cpython", ""]:
            for version in range(8, 4, -1):
                try:
                    # create a virtual environment which is also guaranteed to contain a recent enough pip (bundled)
                    session = run_via_cli([
Exemple #14
0
 def _executables(cls, interpreter):
     host = Path(interpreter.system_executable)
     targets = sorted(
         "{}{}".format(name, PyPy.suffix) for name in cls.exe_names(interpreter)
     )
     yield host, targets
Exemple #15
0
import logging
import os
import pipes
import sys
from collections import OrderedDict

from virtualenv.app_data import AppDataDisabled
from virtualenv.discovery.py_info import PythonInfo
from virtualenv.info import PY2
from virtualenv.util.path import Path
from virtualenv.util.six import ensure_text
from virtualenv.util.subprocess import Popen, subprocess

_CACHE = OrderedDict()
_CACHE[Path(sys.executable)] = PythonInfo()


def from_exe(cls, app_data, exe, raise_on_error=True, ignore_cache=False):
    """"""
    result = _get_from_cache(cls, app_data, exe, ignore_cache=ignore_cache)
    if isinstance(result, Exception):
        if raise_on_error:
            raise result
        else:
            logging.info("%s", str(result))
        result = None
    return result


def _get_from_cache(cls, app_data, exe, ignore_cache=True):
Exemple #16
0
 def wheel(self):
     return Wheel(Path(self.filename))
Exemple #17
0
 def script_dir(self):
     return self.dest / Path(self.interpreter.distutils_install["scripts"])
Exemple #18
0
 def templates(self):
     yield Path("activate.fish")
Exemple #19
0
 def __init__(self, folder):
     self._lock = None
     path = Path(folder)
     self.path = path.resolve() if path.exists() else path
Exemple #20
0
def special_name_dir(tmp_path, special_char_name):
    dest = Path(str(tmp_path)) / special_char_name
    yield dest
    if six.PY2 and sys.platform == "win32" and not IS_PYPY:  # pytest python2 windows does not support unicode delete
        shutil.rmtree(ensure_text(str(dest)))
Exemple #21
0
 def mappings(cls, interpreter):
     mappings = [(Path(interpreter.system_stdlib_platform),
                  cls.to_stdlib_platform)]
     if interpreter.system_stdlib_platform != interpreter.system_stdlib:
         mappings.append((Path(interpreter.system_stdlib), cls.to_stdlib))
     return mappings
def test_do_update_first(tmp_path, mocker, freezer):
    freezer.move_to(_UP_NOW)
    wheel = get_embed_wheel("pip", "3.9")
    app_data_outer = AppDataDiskFolder(str(tmp_path / "app"))
    extra = tmp_path / "extra"
    extra.mkdir()

    pip_version_remote = [
        (wheel_path(wheel, (1, 0, 0)), None),
        (wheel_path(wheel, (0, 1, 0)), _UP_NOW - timedelta(days=1)),
        (wheel_path(wheel, (0, 0, 1)), _UP_NOW - timedelta(days=2)),
        (wheel.path, _UP_NOW - timedelta(days=3)),
        (wheel_path(wheel, (-1, 0, 0)), _UP_NOW - timedelta(days=30)),
    ]
    download_wheels = (Wheel(Path(i[0])) for i in pip_version_remote)

    def _download_wheel(distribution, version_spec, for_py_version, search_dirs, app_data, to_folder):
        assert distribution == "pip"
        assert for_py_version == "3.9"
        assert [str(i) for i in search_dirs] == [str(extra)]
        assert isinstance(app_data, AppDataDiskFolder)
        assert to_folder == app_data_outer.house
        return next(download_wheels)

    download_wheel = mocker.patch("virtualenv.seed.wheels.acquire.download_wheel", side_effect=_download_wheel)
    releases = {
        Wheel(Path(wheel)).version: [
            {"upload_time": datetime.strftime(release_date, "%Y-%m-%dT%H:%M:%S") if release_date is not None else None},
        ]
        for wheel, release_date in pip_version_remote
    }
    pypi_release = json.dumps({"releases": releases})

    @contextmanager
    def _release(of, context):
        assert of == "https://pypi.org/pypi/pip/json"
        assert context is None
        yield StringIO(pypi_release)

    url_o = mocker.patch("virtualenv.seed.wheels.periodic_update.urlopen", side_effect=_release)

    last_update = _UP_NOW - timedelta(days=14)
    u_log = UpdateLog(started=last_update, completed=last_update, versions=[], periodic=True)
    read_dict = mocker.patch("virtualenv.app_data.via_disk_folder.JSONStoreDisk.read", return_value=u_log.to_dict())
    write = mocker.patch("virtualenv.app_data.via_disk_folder.JSONStoreDisk.write")

    versions = do_update("pip", "3.9", str(pip_version_remote[-1][0]), str(app_data_outer), [str(extra)], True)

    assert download_wheel.call_count == len(pip_version_remote)
    assert url_o.call_count == 1

    expected = [
        NewVersion(Path(wheel).name, _UP_NOW, None if release is None else release.replace(microsecond=0))
        for wheel, release in pip_version_remote
    ]
    assert versions == expected

    assert read_dict.call_count == 1
    assert write.call_count == 1
    wrote_json = write.call_args[0][0]
    assert wrote_json == {
        "started": dump_datetime(last_update),
        "completed": dump_datetime(_UP_NOW),
        "periodic": True,
        "versions": [e.to_dict() for e in expected],
    }
Exemple #23
0
 def non_write_able(dest, value):
     common = Path(*os.path.commonprefix([value.parts, dest.parts]))
     raise ArgumentTypeError(
         "the destination {} is not write-able at {}".format(
             dest.relative_to(common), common), )
 def download():
     while True:
         path = pip_version_remote[at["index"]]
         at["index"] += 1
         yield Wheel(Path(path))
Exemple #25
0
 def host_include_marker(cls, interpreter):
     return Path(interpreter.system_include) / "PyPy.h"
Exemple #26
0
def system():
    return get_env_debug_info(Path(CURRENT.system_executable), DEBUG_SCRIPT)
Exemple #27
0
from __future__ import absolute_import, unicode_literals

from virtualenv.seed.wheels.util import Wheel
from virtualenv.util.path import Path

BUNDLE_FOLDER = Path(__file__).absolute().parent
BUNDLE_SUPPORT = {
    "3.10": {
        "pip": "pip-20.2.4-py2.py3-none-any.whl",
        "setuptools": "setuptools-50.3.2-py3-none-any.whl",
        "wheel": "wheel-0.35.1-py2.py3-none-any.whl",
    },
    "3.9": {
        "pip": "pip-20.2.4-py2.py3-none-any.whl",
        "setuptools": "setuptools-50.3.2-py3-none-any.whl",
        "wheel": "wheel-0.35.1-py2.py3-none-any.whl",
    },
    "3.8": {
        "pip": "pip-20.2.4-py2.py3-none-any.whl",
        "setuptools": "setuptools-50.3.2-py3-none-any.whl",
        "wheel": "wheel-0.35.1-py2.py3-none-any.whl",
    },
    "3.7": {
        "pip": "pip-20.2.4-py2.py3-none-any.whl",
        "setuptools": "setuptools-50.3.2-py3-none-any.whl",
        "wheel": "wheel-0.35.1-py2.py3-none-any.whl",
    },
    "3.6": {
        "pip": "pip-20.2.4-py2.py3-none-any.whl",
        "setuptools": "setuptools-50.3.2-py3-none-any.whl",
        "wheel": "wheel-0.35.1-py2.py3-none-any.whl",
Exemple #28
0
 def stdlib_platform(self):
     if self._stdlib_platform is None:
         self._stdlib_platform = Path(
             self.interpreter.sysconfig_path("platstdlib",
                                             config_var=self._config_vars))
     return self._stdlib_platform
Exemple #29
0
 def image_ref(cls, interpreter):
     return Path(interpreter.prefix) / "Python"
Exemple #30
0
 def templates(self):
     yield Path("activate.bat")
     yield Path("deactivate.bat")
     yield Path("pydoc.bat")