Skip to content

Commit f64e0ff

Browse files
author
Christopher Doris
committed
dev
1 parent 05dd27d commit f64e0ff

26 files changed

+1148
-289
lines changed

juliapy/julia/__init__.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,15 @@ def _init_():
3333
lib.jl_eval_string.restype = c.c_void_p
3434
res = lib.jl_eval_string(
3535
'''
36-
ENV["PYTHONJL_LIBPTR"] = "{}"
37-
import Python
38-
Python.with_gil() do
39-
Python.pyimport("sys").modules["julia"].Main = Python.pyjl(Main)
36+
try
37+
ENV["PYTHONJL_LIBPTR"] = "{}"
38+
import Python
39+
Python.with_gil() do
40+
Python.pyimport("sys").modules["julia"].Main = Python.pyjlraw(Main)
41+
end
42+
catch err
43+
@error "Error loading Python.jl" err=err
44+
rethrow()
4045
end
4146
'''.format(c.pythonapi._handle).encode('utf8'))
4247
if res is None:

src/old/PyBuffer.jl renamed to src/PyBuffer.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
PyBuffer(o)
2+
PyBuffer(o, [flags=C.PyBUF_FULL_RO])
33
44
A reference to the underlying buffer of `o`, if it satisfies the buffer protocol.
55
@@ -20,16 +20,15 @@ Has the following properties:
2020
"""
2121
mutable struct PyBuffer
2222
info :: Array{C.Py_buffer, 0}
23-
function PyBuffer(o::PyObject, flags::Integer=C.PyBUF_FULL_RO)
23+
function PyBuffer(o, flags::Integer=C.PyBUF_FULL_RO)
2424
info = fill(C.Py_buffer())
2525
check(C.PyObject_GetBuffer(o, pointer(info), flags))
2626
b = new(info)
2727
finalizer(b) do b
2828
if CONFIG.isinitialized
29-
err = with_gil(false) do
29+
with_gil(false) do
3030
C.PyBuffer_Release(pointer(b.info))
3131
end
32-
check(err)
3332
end
3433
end
3534
b

src/PyException.jl

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mutable struct PyException <: Exception
77
end
88
export PyException
99

10-
pythrow() = throw(PyException(Val(:new), C.PyErr_FetchTuple()...))
10+
pythrow() = throw(PyException(Val(:new), C.PyErr_FetchTuple(true)...))
1111

1212
"""
1313
check(x)
@@ -81,36 +81,47 @@ function Base.showerror(io::IO, e::PyException)
8181
end
8282
end
8383

84-
# # if this is a Julia exception then recursively print it and its stacktrace
85-
# if pyerrmatches(e.t, pyjlexception)
86-
# try
87-
# jp = pyjlgetvalue(e.v.args[0])
88-
# if jp !== nothing
89-
# je, jb = jp
90-
# print(io, "Python: Julia: ")
91-
# showerror(io, je)
92-
# if jb === nothing
93-
# println(io)
94-
# print(io, "Stacktrace: none")
95-
# else
96-
# io2 = IOBuffer()
97-
# Base.show_backtrace(IOContext(io2, :color=>true, :displaysize=>displaysize(io)), jb)
98-
# printstyled(io, String(take!(io2)))
99-
# end
100-
# end
101-
# if pyisnone(e.b)
102-
# println(io)
103-
# printstyled(io, "Python stacktrace: none")
104-
# return
105-
# else
106-
# @goto pystacktrace
107-
# end
108-
# catch err
109-
# println(io, "<error while printing Julia excpetion inside Python exception: $(err)>")
110-
# end
111-
# end
112-
113-
# otherwise, print the Python exception ****** TODO ******
84+
# if this is a Julia exception then recursively print it and its stacktrace
85+
if C.PyErr_GivenExceptionMatches(e.tref, C.PyExc_JuliaError()) != 0
86+
try
87+
# Extract error value
88+
vo = @pyv `$(e.vref).args[0]`::Any
89+
if vo isa Tuple{Exception, Any}
90+
je, jb = vo
91+
else
92+
je = vo
93+
jb = nothing
94+
end
95+
print(io, "Python: Julia: ")
96+
# Show exception
97+
if je isa Exception
98+
showerror(io, je)
99+
else
100+
print(io, je)
101+
end
102+
# Show backtrace
103+
if jb === nothing
104+
println(io)
105+
print(io, "Stacktrace: none")
106+
else
107+
io2 = IOBuffer()
108+
Base.show_backtrace(IOContext(io2, :color=>true, :displaysize=>displaysize(io)), jb)
109+
printstyled(io, String(take!(io2)))
110+
end
111+
# Show Python backtrace
112+
if isnull(e.bref)
113+
println(io)
114+
printstyled(io, "Python stacktrace: none")
115+
return
116+
else
117+
@goto pystacktrace
118+
end
119+
catch err
120+
println("<error while printing Julia exception inside Python exception>")
121+
end
122+
end
123+
124+
# otherwise, print the Python exception
114125
print(io, "Python: ")
115126

116127
# print the type name

src/PyRef.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mutable struct PyRef
1414
x = new(CPyPtr(ptr))
1515
borrowed && C.Py_IncRef(ptr)
1616
finalizer(x) do x
17-
if !CONFIG.isinitialized
17+
if CONFIG.isinitialized
1818
ptr = x.ptr
1919
if !isnull(ptr)
2020
with_gil(false) do

src/Python.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,12 @@ include("PyList.jl")
9393
include("PySet.jl")
9494
include("PyIterable.jl")
9595
include("PyIO.jl")
96+
include("PyBuffer.jl")
9697
include("PyPandasDataFrame.jl")
9798

99+
include("julia.jl")
98100
include("gui.jl")
101+
include("matplotlib.jl")
99102

100103
include("init.jl")
101104

src/builtins.jl

Lines changed: 95 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -640,12 +640,6 @@ pyinv(::Type{T}, x) where {T} = cpyop(T, C.PyNumber_Invert, x)
640640
pyinv(x) = pyinv(typeof(x), x)
641641
export pyinv
642642

643-
# pycollist(x::AbstractArray{T,N}) where {T,N} = N==0 ? pyobject(x[]) : pylist_fromiter(pycollist(y) for y in eachslice(x; dims=N))
644-
# export pycollist
645-
646-
# pyrowlist(x::AbstractArray{T,N}) where {T,N} = N==0 ? pyobject(x[]) : pylist_fromiter(pyrowlist(y) for y in eachslice(x; dims=1))
647-
# export pyrowlist
648-
649643
"""
650644
pyiter([T=PyObject] x) :: T
651645
@@ -688,6 +682,101 @@ function pywith(f, _o, d=nothing)
688682
end
689683
export pywith
690684

685+
"""
686+
pytuple([T=PyObject,] [x]) :: T
687+
688+
Create a Python `tuple` from the elements of `x`.
689+
"""
690+
pytuple(::Type{T}, x) where {T} = checknullconvert(T, ispyreftype(typeof(x)) ? C.PyObject_CallNice(C.PyTuple_Type(), x) : C.PyTuple_FromIter(x))
691+
pytuple(::Type{T}) where {T} = checknullconvert(T, C.PyTuple_New(0))
692+
pytuple(x) = pytuple(PyObject, x)
693+
pytuple() = pytuple(PyObject)
694+
export pytuple
695+
696+
"""
697+
pylist([T=PyObject,] [x]) :: T
698+
699+
Create a Python `list` from the elements of `x`.
700+
"""
701+
pylist(::Type{T}, x) where {T} = checknullconvert(T, ispyreftype(typeof(x)) ? C.PyObject_CallNice(C.PyList_Type(), x) : C.PyList_FromIter(x))
702+
pylist(::Type{T}) where {T} = checknullconvert(T, C.PyList_New(0))
703+
pylist(x) = pylist(PyObject, x)
704+
pylist() = pylist(PyObject)
705+
export pylist
706+
707+
"""
708+
pycollist([T=PyObject,] x::AbstractArray) :: T
709+
710+
Create a nested Python `list`-of-`list`s from the elements of `x`. For matrices, this is a list of columns.
711+
"""
712+
pycollist(::Type{T}, x::AbstractArray) where {T} = ndims(x)==0 ? pyconvert(T, x[]) : pylist(T, pycollist(PyRef, y) for y in eachslice(x; dims=ndims(x)))
713+
pycollist(x::AbstractArray) = pycollist(PyObject, x)
714+
export pycollist
715+
716+
"""
717+
pyrowlist([T=PyObject,] x::AbstractArray) :: T
718+
719+
Create a nested Python `list`-of-`list`s from the elements of `x`. For matrices, this is a list of rows.
720+
"""
721+
pyrowlist(::Type{T}, x::AbstractArray) where {T} = ndims(x)==0 ? pyconvert(T, x[]) : pylist(T, pyrowlist(PyRef, y) for y in eachslice(x; dims=1))
722+
pyrowlist(x::AbstractArray) = pyrowlist(PyObject, x)
723+
export pyrowlist
724+
725+
"""
726+
pyset([T=PyObject,] [x]) :: T
727+
728+
Create a Python `set` from the elements of `x`.
729+
"""
730+
pyset(::Type{T}, x) where {T} = checknullconvert(T, ispyreftype(typeof(x)) ? C.PyObject_CallNice(C.PySet_Type(), x) : C.PySet_FromIter(x))
731+
pyset(::Type{T}) where {T} = checknullconvert(T, C.PySet_New(C_NULL))
732+
pyset(x) = pyset(PyObject, x)
733+
pyset() = pyset(PyObject)
734+
export pyset
735+
736+
"""
737+
pyfrozenset([T=PyObject,] [x]) :: T
738+
739+
Create a Python `frozenset` from the elements of `x`.
740+
"""
741+
pyfrozenset(::Type{T}, x) where {T} = checknullconvert(T, ispyreftype(typeof(x)) ? C.PyObject_CallNice(C.PyFrozenSet_Type(), x) : C.PyFrozenSet_FromIter(x))
742+
pyfrozenset(::Type{T}) where {T} = checknullconvert(T, C.PyFrozenSet_New(C_NULL))
743+
pyfrozenset(x) = pyfrozenset(PyObject, x)
744+
pyfrozenset() = pyfrozenset(PyObject)
745+
export pyfrozenset
746+
747+
"""
748+
pydict([T=PyObject,] [x]) :: T
749+
750+
Create a Python `dict` from the key-value pairs in `x`.
751+
"""
752+
pydict(::Type{T}, x) where {T} = checknullconvert(T, ispyreftype(typeof(x)) ? C.PyObject_CallNice(C.PyDict_Type(), x) : C.PyDict_FromPairs(x))
753+
pydict(::Type{T}) where {T} = checknullconvert(T, C.PyDict_New())
754+
pydict(x) = pydict(PyObject, x)
755+
pydict() = pydict(PyObject)
756+
export pydict
757+
758+
"""
759+
pyslice([T=PyObject,] [start,] stop, [step]) :: T
760+
761+
Equivalent to `slice(start, stop, step)` in Python (or `start:stop:step` while indexing).
762+
"""
763+
pyslice(::Type{T}, x) where {T} = cpyop(T, x->C.PySlice_New(C_NULL, x, C_NULL), x)
764+
pyslice(::Type{T}, x, y) where {T} = cpyop(T, (x,y)->C.PySlice_New(x, y, C_NULL), x, y)
765+
pyslice(::Type{T}, x, y, z) where {T} = cpyop(T, C.PySlice_New, x, y, z)
766+
pyslice(x) = pyslice(PyObject, x)
767+
pyslice(x, y) = pyslice(PyObject, x, y)
768+
pyslice(x, y, z) = pyslice(PyObject, x, y, z)
769+
export pyslice
770+
771+
"""
772+
pyellipsis([T=PyObject])
773+
774+
Equivalent to `Ellipsis` in Python (or `...` while indexing).
775+
"""
776+
pyellipsis(::Type{T}) where {T} = checknullconvert(T, C.PyEllipsis_New())
777+
pyellipsis() = pyellipsis(PyObject)
778+
export pyellipsis
779+
691780
### MULTIMEDIA DISPLAY
692781

693782
for (mime, method) in [

src/cpython/CPython.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ include("collections.jl")
5050
include("range.jl")
5151
include("ctypes.jl")
5252
include("numpy.jl")
53+
include("slice.jl")
54+
include("fraction.jl")
55+
include("newtype.jl")
56+
include("juliaerror.jl")
57+
include("juliabase.jl")
58+
include("juliaraw.jl")
59+
include("arg.jl")
5360

5461
__init__() = begin
5562
PyObject_TryConvert_AddRules("builtins.NoneType", [
@@ -124,6 +131,9 @@ __init__() = begin
124131
PyObject_TryConvert_AddRules("collections.abc.Mapping", [
125132
(Dict, PyMapping_ConvertRule_dict),
126133
])
134+
PyObject_TryConvert_AddRules("julia.ValueBase", [
135+
(Any, PyJuliaValue_TryConvert_any),
136+
])
127137
PyObject_TryConvert_AddExtraTypes([
128138
PyIterableABC_Type,
129139
PyCallableABC_Type,

0 commit comments

Comments
 (0)