-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Julia 1.0 support #183
Julia 1.0 support #183
Conversation
Needs a rebase. |
Awesome! Thanks for the merge! It's rebased now. |
CIs are all green now! |
Why then do we have:
in the Travis log (checked that of Python 3.6)? |
julia/core.py
Outdated
:(Main.Base.include($PyCall_depsfile)), | ||
:(println(pyprogramname)))) | ||
include(PyCall_depsfile) | ||
println(pyprogramname) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought the reason for putting this in an anonymous module was to avoid putting pyprogramname
into the global namespace. Is this no longer a concern?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it was Julia 0.4 compatibility or something. This is executed in a subprocess which exits right after printing pyprogramname
. So I don't think we have namespace problem. It is added in fde40d7#diff-2f4f81856f2b92c6a4bb1e5bba2cf28aR260
try: | ||
yield | ||
finally: | ||
signal.signal(sig, s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a comment about what's going on here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a docstring.
test/test_core.py
Outdated
@@ -97,8 +97,8 @@ def test_from_import_non_existing_julia_name(self): | |||
def test_julia_module_bang(self): | |||
from julia import Base | |||
xs = [1, 2, 3] | |||
ys = Base.scale_b(xs[:], 2) | |||
assert all(x * 2 == y for x, y in zip(xs, ys)) | |||
ys = Base.fill_b(xs[:], 10) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not ys = Base.fill_b(xs, 10)
?
But I would just set ys = [2, 4, 6]
and keep the old test all(x * 2 == y for x, y in zip(xs, ys))
If we want to test the "bang" in-place operators we should do so with a numpy array where we can check that it is actually operating in-place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old test does not work since scale!
is gone in Julia 1.0. The easiest bang method that I could find both in Julia 0.6 and 1.0 was fill!
. And indeed xs[:]
is redundant. Thanks for catching thins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize that, but the new test doesn't actually test much. That's why I suggested just setting ys = [2, 4, 6]
and keeping the test of all
as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My intention when writing the test was just to test variable renaming code path (back then I wasn't sure if it was OK to import numpy). But now that we have it via tox, I suggest something like:
xs = numpy.zeros(3)
Base.fill_b(xs, 10)
assert all(ys == 10)
or
xs = numpy.array([1, 2, 3])
ys = xs.copy()
if julia.eval('VERSION >= v"0.7-"'):
Base.rmul_b(xs, 2)
else:
Base.scale_b(xs, 2)
assert all(2 * ys == xs)
Which one do you like?
Edit: ys = xs[:]
-> ys = xs.copy()
. Coding to much in Julia. I start forgetting Python :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, the test I proposed does not work. Strange...
def test_julia_module_bang(self):
from julia import Base
xs = numpy.zeros(3)
ys = Base.fill_b(xs, 10)
assert all(ys == 10)
> assert all(xs == 10)
E AssertionError: assert False
E + where False = all(array([0., 0., 0.]) == 10)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that was because py"xs"
was converted to PyAny
. If I do fill!(PyArray(PyCall.maindict()["xs"]), 10)
in Julia, mutation works (= it's reflected on Python side).
I'm not sure what's the right illustration of this problem in Julia. Something like this?:
julia> py"""
def apply(f):
xs = numpy.zeros(3)
f(xs)
return xs
"""
julia> py"apply"(xs -> fill!(xs, 10))
3-element Array{Float64,1}:
0.0
0.0
0.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See JuliaPy/PyCall.jl#531 (comment) … you need to specify the type conversion you want for an argument if you want in-place operations to be possible in general.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. Yes, I think explicitly denoting which argument is mutating is a good idea.
So, for this test, we just need to check the returned value, right?:
def test_julia_module_bang(self):
from julia import Base
xs = [1, 2, 3]
ys = Base.fill_b(xs, 10)
assert all(y == 10 for y in ys)
Although it may be better if we just drop _b
since users have to implement a callback on Julia side to avoid allocations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. So I think I finally found a meaningful test:
def test_julia_module_bang(self):
from julia.Base import Channel, put_b, take_b
chan = Channel(1)
sent = 123
put_b(chan, sent)
received = take_b(chan)
assert sent == received
What do you think?
In the future, I think we need an API to denote some Python values have to be passed without copying. Something like fill_b(asref(arr), 10)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the right thing to do is to make it easy to use the pyfunction
method from Julia, for cases where you need control over precisely how arguments are passed.
@mprogram Those are expected debug messages. We pass |
With
I get this error:
Investigating: and |
@noahstier look at /issues/148 for a patching hint (presently blocked by #185) |
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") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These lines above are for suppressing "Pkg.dir(pkgname, paths...)
is deprecated" warning.
- Before this change: https://travis-ci.org/JuliaPy/pyjulia/jobs/417810499#L540-L542
- After this change: https://travis-ci.org/JuliaPy/pyjulia/jobs/418083304#L540
I took the code from Pkg.dir
: https://github.com/JuliaLang/Pkg.jl/blob/df546844d98dfe233889e91a86f076e01926f69e/src/API.jl#L456-L463 (Note: Base.locate_package(::Nothing) = nothing
is defined so I don't think we need to guard against Base.identify_package
returning nothing
as Pkg.dir
does.)
Ready to merge? |
What about #183 (comment)? The problem you pointed about |
sent = 123 | ||
put_b(chan, sent) | ||
received = take_b(chan) | ||
assert sent == received |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I go ahead and I do #183 (comment) (to make sure that it works on CIs). If you prefer fill_b
or something else let me know.
If CIs and you are happy with it then I think it's ready for merge.
I wonder why appveyor is not running. There is "Intermittent issues with Chocolatey packages installation" https://appveyor.statuspage.io/incidents/kqwjgg14m71g but I don't think it's related to our setup (unless it is used internally somewhere). |
It is based on #178. It's probably better to pull #178 first to make reviewing easier.