Skip to content
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

Merged
merged 11 commits into from
Aug 22, 2018
Merged

Julia 1.0 support #183

merged 11 commits into from
Aug 22, 2018

Conversation

tkf
Copy link
Member

@tkf tkf commented Aug 17, 2018

It is based on #178. It's probably better to pull #178 first to make reviewing easier.

@stevengj
Copy link
Member

Needs a rebase.

@tkf
Copy link
Member Author

tkf commented Aug 17, 2018

Awesome! Thanks for the merge! It's rebased now.

@tkf
Copy link
Member Author

tkf commented Aug 17, 2018

CIs are all green now!

@mprogram
Copy link

Why then do we have:

test/test_core.py exception occured? None
exception occured? None
.exception occured? 139909767752752
...exception occured? None
exception occured? None
.exception occured? None
exception occured? None
exception occured? None
exception occured? None
exception occured? None
.......Executing: /home/travis/build/JuliaPy/pyjulia/.tox/py/bin/python -c from julia import Base
┌ Warning: `Pkg.dir(pkgname, paths...)` is deprecated; instead, do `import PyCall; joinpath(dirname(pathof(PyCall)), "..", paths...)`.
└ @ Pkg.API /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.0/Pkg/src/API.jl:454
...exception occured? None
.....                                         
test/test_magic.py Initializing Julia interpreter. This may take some time...
.Initializing Julia interpreter. This may take some time...
.Initializing Julia interpreter. This may take some time...
.Initializing Julia interpreter. This may take some time...
Exception 'ArgumentError' occurred while calling julia code:
pop!([])
.Initializing Julia interpreter. This may take some time...
Exception 'ErrorException' occurred while calling julia code:
1 += 1
.                                                       

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)
Copy link
Member

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?

Copy link
Member Author

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)
Copy link
Member

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a docstring.

@@ -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)
Copy link
Member

@stevengj stevengj Aug 17, 2018

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.

Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member Author

@tkf tkf Aug 17, 2018

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 :)

Copy link
Member Author

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)

Copy link
Member Author

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

Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member Author

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).

Copy link
Member

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.

@tkf
Copy link
Member Author

tkf commented Aug 17, 2018

@mprogram Those are expected debug messages. We pass -s option to pytest so that it's easier to debug CI but I agree it's not very clean.

@noahstier
Copy link

noahstier commented Aug 18, 2018

With julia --version -> 1.0.0 and python --version -> Python 3.5.5 :: Anaconda, Inc., if I do this:

pip install git+https://github.com/tkf/pyjulia.git@jl10
python -c "import julia; julia.Julia()"

I get this error:

┌ Warning: `Pkg.dir(pkgname, paths...)` is deprecated; instead, do `import PyCall; joinpath(dirname(pathof(PyCall)), "..", paths...)`.
└ @ Pkg.API /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.0/Pkg/src/API.jl:454
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "~/miniconda3/envs/35/lib/python3.5/site-packages/julia/core.py", line 562, in __init__
    self.__julia = Julia(*args, **kwargs)
  File "~/miniconda3/envs/35/lib/python3.5/site-packages/julia/core.py", line 440, in __init__
    "\"lib\", \"pyjulia%s-v$(VERSION.major).$(VERSION.minor)\"))" % sys.version_info[0])
  File "~/miniconda3/envs/35/lib/python3.5/site-packages/julia/core.py", line 488, in _call
    self.check_exception(src)
  File "~/miniconda3/envs/35/lib/python3.5/site-packages/julia/core.py", line 517, in check_exception
    .format(exception, src))
julia.core.JuliaError: Exception 'UndefVarError' occurred while calling julia code:
pushfirst!(Base.LOAD_CACHE_PATH, abspath(Pkg.Dir._pkgroot(),"lib", "pyjulia3-v$(VERSION.major).$(VERSION.minor)"))

Investigating:
julia -e "println(Base.LOAD_CACHE_PATH)"
gives
ERROR: UndefVarError: LOAD_CACHE_PATH not defined

and
julia -e "using Pkg; println(Pkg.Dir)"
gives
ERROR: UndefVarError: Dir not defined

@tkf
Copy link
Member Author

tkf commented Aug 18, 2018

@noahstier #185

@mprogram
Copy link

@noahstier look at /issues/148 for a patching hint (presently blocked by #185)

@tkf tkf mentioned this pull request Aug 19, 2018
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")
Copy link
Member Author

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.

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.)

@stevengj
Copy link
Member

Ready to merge?

@tkf
Copy link
Member Author

tkf commented Aug 21, 2018

What about #183 (comment)? The problem you pointed about test_julia_module_bang is not solved yet. I can apply my last suggestion if you think that's better.

sent = 123
put_b(chan, sent)
received = take_b(chan)
assert sent == received
Copy link
Member Author

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.

@tkf
Copy link
Member Author

tkf commented Aug 22, 2018

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).

@tkf tkf mentioned this pull request Aug 22, 2018
@stevengj stevengj merged commit 138d47d into JuliaPy:master Aug 22, 2018
@tkf tkf deleted the jl10 branch March 23, 2019 04:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants