forked from JuliaPy/PyCall.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_venv.jl
More file actions
134 lines (121 loc) · 4.54 KB
/
test_venv.jl
File metadata and controls
134 lines (121 loc) · 4.54 KB
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
using PyCall, Test
"""Gets temp directory, possibly with user-set environment variable"""
function _mktempdir(f::Function, parent=nothing; kwargs...)
if parent === nothing && haskey(ENV, "_TMP_DIR")
return mktempdir(f, ENV["_TMP_DIR"]; kwargs...)
end
if parent === nothing
parent = tempdir()
end
return mktempdir(f, parent; kwargs...)
end
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 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