Skip to content

Commit

Permalink
Fix crash on Python 2 when reusing environments (#450)
Browse files Browse the repository at this point in the history
* Remove redundant mock in test for environment reuse

This breaks tests comparing a string from pyvenv.cfg to command output, because
the latter will be a mock. There is no inherent need for this mock. It was added
recently, and probably speculatively or for performance reasons.

* Add test case for reusing Python 2 environments

* Read base prefix from pyvenv.cfg if present

* Remove trailing newline when querying interpreter base prefix
  • Loading branch information
cjolowicz authored Jun 12, 2021
1 parent 0fb841d commit 2791b70
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
26 changes: 23 additions & 3 deletions nox/virtualenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,15 +339,35 @@ def _check_reused_environment_type(self) -> bool:

def _check_reused_environment_interpreter(self) -> bool:
"""Check if reused environment interpreter is the same."""
program = "import sys; print(getattr(sys, 'real_prefix', sys.base_prefix))"
original = nox.command.run(
[self._resolved_interpreter, "-c", program], silent=True, log=False
original = self._read_base_prefix_from_pyvenv_cfg()
program = (
"import sys; sys.stdout.write(getattr(sys, 'real_prefix', sys.base_prefix))"
)

if original is None:
output = nox.command.run(
[self._resolved_interpreter, "-c", program], silent=True, log=False
)
assert isinstance(output, str)
original = output

created = nox.command.run(
["python", "-c", program], silent=True, log=False, paths=self.bin_paths
)

return original == created

def _read_base_prefix_from_pyvenv_cfg(self) -> Optional[str]:
"""Return the base-prefix entry from pyvenv.cfg, if present."""
path = os.path.join(self.location, "pyvenv.cfg")
if os.path.isfile(path):
with open(path) as io:
for line in io:
key, _, value = line.partition("=")
if key.strip() == "base-prefix":
return value.strip()
return None

@property
def _resolved_interpreter(self) -> str:
"""Return the interpreter, appropriately resolved for the platform.
Expand Down
14 changes: 13 additions & 1 deletion tests/test_virtualenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ def test_create(monkeypatch, make_one):
dir_.ensure("test.txt")
assert dir_.join("test.txt").check()
venv.reuse_existing = True
monkeypatch.setattr(nox.virtualenv.nox.command, "run", mock.MagicMock())

venv.create()

Expand Down Expand Up @@ -443,6 +442,19 @@ def test_create_reuse_oldstyle_virtualenv_environment(make_one):
assert reused


def test_create_reuse_python2_environment(make_one):
venv, location = make_one(reuse_existing=True, interpreter="2.7")

try:
venv.create()
except nox.virtualenv.InterpreterNotFound:
pytest.skip("Requires Python 2.7 installation.")

reused = not venv.create()

assert reused


def test_create_venv_backend(make_one):
venv, dir_ = make_one(venv=True)
venv.create()
Expand Down

0 comments on commit 2791b70

Please sign in to comment.