Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow testing via the system Python #1731

Merged
merged 1 commit into from
Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
.tox
pip-wheel-metadata
venv*
*.pyz
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ venv*

*wheel-store*

Dockerfile
Dockerfile*
.dockerignore
2 changes: 2 additions & 0 deletions docs/changelog/1721.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Allow the test suite to pass even when called with the system Python - to help repackaging of the tool for Linux
distributions - by :user:`gaborbernat`.
37 changes: 32 additions & 5 deletions tests/unit/create/test_creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ def test_destination_exists_file(tmp_path, capsys):

@pytest.mark.skipif(sys.platform == "win32", reason="Windows only applies R/O to files")
def test_destination_not_write_able(tmp_path, capsys):
if hasattr(os, "geteuid"):
if os.geteuid() == 0:
pytest.skip("no way to check permission restriction when running under root")

target = tmp_path
prev_mod = target.stat().st_mode
target.chmod(S_IREAD | S_IRGRP | S_IROTH)
Expand Down Expand Up @@ -196,8 +200,8 @@ def list_to_str(iterable):
exes = ("python.exe",)
else:
exes = ("python", "python{}".format(*sys.version_info), "python{}.{}".format(*sys.version_info))
# pypy3<=7.3: https://bitbucket.org/pypy/pypy/pull-requests/697
if IS_PYPY and creator_key == "venv":
if creator_key == "venv":
# for venv some repackaging does not includes the pythonx.y
exes = exes[:-1]
for exe in exes:
exe_path = result.creator.bin_dir / exe
Expand All @@ -218,6 +222,10 @@ def list_to_str(iterable):

@pytest.mark.skipif(not CURRENT.has_venv, reason="requires interpreter with venv")
def test_venv_fails_not_inline(tmp_path, capsys, mocker):
if hasattr(os, "geteuid"):
if os.geteuid() == 0:
pytest.skip("no way to check permission restriction when running under root")

def _session_via_cli(args, options=None):
session = session_via_cli(args, options)
assert session.creator.can_be_inline is False
Expand Down Expand Up @@ -396,14 +404,33 @@ def test_create_distutils_cfg(creator, tmp_path, monkeypatch):

monkeypatch.chdir(dest) # distutils will read the setup.cfg from the cwd, so change to that

install_demo_cmd = [str(result.creator.script("pip")), "install", str(dest), "--no-use-pep517"]
install_demo_cmd = [
str(result.creator.script("pip")),
"--disable-pip-version-check",
"install",
str(dest),
"--no-use-pep517",
"-vv",
]
subprocess.check_call(install_demo_cmd)

magic = result.creator.script("magic") # console scripts are created in the right location
assert magic.exists()

package_folder = result.creator.platlib / "demo" # prefix is set to the virtualenv prefix for install
assert package_folder.exists()
package_folder = result.creator.purelib / "demo" # prefix is set to the virtualenv prefix for install
assert package_folder.exists(), list_files(str(tmp_path))


def list_files(path):
result = ""
for root, _, files in os.walk(path):
level = root.replace(path, "").count(os.sep)
indent = " " * 4 * level
result += "{}{}/\n".format(indent, os.path.basename(root))
sub = " " * 4 * (level + 1)
for f in files:
result += "{}{}\n".format(sub, f)
return result


@pytest.mark.parametrize("python_path_on", [True, False], ids=["on", "off"])
Expand Down
7 changes: 6 additions & 1 deletion tests/unit/create/test_interpreters.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ def test_failed_to_find_bad_spec():
assert repr(context.value) == msg


@pytest.mark.parametrize("of_id", [sys.executable, PythonInfo.current_system().implementation])
SYSTEM = PythonInfo.current_system()


@pytest.mark.parametrize(
"of_id", ({sys.executable} if sys.executable != SYSTEM.executable else set()) | {SYSTEM.implementation}
)
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:
Expand Down
12 changes: 8 additions & 4 deletions tests/unit/discovery/py_info/test_py_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,13 @@ def test_py_info_cached_symlink_error(mocker, tmp_path, session_app_data):

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
result = PythonInfo.from_exe(sys.executable, session_app_data)
assert result is not None
count = 1 if result.executable == sys.executable else 2 # at least two, one for the venv, one more for the host
assert spy.call_count >= count
PythonInfo.clear_cache(session_app_data)
assert PythonInfo.from_exe(sys.executable, session_app_data) is not None
assert spy.call_count >= 4
assert spy.call_count >= 2 * count


@pytest.mark.skipif(not fs_supports_symlink(), reason="symlink is not supported")
Expand All @@ -146,7 +148,9 @@ def test_py_info_cached_symlink(mocker, tmp_path, session_app_data):
first_result = PythonInfo.from_exe(sys.executable, session_app_data)
assert first_result is not None
count = spy.call_count
assert count >= 2 # at least two, one for the venv, one more for the host
# 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)
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/discovery/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

@pytest.mark.skipif(not fs_supports_symlink(), reason="symlink not supported")
@pytest.mark.parametrize("case", ["mixed", "lower", "upper"])
def test_discovery_via_path(monkeypatch, case, special_name_dir, caplog, session_app_data):
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]))
Expand All @@ -26,7 +26,7 @@ def test_discovery_via_path(monkeypatch, case, special_name_dir, caplog, session
elif case == "upper":
name = name.upper()
exe_name = "{}{}{}".format(name, current.version_info.major, ".exe" if sys.platform == "win32" else "")
target = special_name_dir / current.distutils_install["scripts"]
target = tmp_path / current.distutils_install["scripts"]
target.mkdir(parents=True)
executable = target / exe_name
os.symlink(sys.executable, ensure_text(str(executable)))
Expand Down