Skip to content

Commit 837fbb5

Browse files
jurko-gospodneticgaborbernat
authored andcommitted
trivial interpreters py touchups and test coverage improvements (tox-dev#708)
* simplify exception handling code * rewrap long code lines * fix NoInterpreterInfo string representation with a set executable * add several missing interpreters.py tests In the process touched up the `sitepackagesdir()` implementation to make it easier to test. * add changelog entry
1 parent 2edec31 commit 837fbb5

File tree

3 files changed

+107
-13
lines changed

3 files changed

+107
-13
lines changed

changelog/708.trivial.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
touched up ``interpreters.py`` code and added some missing tests for it - by @jurko-gospodnetic

tests/test_interpreters.py

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@
77
import pytest
88

99
from tox.config import get_plugin_manager
10+
from tox.interpreters import ExecFailed
11+
from tox.interpreters import InterpreterInfo
1012
from tox.interpreters import Interpreters
13+
from tox.interpreters import NoInterpreterInfo
14+
from tox.interpreters import pyinfo
1115
from tox.interpreters import run_and_get_interpreter_info
16+
from tox.interpreters import sitepackagesdir
1217
from tox.interpreters import tox_get_python_executable
1318

1419

@@ -70,7 +75,8 @@ class envconfig:
7075
envconfig.basepython = name
7176
p = tox_get_python_executable(envconfig)
7277
assert p
73-
popen = subprocess.Popen([str(p), '-V'], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
78+
popen = subprocess.Popen([str(p), '-V'], stderr=subprocess.PIPE,
79+
stdout=subprocess.PIPE)
7480
stdout, stderr = popen.communicate()
7581
assert not stdout or not stderr
7682
assert ver in stderr.decode('ascii') or ver in stdout.decode('ascii')
@@ -130,3 +136,92 @@ class envconfig:
130136
info = interpreters.get_info(envconfig)
131137
s = interpreters.get_sitepackagesdir(info, "")
132138
assert s
139+
140+
141+
def test_pyinfo(monkeypatch):
142+
monkeypatch.setattr(sys, "version_info", [42, 4242])
143+
monkeypatch.setattr(sys, "platform", "an unladen swallow")
144+
result = pyinfo()
145+
assert len(result) == 2
146+
assert result["version_info"] == (42, 4242)
147+
assert result["sysplatform"] == "an unladen swallow"
148+
149+
150+
def test_sitepackagesdir(monkeypatch):
151+
import distutils.sysconfig as sysconfig
152+
test_envdir = "holy grail"
153+
test_dir = "Now go away or I will taunt you a second time."
154+
155+
def dummy_get_python_lib(prefix):
156+
assert prefix is test_envdir
157+
return test_dir
158+
159+
monkeypatch.setattr(sysconfig, "get_python_lib", dummy_get_python_lib)
160+
assert sitepackagesdir(test_envdir) == {"dir": test_dir}
161+
162+
163+
def test_exec_failed():
164+
x = ExecFailed("my-executable", "my-source", "my-out", "my-err")
165+
assert isinstance(x, Exception)
166+
assert x.executable == "my-executable"
167+
assert x.source == "my-source"
168+
assert x.out == "my-out"
169+
assert x.err == "my-err"
170+
171+
172+
class TestInterpreterInfo:
173+
174+
def info(self, name="my-name", executable="my-executable",
175+
version_info="my-version-info", sysplatform="my-sys-platform"):
176+
return InterpreterInfo(name, executable, version_info, sysplatform)
177+
178+
def test_runnable(self):
179+
assert self.info().runnable
180+
181+
@pytest.mark.parametrize("missing_arg", ("executable", "version_info"))
182+
def test_assert_on_missing_args(self, missing_arg):
183+
with pytest.raises(AssertionError):
184+
self.info(**{missing_arg: None})
185+
186+
def test_data(self):
187+
x = self.info("larry", "moe", "shemp", "curly")
188+
assert x.name == "larry"
189+
assert x.executable == "moe"
190+
assert x.version_info == "shemp"
191+
assert x.sysplatform == "curly"
192+
193+
def test_str(self):
194+
x = self.info(executable="foo", version_info="bar")
195+
assert str(x) == "<executable at foo, version_info bar>"
196+
197+
198+
class TestNoInterpreterInfo:
199+
200+
def test_runnable(self):
201+
assert not NoInterpreterInfo("foo").runnable
202+
assert not NoInterpreterInfo("foo", executable=sys.executable).runnable
203+
204+
def test_default_data(self):
205+
x = NoInterpreterInfo("foo")
206+
assert x.name == "foo"
207+
assert x.executable is None
208+
assert x.version_info is None
209+
assert x.out is None
210+
assert x.err == "not found"
211+
212+
def test_set_data(self):
213+
x = NoInterpreterInfo("migraine", executable="my-executable",
214+
out="my-out", err="my-err")
215+
assert x.name == "migraine"
216+
assert x.executable == "my-executable"
217+
assert x.version_info is None
218+
assert x.out == "my-out"
219+
assert x.err == "my-err"
220+
221+
def test_str_without_executable(self):
222+
x = NoInterpreterInfo("coconut")
223+
assert str(x) == "<executable not found for: coconut>"
224+
225+
def test_str_with_executable(self):
226+
x = NoInterpreterInfo("coconut", executable="bang/em/together")
227+
assert str(x) == "<executable at bang/em/together, not runnable>"

tox/interpreters.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ def get_sitepackagesdir(self, info, envdir):
4848
res = exec_on_interpreter(info.executable,
4949
[inspect.getsource(sitepackagesdir),
5050
"print(sitepackagesdir(%r))" % envdir])
51-
except ExecFailed:
52-
val = sys.exc_info()[1]
53-
print("execution failed: %s -- %s" % (val.out, val.err))
51+
except ExecFailed as e:
52+
print("execution failed: %s -- %s" % (e.out, e.err))
5453
return ""
5554
else:
5655
return res["dir"]
@@ -59,12 +58,11 @@ def get_sitepackagesdir(self, info, envdir):
5958
def run_and_get_interpreter_info(name, executable):
6059
assert executable
6160
try:
62-
result = exec_on_interpreter(executable,
63-
[inspect.getsource(pyinfo), "print(pyinfo())"])
64-
except ExecFailed:
65-
val = sys.exc_info()[1]
66-
return NoInterpreterInfo(name, executable=val.executable,
67-
out=val.out, err=val.err)
61+
result = exec_on_interpreter(executable, [inspect.getsource(pyinfo),
62+
"print(pyinfo())"])
63+
except ExecFailed as e:
64+
return NoInterpreterInfo(name, executable=e.executable,
65+
out=e.out, err=e.err)
6866
else:
6967
return InterpreterInfo(name, executable, **result)
7068

@@ -123,7 +121,7 @@ def __init__(self, name, executable=None,
123121

124122
def __str__(self):
125123
if self.executable:
126-
return "<executable at %s, not runnable>"
124+
return "<executable at %s, not runnable>" % self.executable
127125
else:
128126
return "<executable not found for: %s>" % self.name
129127

@@ -184,5 +182,5 @@ def pyinfo():
184182

185183

186184
def sitepackagesdir(envdir):
187-
from distutils.sysconfig import get_python_lib
188-
return dict(dir=get_python_lib(prefix=envdir))
185+
import distutils.sysconfig
186+
return dict(dir=distutils.sysconfig.get_python_lib(prefix=envdir))

0 commit comments

Comments
 (0)