Example #1
0
def _non_success_exit_code(capsys, target):
    with pytest.raises(SystemExit) as context:
        run_via_cli(args=[target])
    assert context.value.code != 0
    out, err = capsys.readouterr()
    assert not out, out
    return err
Example #2
0
def test_failed_to_find_implementation(of_id, mocker):
    mocker.patch("virtualenv.run.plugin.creators.CreatorSelector._OPTIONS",
                 return_value={})
    with pytest.raises(RuntimeError) as context:
        run_via_cli(["-p", of_id])
    assert repr(context.value) == repr(
        RuntimeError("No virtualenv implementation for {}".format(
            PythonInfo.current_system())))
Example #3
0
def test_help(capsys):
    with pytest.raises(SystemExit) as context:
        run_via_cli(args=["-h", "-vvv"])
    assert context.value.code == 0

    out, err = capsys.readouterr()
    assert not err
    assert out
Example #4
0
def test_failed_to_find_bad_spec():
    of_id = uuid4().hex
    with pytest.raises(RuntimeError) as context:
        run_via_cli(["-p", of_id])
    msg = repr(
        RuntimeError(
            "failed to find interpreter for Builtin discover of python_spec={!r}"
            .format(of_id)))
    assert repr(context.value) == msg
Example #5
0
def test_create_clear_resets(tmp_path, creator, clear, caplog):
    caplog.set_level(logging.DEBUG)
    if creator == "venv" and clear is False:
        pytest.skip("venv without clear might fail")
    marker = tmp_path / "magic"
    cmd = [str(tmp_path), "--seeder", "app-data", "--without-pip", "--creator", creator, "-vvv"]
    run_via_cli(cmd)

    marker.write_text("")  # if we a marker file this should be gone on a clear run, remain otherwise
    assert marker.exists()

    run_via_cli(cmd + (["--clear"] if clear else []))
    assert marker.exists() is not clear
Example #6
0
def test_version(capsys):
    with pytest.raises(SystemExit) as context:
        run_via_cli(args=["--version"])
    assert context.value.code == 0

    out, err = capsys.readouterr()
    extra = out if six.PY2 else err
    content = out if six.PY3 else err
    assert not extra

    assert __version__ in content
    import virtualenv

    assert virtualenv.__file__ in content
Example #7
0
def test_base_bootstrap_via_pip_invoke(tmp_path, coverage_env,
                                       current_fastest):
    bundle_ver = BUNDLE_SUPPORT[
        PythonInfo.current_system().version_release_str]
    create_cmd = [
        "--seeder",
        "pip",
        str(tmp_path / "env"),
        "--download",
        "--pip",
        bundle_ver["pip"].split("-")[1],
        "--setuptools",
        bundle_ver["setuptools"].split("-")[1],
        "--creator",
        current_fastest,
    ]
    result = run_via_cli(create_cmd)
    coverage_env()
    assert result

    site_package = result.creator.purelib
    pip = site_package / "pip"
    setuptools = site_package / "setuptools"
    wheel = site_package / "wheel"

    files_post_first_create = list(site_package.iterdir())
    assert pip in files_post_first_create
    assert setuptools in files_post_first_create
    assert wheel in files_post_first_create
Example #8
0
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([
                        "-v", "-p", "{}3.{}".format(impl, version),
                        "--activators", "",
                        str(create_env_path)
                    ])
                    exe = str(session.creator.exe)
                    found = True
                    break
                except Exception:
                    pass
            if found:
                break
        else:
            raise RuntimeError("could not find a python to build zipapp")
        cmd = [
            str(Path(exe).parent / "pip"), "install", "pip>=19.3",
            "packaging>=20"
        ]
        subprocess.check_call(cmd)
    yield exe
    if create_env_path is not None:
        shutil.rmtree(str(create_env_path))
Example #9
0
def zipapp_test_env(tmp_path_factory):
    base_path = tmp_path_factory.mktemp("zipapp-test")
    session = run_via_cli(
        ["-v", "--activators", "", "--without-pip",
         str(base_path / "env")])
    yield session.creator.exe
    shutil.rmtree(str(base_path))
def run(args=None):
    start = datetime.now()
    from virtualenv.error import ProcessCallFailed
    from virtualenv.run import run_via_cli

    if args is None:
        args = sys.argv[1:]
    try:
        run_via_cli(args)
    except ProcessCallFailed as exception:
        print("subprocess call failed for {}".format(exception.cmd))
        print(exception.out, file=sys.stdout, end="")
        print(exception.err, file=sys.stderr, end="")
        raise SystemExit(exception.code)
    finally:
        logging.info("done in %.0fms",
                     (datetime.now() - start).total_seconds() * 1000)
Example #11
0
def activation_python(tmp_path_factory, special_char_name, current_fastest):
    dest = os.path.join(
        six.ensure_text(str(tmp_path_factory.mktemp("activation-tester-env"))),
        special_char_name)
    session = run_via_cli([
        "--without-pip", dest, "--prompt", special_char_name, "--creator",
        current_fastest, "-vv"
    ])
    pydoc_test = session.creator.purelib / "pydoc_test.py"
    pydoc_test.write_text('"""This is pydoc_test.py"""')
    yield session
    if WIN_CPYTHON_2:  # PY2 windows does not support unicode delete
        shutil.rmtree(dest)
Example #12
0
def test_debug_bad_virtualenv(tmp_path):
    cmd = [str(tmp_path), "--without-pip"]
    result = run_via_cli(cmd)
    # if the site.py is removed/altered the debug should fail as no one is around to fix the paths
    site_py = result.creator.stdlib / "site.py"
    site_py.unlink()
    # insert something that writes something on the stdout
    site_py.write_text('import sys; sys.stdout.write(repr("std-out")); sys.stderr.write("std-err"); raise ValueError')
    debug_info = result.creator.debug
    assert debug_info["returncode"]
    assert debug_info["err"].startswith("std-err")
    assert "std-out" in debug_info["out"]
    assert debug_info["exception"]
Example #13
0
def test_create_long_path(current_fastest, tmp_path):
    if sys.platform == "darwin":
        max_shebang_length = 512
    else:
        max_shebang_length = 127
    # filenames can be at most 255 long on macOS, so split to to levels
    count = max_shebang_length - len(str(tmp_path))
    folder = tmp_path / ("a" * (count // 2)) / ("b" * (count // 2)) / "c"
    folder.mkdir(parents=True)

    cmd = [str(folder)]
    result = run_via_cli(cmd)
    subprocess.check_call([str(result.creator.script("pip")), "--version"])
Example #14
0
def test_prompt_set(tmp_path, creator, prompt):
    cmd = [str(tmp_path), "--seeder", "app-data", "--without-pip", "--creator", creator]
    if prompt is not None:
        cmd.extend(["--prompt", "magic"])

    result = run_via_cli(cmd)
    actual_prompt = tmp_path.name if prompt is None else prompt
    cfg = PyEnvCfg.from_file(result.creator.pyenv_cfg.path)
    if prompt is None:
        assert "prompt" not in cfg
    else:
        if creator != "venv":
            assert "prompt" in cfg, list(cfg.content.keys())
            assert cfg["prompt"] == actual_prompt
Example #15
0
def test_cross_major(cross_python, coverage_env, tmp_path, current_fastest):
    cmd = [
        "-v",
        "-v",
        "-p",
        six.ensure_text(cross_python.executable),
        six.ensure_text(str(tmp_path)),
        "--no-seed",
        "--activators",
        "",
        "--creator",
        current_fastest,
    ]
    result = run_via_cli(cmd)
    coverage_env()
    env = PythonInfo.from_exe(str(result.creator.exe))
    assert env.version_info.major != CURRENT.version_info.major
Example #16
0
def run(args=None, options=None):
    start = datetime.now()
    from virtualenv.error import ProcessCallFailed
    from virtualenv.run import run_via_cli

    if args is None:
        args = sys.argv[1:]
    try:
        session = run_via_cli(args, options)
        logging.warning(
            "created virtual environment in %.0fms %s with seeder %s",
            (datetime.now() - start).total_seconds() * 1000,
            six.ensure_text(str(session.creator)),
            six.ensure_text(str(session.seeder)),
        )
    except ProcessCallFailed as exception:
        print("subprocess call failed for {}".format(exception.cmd))
        print(exception.out, file=sys.stdout, end="")
        print(exception.err, file=sys.stderr, end="")
        raise SystemExit(exception.code)
Example #17
0
def test_can_build_c_extensions(creator, tmp_path, coverage_env):
    session = run_via_cli(["--creator", creator, "--seed", "app-data", str(tmp_path), "-vvv"])
    coverage_env()
    cmd = [
        str(session.creator.script("pip")),
        "install",
        "--no-index",
        "--no-deps",
        "--disable-pip-version-check",
        "-vvv",
        str(Path(__file__).parent.resolve() / "greet"),
    ]
    process = Popen(cmd)
    process.communicate()
    assert process.returncode == 0

    process = Popen(
        [str(session.creator.exe), "-c", "import greet; greet.greet('World')"],
        universal_newlines=True,
        stdout=subprocess.PIPE,
    )
    out, _ = process.communicate()
    assert process.returncode == 0
    assert out == "Hello World!\n"
def test_base_bootstrap_link_via_app_data(tmp_path, coverage_env,
                                          current_fastest):
    current = PythonInfo.current_system()
    bundle_ver = BUNDLE_SUPPORT[current.version_release_str]
    create_cmd = [
        six.ensure_text(str(tmp_path / "env")),
        "--seeder",
        "app-data",
        "--extra-search-dir",
        six.ensure_text(str(BUNDLE_FOLDER)),
        "--download",
        "--pip",
        bundle_ver["pip"].split("-")[1],
        "--setuptools",
        bundle_ver["setuptools"].split("-")[1],
        "--clear-app-data",
        "--creator",
        current_fastest,
        "-vv",
    ]
    result = run_via_cli(create_cmd)
    coverage_env()
    assert result

    # uninstalling pip/setuptools now should leave us with a ensure_safe_to_do env
    site_package = result.creator.purelib
    pip = site_package / "pip"
    setuptools = site_package / "setuptools"

    files_post_first_create = list(site_package.iterdir())
    assert pip in files_post_first_create
    assert setuptools in files_post_first_create
    for pip_exe in [
            result.creator.script_dir /
            "pip{}{}".format(suffix, result.creator.exe.suffix) for suffix in (
                "",
                "{}".format(current.version_info.major),
                "-{}.{}".format(current.version_info.major,
                                current.version_info.minor),
            )
    ]:
        assert pip_exe.exists()
        process = Popen([
            six.ensure_text(str(pip_exe)), "--version",
            "--disable-pip-version-check"
        ])
        _, __ = process.communicate()
        assert not process.returncode

    remove_cmd = [
        str(result.creator.exe),
        "-m",
        "pip",
        "--verbose",
        "--disable-pip-version-check",
        "uninstall",
        "-y",
        "setuptools",
    ]
    process = Popen(remove_cmd)
    _, __ = process.communicate()
    assert not process.returncode
    assert site_package.exists()

    files_post_first_uninstall = list(site_package.iterdir())
    assert pip in files_post_first_uninstall
    assert setuptools not in files_post_first_uninstall

    # check we can run it again and will work - checks both overwrite and reuse cache
    result = run_via_cli(create_cmd)
    coverage_env()
    assert result
    files_post_second_create = list(site_package.iterdir())
    assert files_post_first_create == files_post_second_create

    process = Popen(remove_cmd + ["pip", "wheel"])
    _, __ = process.communicate()
    assert not process.returncode
    # pip is greedy here, removing all packages removes the site-package too
    if site_package.exists():
        post_run = list(site_package.iterdir())
        assert not post_run, "\n".join(str(i) for i in post_run)

    if sys.version_info[0:2] == (3, 4) and os.environ.get(
            str("PIP_REQ_TRACKER")):
        os.environ.pop(str("PIP_REQ_TRACKER"))
Example #19
0
def test_create_no_seed(python, creator, isolated, system, coverage_env,
                        special_name_dir, method):
    dest = special_name_dir
    cmd = [
        "-v",
        "-v",
        "-p",
        six.ensure_text(python),
        six.ensure_text(str(dest)),
        "--without-pip",
        "--activators",
        "",
        "--creator",
        creator,
        "--{}".format(method),
    ]
    if isolated == "global":
        cmd.append("--system-site-packages")
    result = run_via_cli(cmd)
    coverage_env()
    if IS_PYPY:
        # pypy cleans up file descriptors periodically so our (many) subprocess calls impact file descriptor limits
        # force a cleanup of these on system where the limit is low-ish (e.g. MacOS 256)
        gc.collect()
    content = list(result.creator.purelib.iterdir())
    assert not content, "\n".join(six.ensure_text(str(i)) for i in content)
    assert result.creator.env_name == six.ensure_text(dest.name)
    debug = result.creator.debug
    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(six.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(
            six.ensure_text(str(path)),
            six.ensure_text(str(dest)),
            "\n".join(six.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
    last_from_system_path = next(i for i in reversed(system_sys_path)
                                 if str(i).startswith(system["sys"]["prefix"]))
    if isolated == "isolated":
        assert last_from_system_path not in sys_path
    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 [six.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)))