-
-
Notifications
You must be signed in to change notification settings - Fork 504
/
__init__.py
141 lines (118 loc) · 4.28 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
from __future__ import unicode_literals
import json
import sys
import tox
from tox import reporter
from tox.constants import SITE_PACKAGE_QUERY_SCRIPT
from tox.interpreters.via_path import get_python_info
class Interpreters:
def __init__(self, hook):
self.name2executable = {}
self.executable2info = {}
self.hook = hook
def get_executable(self, envconfig):
"""return path object to the executable for the given
name (e.g. python2.7, python3.6, python etc.)
if name is already an existing path, return name.
If an interpreter cannot be found, return None.
"""
try:
return self.name2executable[envconfig.envname]
except KeyError:
exe = self.hook.tox_get_python_executable(envconfig=envconfig)
reporter.verbosity2("{} uses {}".format(envconfig.envname, exe))
self.name2executable[envconfig.envname] = exe
return exe
def get_info(self, envconfig):
executable = self.get_executable(envconfig)
name = envconfig.basepython
if not executable:
return NoInterpreterInfo(name=name)
try:
return self.executable2info[executable]
except KeyError:
info = run_and_get_interpreter_info(name, executable)
self.executable2info[executable] = info
return info
def get_sitepackagesdir(self, info, envdir):
if not info.executable:
return ""
envdir = str(envdir)
try:
res = exec_on_interpreter(str(info.executable), SITE_PACKAGE_QUERY_SCRIPT, str(envdir))
except ExecFailed as e:
reporter.verbosity1("execution failed: {} -- {}".format(e.out, e.err))
return ""
else:
return res["dir"]
def run_and_get_interpreter_info(name, executable):
assert executable
try:
result = get_python_info(str(executable))
result["version_info"] = tuple(result["version_info"]) # fix json dump transformation
if result["extra_version_info"] is not None:
result["extra_version_info"] = tuple(
result["extra_version_info"],
) # fix json dump transformation
del result["version"]
result["executable"] = str(executable)
except ExecFailed as e:
return NoInterpreterInfo(name, executable=e.executable, out=e.out, err=e.err)
else:
return InterpreterInfo(**result)
def exec_on_interpreter(*args):
from subprocess import PIPE, Popen
popen = Popen(args, stdout=PIPE, stderr=PIPE, universal_newlines=True)
out, err = popen.communicate()
if popen.returncode:
raise ExecFailed(args[0], args[1:], out, err)
if err:
sys.stderr.write(err)
try:
result = json.loads(out)
except Exception:
raise ExecFailed(args[0], args[1:], out, "could not decode {!r}".format(out))
return result
class ExecFailed(Exception):
def __init__(self, executable, source, out, err):
self.executable = executable
self.source = source
self.out = out
self.err = err
class InterpreterInfo:
def __init__(
self,
implementation,
executable,
version_info,
sysplatform,
is_64,
os_sep,
extra_version_info,
):
self.implementation = implementation
self.executable = executable
self.version_info = version_info
self.sysplatform = sysplatform
self.is_64 = is_64
self.os_sep = os_sep
self.extra_version_info = extra_version_info
def __str__(self):
return "<executable at {}, version_info {}>".format(self.executable, self.version_info)
class NoInterpreterInfo:
def __init__(self, name, executable=None, out=None, err="not found"):
self.name = name
self.executable = executable
self.version_info = None
self.out = out
self.err = err
def __str__(self):
if self.executable:
return "<executable at {}, not runnable>".format(self.executable)
else:
return "<executable not found for: {}>".format(self.name)
if tox.INFO.IS_WIN:
from .windows import tox_get_python_executable
else:
from .unix import tox_get_python_executable
assert tox_get_python_executable