コード例 #1
0
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
    assert spy.call_count >= 2  # at least two, one for the venv, one more for the host
    PythonInfo.clear_cache(session_app_data)
    assert PythonInfo.from_exe(sys.executable, session_app_data) is not None
    assert spy.call_count >= 4
コード例 #2
0
def test_bad_exe_py_info_raise(tmp_path, session_app_data):
    exe = str(tmp_path)
    with pytest.raises(RuntimeError) as context:
        PythonInfo.from_exe(exe, session_app_data)
    msg = str(context.value)
    assert "code" in msg
    assert exe in msg
コード例 #3
0
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
コード例 #4
0
def test_py_info_cached_symlink_error(mocker, tmp_path):
    spy = mocker.spy(cached_py_info, "_run_subprocess")
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(tmp_path))
    symlinked = tmp_path / "a"
    symlinked.symlink_to(tmp_path)
    with pytest.raises(RuntimeError):
        PythonInfo.from_exe(str(symlinked))
    assert spy.call_count == 2
コード例 #5
0
def test_py_info_cached_symlink(mocker, tmp_path):
    spy = mocker.spy(cached_py_info, "_run_subprocess")
    first_result = PythonInfo.from_exe(sys.executable)
    assert first_result is not None
    assert spy.call_count == 2  # at least two, one for the venv, one more for the host

    new_exe = tmp_path / "a"
    new_exe.symlink_to(sys.executable)
    new_exe_str = str(new_exe)
    second_result = PythonInfo.from_exe(new_exe_str)
    assert second_result.executable == new_exe_str
    assert spy.call_count == 3  # no longer needed the host invocation, but the new symlink is must
コード例 #6
0
ファイル: test_creator.py プロジェクト: tucked/virtualenv
def test_cross_major(cross_python, coverage_env, tmp_path, current_fastest,
                     session_app_data):
    cmd = [
        "-v",
        "-v",
        "-p",
        ensure_text(cross_python.executable),
        ensure_text(str(tmp_path)),
        "--no-setuptools",
        "--no-wheel",
        "--activators",
        "",
        "--creator",
        current_fastest,
    ]
    result = cli_run(cmd)
    pip_scripts = {
        i.name.replace(".exe", "")
        for i in result.creator.script_dir.iterdir()
        if i.name.startswith("pip")
    }
    major, minor = cross_python.version_info[0:2]
    assert pip_scripts == {
        "pip", "pip-{}.{}".format(major, minor), "pip{}".format(major)
    }
    coverage_env()
    env = PythonInfo.from_exe(str(result.creator.exe), session_app_data)
    assert env.version_info.major != CURRENT.version_info.major
コード例 #7
0
def test_py_info_cached_symlink(mocker, tmp_path, session_app_data):
    spy = mocker.spy(cached_py_info, "_run_subprocess")
    first_result = PythonInfo.from_exe(sys.executable, session_app_data)
    assert first_result is not None
    count = spy.call_count
    # at least two, one for the venv, one more for the host
    exp_count = 1 if first_result.executable == sys.executable else 2
    assert count >= exp_count  # at least two, one for the venv, one more for the host

    new_exe = tmp_path / "a"
    new_exe.symlink_to(sys.executable)
    pyvenv = Path(sys.executable).parents[1] / "pyvenv.cfg"
    if pyvenv.exists():
        (tmp_path / pyvenv.name).write_text(pyvenv.read_text())
    new_exe_str = str(new_exe)
    second_result = PythonInfo.from_exe(new_exe_str, session_app_data)
    assert second_result.executable == new_exe_str
    assert spy.call_count == count + 1  # no longer needed the host invocation, but the new symlink is must
コード例 #8
0
def test_py_info_to_system_raises(session_app_data, mocker, caplog):
    caplog.set_level(logging.DEBUG)
    mocker.patch.object(PythonInfo, "_find_possible_folders", return_value=[])
    result = PythonInfo.from_exe(sys.executable, app_data=session_app_data, raise_on_error=False)
    assert result is None
    log = caplog.records[-1]
    assert log.levelno == logging.INFO
    expected = "ignore {} due cannot resolve system due to RuntimeError('failed to detect ".format(sys.executable)
    assert expected in log.message
コード例 #9
0
def test_bad_exe_py_info_no_raise(tmp_path, caplog, capsys, session_app_data):
    caplog.set_level(logging.NOTSET)
    exe = str(tmp_path)
    result = PythonInfo.from_exe(exe, session_app_data, raise_on_error=False)
    assert result is None
    out, _ = capsys.readouterr()
    assert not out
    messages = [r.message for r in caplog.records if r.filename != "filelock.py"]
    assert len(messages) == 2
    msg = messages[0]
    assert "get interpreter info via cmd: " in msg
    msg = messages[1]
    assert str(exe) in msg
    assert "code" in msg
コード例 #10
0
ファイル: test_py_info.py プロジェクト: sharlenlxm/virtualenv
def test_py_info_ignores_distutils_config(monkeypatch, tmp_path):
    (tmp_path / "setup.cfg").write_text(
        dedent("""
            [install]
            prefix={0}{1}prefix
            install_purelib={0}{1}purelib
            install_platlib={0}{1}platlib
            install_headers={0}{1}headers
            install_scripts={0}{1}scripts
            install_data={0}{1}data
            """.format(tmp_path, os.sep)))
    monkeypatch.chdir(tmp_path)
    py_info = PythonInfo.from_exe(sys.executable)
    distutils = py_info.distutils_install
    for key, value in distutils.items():
        assert not value.startswith(str(tmp_path)), "{}={}".format(key, value)
コード例 #11
0
ファイル: test_creator.py プロジェクト: pydawan/virtualenv
def test_cross_major(cross_python, coverage_env, tmp_path, current_fastest):
    cmd = [
        "-v",
        "-v",
        "-p",
        ensure_text(cross_python.executable),
        ensure_text(str(tmp_path)),
        "--no-seed",
        "--activators",
        "",
        "--creator",
        current_fastest,
    ]
    result = cli_run(cmd)
    coverage_env()
    env = PythonInfo.from_exe(str(result.creator.exe))
    assert env.version_info.major != CURRENT.version_info.major
コード例 #12
0
def test_pyc_only(tmp_path, mocker, session_app_data):
    """Ensure that creation can succeed if os.pyc exists (even if os.py has been deleted)"""
    interpreter = PythonInfo.from_exe(sys.executable, session_app_data)
    host_pyc, _, host_pyc_exists = Python2.from_stdlib(Python2.mappings(interpreter), "os.pyc")
    if not host_pyc_exists:
        pytest.skip("missing system os.pyc at {}".format(host_pyc))
    previous = Python2.from_stdlib

    def from_stdlib(mappings, name):
        path, to, exists = previous(mappings, name)
        if name.endswith(".py"):
            exists = False
        return path, to, exists

    mocker.patch.object(Python2, "from_stdlib", side_effect=from_stdlib)

    result = cli_run([ensure_text(str(tmp_path)), "--without-pip", "--activators", ""])

    assert not (result.creator.stdlib / "os.py").exists()
    assert (result.creator.stdlib / "os.pyc").exists()
    assert "os.pyc" in result.creator.debug["os"]
コード例 #13
0
def test_create_no_seed(python, creator, isolated, system, coverage_env,
                        special_name_dir):
    dest = special_name_dir
    creator_key, method = creator
    cmd = [
        "-v",
        "-v",
        "-p",
        ensure_text(python),
        ensure_text(str(dest)),
        "--without-pip",
        "--activators",
        "",
        "--creator",
        creator_key,
        "--{}".format(method),
    ]
    if isolated == "global":
        cmd.append("--system-site-packages")
    result = cli_run(cmd)
    creator = result.creator
    coverage_env()
    if IS_PYPY:
        # pypy cleans up file descriptors periodically so our (many) subprocess calls impact file descriptor limits
        # force a close of these on system where the limit is low-ish (e.g. MacOS 256)
        gc.collect()
    purelib = creator.purelib
    patch_files = {
        purelib / "{}.{}".format("_virtualenv", i)
        for i in ("py", "pyc", "pth")
    }
    patch_files.add(purelib / "__pycache__")
    content = set(creator.purelib.iterdir()) - patch_files
    assert not content, "\n".join(ensure_text(str(i)) for i in content)
    assert creator.env_name == ensure_text(dest.name)
    debug = creator.debug
    assert "exception" not in debug, "{}\n{}\n{}".format(
        debug.get("exception"), debug.get("out"), debug.get("err"))
    sys_path = cleanup_sys_path(debug["sys"]["path"])
    system_sys_path = cleanup_sys_path(system["sys"]["path"])
    our_paths = set(sys_path) - set(system_sys_path)
    our_paths_repr = "\n".join(ensure_text(repr(i)) for i in our_paths)

    # ensure we have at least one extra path added
    assert len(our_paths) >= 1, our_paths_repr
    # ensure all additional paths are related to the virtual environment
    for path in our_paths:
        msg = "\n{}\ndoes not start with {}\nhas:\n{}".format(
            ensure_text(str(path)),
            ensure_text(str(dest)),
            "\n".join(ensure_text(str(p)) for p in system_sys_path),
        )
        assert str(path).startswith(str(dest)), msg
    # ensure there's at least a site-packages folder as part of the virtual environment added
    assert any(p for p in our_paths
               if p.parts[-1] == "site-packages"), our_paths_repr

    # ensure the global site package is added or not, depending on flag
    global_sys_path = system_sys_path[-1]
    if isolated == "isolated":
        msg = "global sys path {} is in virtual environment sys path:\n{}".format(
            ensure_text(str(global_sys_path)),
            "\n".join(ensure_text(str(j)) for j in sys_path),
        )
        assert global_sys_path not in sys_path, msg
    else:
        common = []
        for left, right in zip(reversed(system_sys_path), reversed(sys_path)):
            if left == right:
                common.append(left)
            else:
                break

        def list_to_str(iterable):
            return [ensure_text(str(i)) for i in iterable]

        assert common, "\n".join(
            difflib.unified_diff(list_to_str(sys_path),
                                 list_to_str(system_sys_path)))

    # test that the python executables in the bin directory are either:
    # - files
    # - absolute symlinks outside of the venv
    # - relative symlinks inside of the venv
    if sys.platform == "win32":
        exes = ("python.exe", )
    else:
        exes = ("python", "python{}".format(*sys.version_info),
                "python{}.{}".format(*sys.version_info))
        if creator_key == "venv":
            # for venv some repackaging does not includes the pythonx.y
            exes = exes[:-1]
    for exe in exes:
        exe_path = creator.bin_dir / exe
        assert exe_path.exists(), "\n".join(
            str(i) for i in creator.bin_dir.iterdir())
        if not exe_path.is_symlink():  # option 1: a real file
            continue  # it was a file
        link = os.readlink(str(exe_path))
        if not os.path.isabs(link):  # option 2: a relative symlink
            continue
        # option 3: an absolute symlink, should point outside the venv
        assert not link.startswith(str(creator.dest))

    if IS_WIN and CURRENT.implementation == "CPython":
        python_w = creator.exe.parent / "pythonw.exe"
        assert python_w.exists()
        assert python_w.read_bytes() != creator.exe.read_bytes()

    if CPython3Posix.pyvenv_launch_patch_active(
            PythonInfo.from_exe(python)) and creator_key != "venv":
        result = subprocess.check_output(
            [
                str(creator.exe), "-c",
                'import os; print(os.environ.get("__PYVENV_LAUNCHER__"))'
            ],
            universal_newlines=True,
        ).strip()
        assert result == "None"

    if isinstance(creator, CPython2PosixBase):
        make_file = debug["makefile_filename"]
        assert os.path.exists(make_file)

    git_ignore = (dest / ".gitignore").read_text()
    assert git_ignore.splitlines() == [
        "# created by virtualenv automatically", "*"
    ]