Skip to content

Commit 138d47d

Browse files
tkfstevengj
authored andcommitted
Julia 1.0 support (#183)
* Fix with_rebuilt for Julia 1.0 * Pass runtime to juliainfo * Ignore SIGINT in with_rebuilt so that it works well with debuggers * Make tests Julia 1.0-compatible * Test with Julia 1.0 in Travis CI * Fix .travis.yml and appveyor.yml * Document with_rebuilt.ignoring * Skip test_import_without_setup if JULIA_EXE is set * Don't use Pkg.dir in Julia >= 0.7 * Don't call isfile(nothing) * Test mutation in test_julia_module_bang
1 parent 25ab71c commit 138d47d

File tree

5 files changed

+70
-19
lines changed

5 files changed

+70
-19
lines changed

.travis.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ python:
77
env:
88
matrix:
99
- JULIA_VERSION=0.6.4 CROSS_VERSION=1
10-
- JULIA_VERSION=0.7.0-rc2
10+
- JULIA_VERSION=1.0.0
1111
# - JULIA_VERSION=nightly
1212
global:
1313
- TOXENV=py
@@ -17,7 +17,7 @@ matrix:
1717
- language: generic
1818
env:
1919
- PYTHON=python2
20-
- JULIA_VERSION=0.7.0-rc2
20+
- JULIA_VERSION=1.0.0
2121
# - JULIA_VERSION=nightly
2222
os: osx
2323
- language: generic
@@ -29,7 +29,7 @@ matrix:
2929
- language: generic
3030
env:
3131
- PYTHON=python3
32-
- JULIA_VERSION=0.7.0-rc2
32+
- JULIA_VERSION=1.0.0
3333
# - JULIA_VERSION=nightly
3434
os: osx
3535
- language: generic
@@ -54,7 +54,7 @@ before_script:
5454
- which $PYTHON
5555
- $PYTHON -m pip --version
5656
- $PYTHON -m pip install --quiet tox
57-
- julia -e 'Pkg.add("PyCall")'
57+
- julia --color=yes -e 'VERSION >= v"0.7.0-DEV.5183" && using Pkg; Pkg.add("PyCall")'
5858
script:
5959

6060
# "py,py27" below would be redundant when the main interpreter is

appveyor.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,15 @@ build_script:
6363
# - C:\projects\julia\bin\julia -e "versioninfo(); Pkg.add(\"PyCall\"); Pkg.init(); Pkg.resolve()"
6464
# - C:\projects\julia\bin\julia -e "using PyCall; @assert isdefined(:PyCall); @assert typeof(PyCall) === Module"
6565
- "SET PYTHON=%PYTHONDIR%\\python.exe"
66-
- C:\projects\julia\bin\julia -e "versioninfo(); Pkg.add(\"PyCall\")"
66+
- C:\projects\julia\bin\julia -e "
67+
if VERSION >= v\"0.7.0-DEV.3630\";
68+
using InteractiveUtils;
69+
versioninfo(verbose=true);
70+
else
71+
versioninfo(true);
72+
end;
73+
VERSION >= v\"0.7.0-DEV.5183\" && using Pkg;
74+
Pkg.add(\"PyCall\")"
6775
- "%PYTHONDIR%\\python.exe -m pip install --quiet tox"
6876

6977
test_script:

julia/core.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,14 +262,21 @@ def juliainfo(runtime='julia'):
262262
[runtime, "-e",
263263
"""
264264
println(VERSION < v"0.7.0-DEV.3073" ? JULIA_HOME : Base.Sys.BINDIR)
265+
if VERSION >= v"0.7.0-DEV.3630"
266+
using Libdl
267+
using Pkg
268+
end
265269
println(Libdl.dlpath(string("lib", splitext(Base.julia_exename())[1])))
266270
println(unsafe_string(Base.JLOptions().image_file))
267-
PyCall_depsfile = Pkg.dir("PyCall","deps","deps.jl")
268-
if isfile(PyCall_depsfile)
269-
eval(Module(:__anon__),
270-
Expr(:toplevel,
271-
:(Main.Base.include($PyCall_depsfile)),
272-
:(println(pyprogramname))))
271+
if VERSION < v"0.7.0"
272+
PyCall_depsfile = Pkg.dir("PyCall","deps","deps.jl")
273+
else
274+
modpath = Base.locate_package(Base.identify_package("PyCall"))
275+
PyCall_depsfile = joinpath(dirname(modpath),"..","deps","deps.jl")
276+
end
277+
if PyCall_depsfile !== nothing && isfile(PyCall_depsfile)
278+
include(PyCall_depsfile)
279+
println(pyprogramname)
273280
end
274281
"""])
275282
args = output.decode("utf-8").rstrip().split("\n")
@@ -342,7 +349,7 @@ def __init__(self, init_julia=True, jl_runtime_path=None, jl_init_path=None,
342349
runtime = jl_runtime_path
343350
else:
344351
runtime = 'julia'
345-
JULIA_HOME, libjulia_path, image_file, depsjlexe = juliainfo()
352+
JULIA_HOME, libjulia_path, image_file, depsjlexe = juliainfo(runtime)
346353
self._debug("pyprogramname =", depsjlexe)
347354
self._debug("sys.executable =", sys.executable)
348355
exe_differs = is_different_exe(depsjlexe, sys.executable)

julia/with_rebuilt.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from __future__ import print_function, absolute_import
99

1010
import os
11+
import signal
1112
import subprocess
1213
import sys
1314
from contextlib import contextmanager
@@ -21,14 +22,20 @@ def maybe_rebuild(rebuild, julia):
2122
env = os.environ.copy()
2223
info = juliainfo(julia)
2324

24-
build = [julia, '-e', 'Pkg.build("PyCall")']
25+
build = [julia, '-e', """
26+
if VERSION >= v"0.7.0-DEV.3630"
27+
using Pkg
28+
end
29+
Pkg.build("PyCall")
30+
"""]
2531
print('Building PyCall.jl with PYTHON =', sys.executable)
2632
print(*build)
2733
sys.stdout.flush()
2834
subprocess.check_call(build, env=dict(env, PYTHON=sys.executable))
2935
try:
3036
yield
3137
finally:
38+
print() # clear out messages from py.test
3239
print('Restoring previous PyCall.jl build...')
3340
print(*build)
3441
if info.pyprogramname:
@@ -42,8 +49,29 @@ def maybe_rebuild(rebuild, julia):
4249
yield
4350

4451

52+
@contextmanager
53+
def ignoring(sig):
54+
"""
55+
Context manager for ignoring signal `sig`.
56+
57+
For example,::
58+
59+
with ignoring(signal.SIGINT):
60+
do_something()
61+
62+
would ignore user's ctrl-c during ``do_something()``. This is
63+
useful when launching interactive program (in which ctrl-c is a
64+
valid keybinding) from Python.
65+
"""
66+
s = signal.signal(sig, signal.SIG_IGN)
67+
try:
68+
yield
69+
finally:
70+
signal.signal(sig, s)
71+
72+
4573
def with_rebuilt(rebuild, julia, command):
46-
with maybe_rebuild(rebuild, julia):
74+
with maybe_rebuild(rebuild, julia), ignoring(signal.SIGINT):
4775
print('Execute:', *command)
4876
return subprocess.call(command)
4977

test/test_core.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import sys
1313
import os
1414

15+
import pytest
16+
1517
python_version = sys.version_info
1618

1719

@@ -56,7 +58,7 @@ def add(a, b):
5658
self.assertTrue(all(x == y for x, y in zip([11, 11, 11],
5759
julia.map(lambda x: x + 1,
5860
array.array('I', [10, 10, 10])))))
59-
self.assertEqual(6, julia.foldr(add, 0, [1, 2, 3]))
61+
self.assertEqual(6, julia.reduce(add, [1, 2, 3]))
6062

6163
def test_call_python_with_julia_args(self):
6264
self.assertEqual(6, sum(julia.eval('(1, 2, 3)')))
@@ -95,10 +97,12 @@ def test_from_import_non_existing_julia_name(self):
9597
assert not spamspamspam
9698

9799
def test_julia_module_bang(self):
98-
from julia import Base
99-
xs = [1, 2, 3]
100-
ys = Base.scale_b(xs[:], 2)
101-
assert all(x * 2 == y for x, y in zip(xs, ys))
100+
from julia.Base import Channel, put_b, take_b
101+
chan = Channel(1)
102+
sent = 123
103+
put_b(chan, sent)
104+
received = take_b(chan)
105+
assert sent == received
102106

103107
def test_import_julia_submodule(self):
104108
from julia.Base import Enums
@@ -121,6 +125,10 @@ def test_module_dir(self):
121125
from julia import Base
122126
assert 'resize_b' in dir(Base)
123127

128+
@pytest.mark.skipif(
129+
"JULIA_EXE" in orig_env,
130+
reason=("cannot be tested with custom Julia executable;"
131+
" JULIA_EXE is set to {}".format(orig_env.get("JULIA_EXE"))))
124132
def test_import_without_setup(self):
125133
command = [sys.executable, '-c', 'from julia import Base']
126134
print('Executing:', *command)

0 commit comments

Comments
 (0)