diff --git a/julia/core.py b/julia/core.py index 48d1d32d..02dc975a 100644 --- a/julia/core.py +++ b/julia/core.py @@ -267,9 +267,14 @@ def determine_if_statically_linked(): 'pyprogramname', 'libpython']) -def juliainfo(runtime='julia'): - output = subprocess.check_output( - [runtime, "-e", +def juliainfo(runtime='julia', **popen_kwargs): + # Use the original environment variables to avoid a cryptic + # error "fake-julia/../lib/julia/sys.so: cannot open shared + # object file: No such file or directory": + popen_kwargs.setdefault("env", _enviorn) + + proc = subprocess.Popen( + [runtime, "--startup-file=no", "-e", """ println(VERSION < v"0.7.0-DEV.3073" ? JULIA_HOME : Base.Sys.BINDIR) if VERSION >= v"0.7.0-DEV.3630" @@ -282,7 +287,11 @@ def juliainfo(runtime='julia'): PyCall_depsfile = Pkg.dir("PyCall","deps","deps.jl") else modpath = Base.locate_package(Base.identify_package("PyCall")) - PyCall_depsfile = joinpath(dirname(modpath),"..","deps","deps.jl") + if modpath == nothing + PyCall_depsfile = nothing + else + PyCall_depsfile = joinpath(dirname(modpath),"..","deps","deps.jl") + end end if PyCall_depsfile !== nothing && isfile(PyCall_depsfile) include(PyCall_depsfile) @@ -290,11 +299,26 @@ def juliainfo(runtime='julia'): println(libpython) end """], - # Use the original environment variables to avoid a cryptic - # error "fake-julia/../lib/julia/sys.so: cannot open shared - # object file: No such file or directory": - env=_enviorn) - args = output.decode("utf-8").rstrip().split("\n") + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + **popen_kwargs) + + stdout, stderr = proc.communicate() + retcode = proc.wait() + if retcode != 0: + raise subprocess.CalledProcessError( + retcode, + [runtime, "-e", "..."], + stdout, + stderr, + ) + + stderr = stderr.strip() + if stderr: + warnings.warn("{} warned:\n{}".format(runtime, stderr)) + + args = stdout.rstrip().split("\n") args.extend([None] * (len(JuliaInfo._fields) - len(args))) return JuliaInfo(*args) diff --git a/test/test_juliainfo.py b/test/test_juliainfo.py new file mode 100644 index 00000000..ec3f7cb3 --- /dev/null +++ b/test/test_juliainfo.py @@ -0,0 +1,49 @@ +import os +import subprocess + +from julia.core import juliainfo, _enviorn + + +def check_core_juliainfo(jlinfo): + assert os.path.exists(jlinfo.JULIA_HOME) + assert os.path.exists(jlinfo.libjulia_path) + assert os.path.exists(jlinfo.image_file) + + +def test_juliainfo_normal(): + jlinfo = juliainfo(os.getenv("JULIA_EXE", "julia")) + check_core_juliainfo(jlinfo) + assert os.path.exists(jlinfo.pyprogramname) + # Note: jlinfo.libpython is probably not a full path so we are not + # testing it here. + + +def test_juliainfo_without_pycall(tmpdir): + """ + `juliainfo` should not fail even when PyCall.jl is not installed. + """ + + runtime = os.getenv("JULIA_EXE", "julia") + + env_var = subprocess.check_output( + [runtime, "--startup-file=no", "-e", """ + if VERSION < v"0.7-" + println("JULIA_PKGDIR") + print(ARGS[1]) + else + paths = [ARGS[1], DEPOT_PATH[2:end]...] + println("JULIA_DEPOT_PATH") + print(join(paths, Sys.iswindows() ? ';' : ':')) + end + """, str(tmpdir)], + env=_enviorn, + universal_newlines=True) + name, val = env_var.split("\n", 1) + + jlinfo = juliainfo( + runtime, + env=dict(_enviorn, **{name: val})) + + check_core_juliainfo(jlinfo) + assert jlinfo.pyprogramname is None + assert jlinfo.libpython is None