forked from JuliaPy/PyCall.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_venv.jl
123 lines (111 loc) · 4.2 KB
/
test_venv.jl
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
using PyCall, Test
function test_venv_has_python(path)
newpython = PyCall.python_cmd(venv=path).exec[1]
if !isfile(newpython)
@info """
Python executable $newpython does not exists.
This directory contains only the following files:
$(join(readdir(dirname(newpython)), '\n'))
"""
end
@test isfile(newpython)
end
function test_venv_activation(path)
newpython = PyCall.python_cmd(venv=path).exec[1]
# Run a fresh Julia process with new Python environment
code = """
$(Base.load_path_setup_code())
using PyCall
println(PyCall.pyimport("sys").executable)
println(PyCall.pyimport("sys").exec_prefix)
println(PyCall.pyimport("pip").__file__)
"""
# Note that `pip` is just some arbitrary non-standard
# library. Using standard library like `os` does not work
# because those files are not created.
env = copy(ENV)
env["PYCALL_JL_RUNTIME_PYTHON"] = newpython
jlcmd = setenv(`$(Base.julia_cmd()) --startup-file=no -e $code`, env)
if Sys.iswindows()
# Marking the test broken in Windows. It seems that
# venv copies .dll on Windows and libpython check in
# PyCall.__init__ detects that.
@test_broken begin
output = read(jlcmd, String)
sys_executable, exec_prefix, mod_file = split(output, "\n")
newpython == sys_executable
end
else
output = read(jlcmd, String)
sys_executable, exec_prefix, mod_file = split(output, "\n")
@test newpython == sys_executable
@test startswith(exec_prefix, path)
@test startswith(mod_file, path)
end
end
@testset "virtualenv activation" begin
pyname = "python$(pyversion.major).$(pyversion.minor)"
if Sys.which("virtualenv") === nothing
@info "No virtualenv command. Skipping the test..."
elseif Sys.which(pyname) === nothing
@info "No $pyname command. Skipping the test..."
else
mktempdir() do tmppath
if PyCall.pyversion.major == 2
path = joinpath(tmppath, "kind")
else
path = joinpath(tmppath, "ϵνιℓ")
end
run(`virtualenv --python=$pyname $path`)
test_venv_has_python(path)
newpython = PyCall.python_cmd(venv=path).exec[1]
venv_libpython = PyCall.find_libpython(newpython)
if venv_libpython != PyCall.libpython
@info """
virtualenv created an environment with incompatible libpython:
$venv_libpython
"""
return
end
test_venv_activation(path)
end
end
end
@testset "venv activation" begin
# In case PyCall is built with a Python executable created by
# `virtualenv`, let's try to find the original Python executable.
# Otherwise, `venv` does not work with this Python executable:
# https://bugs.python.org/issue30811
sys = PyCall.pyimport("sys")
if hasproperty(sys, :real_prefix)
# sys.real_prefix is set by virtualenv and does not exist in
# standard Python:
# https://github.com/pypa/virtualenv/blob/16.0.0/virtualenv_embedded/site.py#L554
candidates = [
PyCall.venv_python(sys.real_prefix, "$(pyversion.major).$(pyversion.minor)"),
PyCall.venv_python(sys.real_prefix, "$(pyversion.major)"),
PyCall.venv_python(sys.real_prefix),
PyCall.pyprogramname, # must exists
]
python = candidates[findfirst(isfile, candidates)]
else
python = PyCall.pyprogramname
end
if PyCall.conda
@info "Skip venv test with conda."
elseif !success(PyCall.python_cmd(`-c "import venv"`, python=python))
@info "Skip venv test since venv package is missing."
else
mktempdir() do tmppath
if PyCall.pyversion.major == 2
path = joinpath(tmppath, "kind")
else
path = joinpath(tmppath, "ϵνιℓ")
end
# Create a new virtual environment
run(PyCall.python_cmd(`-m venv $path`, python=python))
test_venv_has_python(path)
test_venv_activation(path)
end
end
end