diff --git a/src/PyCall.jl b/src/PyCall.jl index 71bb65e4..48004659 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -20,13 +20,6 @@ import Base: size, ndims, similar, copy, getindex, setindex!, stride, append!, insert!, prepend!, unsafe_convert import Compat: pushfirst!, popfirst!, firstindex, lastindex -# Python C API is not interrupt-safe. In principle, we should -# use sigatomic for every ccall to the Python library, but this -# should really be fixed in Julia (#2622). However, we will -# use the sigatomic_begin/end functions to protect pycall and -# similar long-running (or potentially long-running) code. -import Base: sigatomic_begin, sigatomic_end - import Conda import MacroTools # because of issue #270 import Base.Iterators: filter @@ -36,6 +29,29 @@ import Base.Iterators: filter include(joinpath(dirname(@__FILE__), "..", "deps","depsutils.jl")) include("startup.jl") +# Python C API is not interrupt-safe. This is why we use the +# `disable_sigint` function to protect *all* invocations of Python +# API. This is required since arbitrary Python function can be called +# in virtually any context. For example, a decref may call __dell__ +# which is carelessly defined to invoke a disk operation (say to flush +# buffer). Furthermore, 100% coverage is required since the +# `pyjlwrap_call` callback to Julia uses `reenable_sigint` which has +# to be called within `disable_sigint` context. In principle, this +# should really be fixed in Julia. However, although +# JuliaLang/julia#2622 is closed, ccall still does not automatically +# disable SIGINT. +macro ccall(args...) + quote + disable_sigint() do + ccall($(esc.(args)...)) + end + end +end + +macro pyccall(f, args...) + :(@ccall(@pysym($(esc(f))), $(esc.(args)...))) +end + ######################################################################### # Mirror of C PyObject struct (for non-debugging Python builds). @@ -99,7 +115,7 @@ it is equivalent to a `PyNULL()` object. ispynull(o::PyObject) = o.o == PyPtr_NULL function pydecref_(o::Union{PyPtr,PyObject}) - ccall(@pysym(:Py_DecRef), Cvoid, (PyPtr,), o) + @pyccall(:Py_DecRef, Cvoid, (PyPtr,), o) return o end @@ -110,7 +126,7 @@ function pydecref(o::PyObject) end function pyincref_(o::Union{PyPtr,PyObject}) - ccall((@pysym :Py_IncRef), Cvoid, (PyPtr,), o) + @pyccall(:Py_IncRef, Cvoid, (PyPtr,), o) return o end @@ -150,13 +166,13 @@ function Base.copy!(dest::PyObject, src::PyObject) end pyisinstance(o::PyObject, t::PyObject) = - !ispynull(t) && ccall((@pysym :PyObject_IsInstance), Cint, (PyPtr,PyPtr), o, t.o) == 1 + !ispynull(t) && @pyccall(:PyObject_IsInstance, Cint, (PyPtr,PyPtr), o, t.o) == 1 pyisinstance(o::PyObject, t::Union{Ptr{Cvoid},PyPtr}) = - t != C_NULL && ccall((@pysym :PyObject_IsInstance), Cint, (PyPtr,PyPtr), o, t) == 1 + t != C_NULL && @pyccall(:PyObject_IsInstance, Cint, (PyPtr,PyPtr), o, t) == 1 pyquery(q::Ptr{Cvoid}, o::PyObject) = - ccall(q, Cint, (PyPtr,), o) == 1 + @ccall(q, Cint, (PyPtr,), o) == 1 # conversion to pass PyObject as ccall arguments: unsafe_convert(::Type{PyPtr}, po::PyObject) = po.o @@ -171,7 +187,7 @@ PyObject(o::PyObject) = o include("exception.jl") include("gui.jl") -pytypeof(o::PyObject) = ispynull(o) ? throw(ArgumentError("NULL PyObjects have no Python type")) : PyObject(@pycheckn ccall(@pysym(:PyObject_Type), PyPtr, (PyPtr,), o)) +pytypeof(o::PyObject) = ispynull(o) ? throw(ArgumentError("NULL PyObjects have no Python type")) : PyObject(@pycheckn @pyccall(:PyObject_Type, PyPtr, (PyPtr,), o)) ######################################################################### @@ -201,7 +217,7 @@ PyObject(o::PyPtr, keep::Any) = pyembed(PyObject(o), keep) Return a string representation of `o` corresponding to `str(o)` in Python. """ pystr(o::PyObject) = convert(AbstractString, - PyObject(@pycheckn ccall((@pysym :PyObject_Str), PyPtr, + PyObject(@pycheckn @pyccall(:PyObject_Str, PyPtr, (PyPtr,), o))) """ @@ -210,7 +226,7 @@ pystr(o::PyObject) = convert(AbstractString, Return a string representation of `o` corresponding to `repr(o)` in Python. """ pyrepr(o::PyObject) = convert(AbstractString, - PyObject(@pycheckn ccall((@pysym :PyObject_Repr), PyPtr, + PyObject(@pycheckn @pyccall(:PyObject_Repr, PyPtr, (PyPtr,), o))) """ @@ -224,10 +240,10 @@ function pystring(o::PyObject) if ispynull(o) return "NULL" else - s = ccall((@pysym :PyObject_Repr), PyPtr, (PyPtr,), o) + s = @pyccall(:PyObject_Repr, PyPtr, (PyPtr,), o) if (s == C_NULL) pyerr_clear() - s = ccall((@pysym :PyObject_Str), PyPtr, (PyPtr,), o) + s = @pyccall(:PyObject_Str, PyPtr, (PyPtr,), o) if (s == C_NULL) pyerr_clear() return string(o.o) @@ -265,7 +281,7 @@ function hash(o::PyObject) # since on 64-bit Windows the Python 2.x hash is only 32 bits hashsalt(unsafe_pyjlwrap_to_objref(o.o)) else - h = ccall((@pysym :PyObject_Hash), Py_hash_t, (PyPtr,), o) + h = @pyccall(:PyObject_Hash, Py_hash_t, (PyPtr,), o) if h == -1 # error pyerr_clear() return hashsalt(o.o) @@ -283,7 +299,7 @@ function getindex(o::PyObject, s::AbstractString) if ispynull(o) throw(ArgumentError("ref of NULL PyObject")) end - p = ccall((@pysym :PyObject_GetAttrString), PyPtr, (PyPtr, Cstring), o, s) + p = @pyccall(:PyObject_GetAttrString, PyPtr, (PyPtr, Cstring), o, s) if p == C_NULL pyerr_clear() throw(KeyError(s)) @@ -297,7 +313,7 @@ function setindex!(o::PyObject, v, s::Union{Symbol,AbstractString}) if ispynull(o) throw(ArgumentError("assign of NULL PyObject")) end - if -1 == ccall((@pysym :PyObject_SetAttrString), Cint, + if -1 == @pyccall(:PyObject_SetAttrString, Cint, (PyPtr, Cstring, PyPtr), o, s, PyObject(v)) pyerr_clear() throw(KeyError(s)) @@ -309,7 +325,7 @@ function haskey(o::PyObject, s::Union{Symbol,AbstractString}) if ispynull(o) throw(ArgumentError("haskey of NULL PyObject")) end - return 1 == ccall((@pysym :PyObject_HasAttrString), Cint, + return 1 == @pyccall(:PyObject_HasAttrString, Cint, (PyPtr, Cstring), o, s) end @@ -408,7 +424,7 @@ end function _pyimport(name::AbstractString) cookie = ActivatePyActCtx() try - return PyObject(ccall((@pysym :PyImport_ImportModule), PyPtr, (Cstring,), name)) + return PyObject(@pyccall(:PyImport_ImportModule, PyPtr, (Cstring,), name)) finally DeactivatePyActCtx(cookie) end @@ -709,7 +725,7 @@ include("pyfncall.jl") # for now we can define "get". function get(o::PyObject, returntype::TypeTuple, k, default) - r = ccall((@pysym :PyObject_GetItem), PyPtr, (PyPtr,PyPtr), o,PyObject(k)) + r = @pyccall(:PyObject_GetItem, PyPtr, (PyPtr,PyPtr), o,PyObject(k)) if r == C_NULL pyerr_clear() default @@ -719,14 +735,14 @@ function get(o::PyObject, returntype::TypeTuple, k, default) end get(o::PyObject, returntype::TypeTuple, k) = - convert(returntype, PyObject(@pycheckn ccall((@pysym :PyObject_GetItem), + convert(returntype, PyObject(@pycheckn @pyccall(:PyObject_GetItem, PyPtr, (PyPtr,PyPtr), o, PyObject(k)))) get(o::PyObject, k, default) = get(o, PyAny, k, default) get(o::PyObject, k) = get(o, PyAny, k) function delete!(o::PyObject, k) - e = ccall((@pysym :PyObject_DelItem), Cint, (PyPtr, PyPtr), o, PyObject(k)) + e = @pyccall(:PyObject_DelItem, Cint, (PyPtr, PyPtr), o, PyObject(k)) if e == -1 pyerr_clear() # delete! ignores errors in Julia end @@ -734,7 +750,7 @@ function delete!(o::PyObject, k) end function set!(o::PyObject, k, v) - @pycheckz ccall((@pysym :PyObject_SetItem), Cint, (PyPtr, PyPtr, PyPtr), + @pycheckz @pyccall(:PyObject_SetItem, Cint, (PyPtr, PyPtr, PyPtr), o, PyObject(k), PyObject(v)) v end @@ -751,24 +767,24 @@ function ind2py(i::Integer) return i-1 end -_getindex(o::PyObject, i::Integer, T) = convert(T, PyObject(@pycheckn ccall((@pysym :PySequence_GetItem), PyPtr, (PyPtr, Int), o, ind2py(i)))) +_getindex(o::PyObject, i::Integer, T) = convert(T, PyObject(@pycheckn @pyccall(:PySequence_GetItem, PyPtr, (PyPtr, Int), o, ind2py(i)))) getindex(o::PyObject, i::Integer) = _getindex(o, i, PyAny) function setindex!(o::PyObject, v, i::Integer) - @pycheckz ccall((@pysym :PySequence_SetItem), Cint, (PyPtr, Int, PyPtr), o, ind2py(i), PyObject(v)) + @pycheckz @pyccall(:PySequence_SetItem, Cint, (PyPtr, Int, PyPtr), o, ind2py(i), PyObject(v)) v end getindex(o::PyObject, i1::Integer, i2::Integer) = get(o, (ind2py(i1),ind2py(i2))) setindex!(o::PyObject, v, i1::Integer, i2::Integer) = set!(o, (ind2py(i1),ind2py(i2)), v) getindex(o::PyObject, I::Integer...) = get(o, map(ind2py, I)) setindex!(o::PyObject, v, I::Integer...) = set!(o, map(ind2py, I), v) -length(o::PyObject) = @pycheckz ccall((@pysym :PySequence_Size), Int, (PyPtr,), o) +length(o::PyObject) = @pycheckz @pyccall(:PySequence_Size, Int, (PyPtr,), o) size(o::PyObject) = (length(o),) firstindex(o::PyObject) = 1 lastindex(o::PyObject) = length(o) function splice!(a::PyObject, i::Integer) v = a[i] - @pycheckz ccall((@pysym :PySequence_DelItem), Cint, (PyPtr, Int), a, i-1) + @pycheckz @pyccall(:PySequence_DelItem, Cint, (PyPtr, Int), a, i-1) v end @@ -777,20 +793,20 @@ popfirst!(a::PyObject) = splice!(a, 1) function empty!(a::PyObject) for i in length(a):-1:1 - @pycheckz ccall((@pysym :PySequence_DelItem), Cint, (PyPtr, Int), a, i-1) + @pycheckz @pyccall(:PySequence_DelItem, Cint, (PyPtr, Int), a, i-1) end a end # The following operations only work for the list type and subtypes thereof: function push!(a::PyObject, item) - @pycheckz ccall((@pysym :PyList_Append), Cint, (PyPtr, PyPtr), + @pycheckz @pyccall(:PyList_Append, Cint, (PyPtr, PyPtr), a, PyObject(item)) a end function insert!(a::PyObject, i::Integer, item) - @pycheckz ccall((@pysym :PyList_Insert), Cint, (PyPtr, Int, PyPtr), + @pycheckz @pyccall(:PyList_Insert, Cint, (PyPtr, Int, PyPtr), a, ind2py(i), PyObject(item)) a end @@ -816,7 +832,7 @@ function append!(a::PyObject, items) end append!(a::PyObject, items::PyObject) = - PyObject(@pycheckn ccall((@pysym :PySequence_InPlaceConcat), + PyObject(@pycheckn @pyccall(:PySequence_InPlaceConcat, PyPtr, (PyPtr, PyPtr), a, items)) ######################################################################### diff --git a/src/callback.jl b/src/callback.jl index 55d84936..1c5b629d 100644 --- a/src/callback.jl +++ b/src/callback.jl @@ -47,7 +47,9 @@ function _pyjlwrap_call(f, args_::PyPtr, kw_::PyPtr) end pyjlwrap_call(self_::PyPtr, args_::PyPtr, kw_::PyPtr) = - _pyjlwrap_call(unsafe_pyjlwrap_to_objref(self_), args_, kw_) + reenable_sigint() do + _pyjlwrap_call(unsafe_pyjlwrap_to_objref(self_), args_, kw_) + end ################################################################ # allow the user to convert a Julia function into a Python diff --git a/src/conversions.jl b/src/conversions.jl index ab681ae5..d8919302 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -6,24 +6,24 @@ # conversions from Julia types to PyObject: @static if pyversion < v"3" - PyObject(i::Unsigned) = PyObject(@pycheckn ccall(@pysym(:PyInt_FromSize_t), + PyObject(i::Unsigned) = PyObject(@pycheckn @pyccall(:PyInt_FromSize_t, PyPtr, (UInt,), i)) - PyObject(i::Integer) = PyObject(@pycheckn ccall(@pysym(:PyInt_FromSsize_t), + PyObject(i::Integer) = PyObject(@pycheckn @pyccall(:PyInt_FromSsize_t, PyPtr, (Int,), i)) else - PyObject(i::Unsigned) = PyObject(@pycheckn ccall(@pysym(:PyLong_FromUnsignedLongLong), + PyObject(i::Unsigned) = PyObject(@pycheckn @pyccall(:PyLong_FromUnsignedLongLong, PyPtr, (Culonglong,), i)) - PyObject(i::Integer) = PyObject(@pycheckn ccall(@pysym(:PyLong_FromLongLong), + PyObject(i::Integer) = PyObject(@pycheckn @pyccall(:PyLong_FromLongLong, PyPtr, (Clonglong,), i)) end -PyObject(b::Bool) = PyObject(@pycheckn ccall((@pysym :PyBool_FromLong), +PyObject(b::Bool) = PyObject(@pycheckn @pyccall(:PyBool_FromLong, PyPtr, (Clong,), b)) -PyObject(r::Real) = PyObject(@pycheckn ccall((@pysym :PyFloat_FromDouble), +PyObject(r::Real) = PyObject(@pycheckn @pyccall(:PyFloat_FromDouble, PyPtr, (Cdouble,), r)) -PyObject(c::Complex) = PyObject(@pycheckn ccall((@pysym :PyComplex_FromDoubles), +PyObject(c::Complex) = PyObject(@pycheckn @pyccall(:PyComplex_FromDoubles, PyPtr, (Cdouble,Cdouble), real(c), imag(c))) @@ -33,33 +33,33 @@ PyObject(n::Nothing) = pyerr_check("PyObject(nothing)", pyincref(pynothing[])) @static if pyversion < v"3" convert(::Type{T}, po::PyObject) where {T<:Integer} = - T(@pycheck ccall(@pysym(:PyInt_AsSsize_t), Int, (PyPtr,), po)) + T(@pycheck @pyccall(:PyInt_AsSsize_t, Int, (PyPtr,), po)) elseif pyversion < v"3.2" convert(::Type{T}, po::PyObject) where {T<:Integer} = - T(@pycheck ccall(@pysym(:PyLong_AsLongLong), Clonglong, (PyPtr,), po)) + T(@pycheck @pyccall(:PyLong_AsLongLong, Clonglong, (PyPtr,), po)) else function convert(::Type{T}, po::PyObject) where {T<:Integer} overflow = Ref{Cint}() - val = T(@pycheck ccall(@pysym(:PyLong_AsLongLongAndOverflow), Clonglong, (PyPtr, Ref{Cint}), po, overflow)) + val = T(@pycheck @pyccall(:PyLong_AsLongLongAndOverflow, Clonglong, (PyPtr, Ref{Cint}), po, overflow)) iszero(overflow[]) || throw(InexactError(:convert, T, po)) return val end function convert(::Type{Integer}, po::PyObject) overflow = Ref{Cint}() - val = @pycheck ccall(@pysym(:PyLong_AsLongLongAndOverflow), Clonglong, (PyPtr, Ref{Cint}), po, overflow) + val = @pycheck @pyccall(:PyLong_AsLongLongAndOverflow, Clonglong, (PyPtr, Ref{Cint}), po, overflow) iszero(overflow[]) || return convert(BigInt, po) return val end end convert(::Type{Bool}, po::PyObject) = - 0 != @pycheck ccall(@pysym(:PyObject_IsTrue), Cint, (PyPtr,), po) + 0 != @pycheck @pyccall(:PyObject_IsTrue, Cint, (PyPtr,), po) convert(::Type{T}, po::PyObject) where {T<:Real} = - T(@pycheck ccall(@pysym(:PyFloat_AsDouble), Cdouble, (PyPtr,), po)) + T(@pycheck @pyccall(:PyFloat_AsDouble, Cdouble, (PyPtr,), po)) convert(::Type{T}, po::PyObject) where T<:Complex = - T(@pycheck ccall(@pysym(:PyComplex_AsCComplex), Complex{Cdouble}, (PyPtr,), po)) + T(@pycheck @pyccall(:PyComplex_AsCComplex, Complex{Cdouble}, (PyPtr,), po)) convert(::Type{Nothing}, po::PyObject) = nothing @@ -69,7 +69,7 @@ convert(::Type{Nothing}, po::PyObject) = nothing function PyObject(s::AbstractString) sb = String(s) if pyunicode_literals || !isascii(sb) - PyObject(@pycheckn ccall(@pysym(PyUnicode_DecodeUTF8), + PyObject(@pycheckn @pyccall(PyUnicode_DecodeUTF8, PyPtr, (Ptr{UInt8}, Int, Ptr{UInt8}), sb, sizeof(sb), C_NULL)) else @@ -81,10 +81,10 @@ const _ps_ptr= Ptr{UInt8}[C_NULL] const _ps_len = Int[0] function convert(::Type{T}, po::PyObject) where T<:AbstractString if pyisinstance(po, @pyglobalobj :PyUnicode_Type) - convert(T, PyObject(@pycheckn ccall(@pysym(PyUnicode_AsUTF8String), + convert(T, PyObject(@pycheckn @pyccall(PyUnicode_AsUTF8String, PyPtr, (PyPtr,), po))) else - @pycheckz ccall(@pysym(PyString_AsStringAndSize), + @pycheckz @pyccall(PyString_AsStringAndSize, Cint, (PyPtr, Ptr{Ptr{UInt8}}, Ptr{Int}), po, _ps_ptr, _ps_len) convert(T, unsafe_string(_ps_ptr[1], _ps_len[1])) @@ -107,7 +107,7 @@ function PyObject(a::DenseVector{UInt8}) return array2py(a) # fallback to non-NumPy version end end - PyObject(@pycheckn ccall((@pysym :PyByteArray_FromStringAndSize), + PyObject(@pycheckn @pyccall(:PyByteArray_FromStringAndSize, PyPtr, (Ptr{UInt8}, Int), a, length(a))) end @@ -134,9 +134,9 @@ function convert(::Type{Ptr{Cvoid}}, po::PyObject) pynothing_query(v) == Nothing ? C_NULL : convert(Ptr{Cvoid}, convert(UInt, po["value"])) elseif pyisinstance(po, @pyglobalobj(:PyCapsule_Type)) - @pycheck ccall((@pysym :PyCapsule_GetPointer), + @pycheck @pyccall(:PyCapsule_GetPointer, Ptr{Cvoid}, (PyPtr,Ptr{UInt8}), - po, ccall((@pysym :PyCapsule_GetName), + po, @pyccall(:PyCapsule_GetName, Ptr{UInt8}, (PyPtr,), po)) else convert(Ptr{Cvoid}, convert(UInt, po)) @@ -178,10 +178,10 @@ convert(::Type{Function}, po::PyObject) = function PyObject(t::Union{Tuple,Pair}) len = lastindex(t) # lastindex, not length, because of julia#14924 - o = PyObject(@pycheckn ccall((@pysym :PyTuple_New), PyPtr, (Int,), len)) + o = PyObject(@pycheckn @pyccall(:PyTuple_New, PyPtr, (Int,), len)) for i = 1:len oi = PyObject(t[i]) - @pycheckz ccall((@pysym :PyTuple_SetItem), Cint, (PyPtr,Int,PyPtr), + @pycheckz @pyccall(:PyTuple_SetItem, Cint, (PyPtr,Int,PyPtr), o, i-1, oi) pyincref(oi) # PyTuple_SetItem steals the reference end @@ -204,13 +204,13 @@ isvatuple(T::DataType) = !isempty(T.parameters) && Base.isvarargtype(T.parameter function convert(tt::Type{T}, o::PyObject) where T<:Tuple isva = isvatuple(T) - len = @pycheckz ccall((@pysym :PySequence_Size), Int, (PyPtr,), o) + len = @pycheckz @pyccall(:PySequence_Size, Int, (PyPtr,), o) if !istuplen(tt, isva, len) throw(BoundsError()) end ntuple((i -> convert(tuptype(T, isva, i), - PyObject(ccall((@pysym :PySequence_GetItem), PyPtr, + PyObject(@pyccall(:PySequence_GetItem, PyPtr, (PyPtr, Int), o, i-1)))), len) end @@ -259,11 +259,11 @@ eltype(::Type{PyVector{T}}) where {T} = pyany_toany(T) size(a::PyVector) = (length(a.o),) getindex(a::PyVector) = getindex(a, 1) -getindex(a::PyVector{T}, i::Integer) where {T} = convert(T, PyObject(@pycheckn ccall((@pysym :PySequence_GetItem), PyPtr, (PyPtr, Int), a, i-1))) +getindex(a::PyVector{T}, i::Integer) where {T} = convert(T, PyObject(@pycheckn @pyccall(:PySequence_GetItem, PyPtr, (PyPtr, Int), a, i-1))) setindex!(a::PyVector, v) = setindex!(a, v, 1) function setindex!(a::PyVector, v, i::Integer) - @pycheckz ccall((@pysym :PySequence_SetItem), Cint, (PyPtr, Int, PyPtr), a, i-1, PyObject(v)) + @pycheckz @pyccall(:PySequence_SetItem, Cint, (PyPtr, Int, PyPtr), a, i-1, PyObject(v)) v end @@ -274,7 +274,7 @@ splice!(a::PyVector, i::Integer) = splice!(a.o, i) function splice!(a::PyVector{T}, indices::AbstractVector{I}) where {T,I<:Integer} v = pyany_toany(T)[a[i] for i in indices] for i in sort(indices, rev=true) - @pycheckz ccall((@pysym :PySequence_DelItem), Cint, (PyPtr, Int), a, i-1) + @pycheckz @pyccall(:PySequence_DelItem, Cint, (PyPtr, Int), a, i-1) end v end @@ -300,10 +300,10 @@ function array2py(A::AbstractArray{T, N}, dim::Integer, i::Integer) where {T, N} elseif dim == N # special case last dim to coarsen recursion leaves len = size(A, dim) s = N == 1 ? 1 : stride(A, dim) - o = PyObject(@pycheckn ccall((@pysym :PyList_New), PyPtr, (Int,), len)) + o = PyObject(@pycheckn @pyccall(:PyList_New, PyPtr, (Int,), len)) for j = 0:len-1 oi = PyObject(A[i+j*s]) - @pycheckz ccall((@pysym :PyList_SetItem), Cint, (PyPtr,Int,PyPtr), + @pycheckz @pyccall(:PyList_SetItem, Cint, (PyPtr,Int,PyPtr), o, j, oi) pyincref(oi) # PyList_SetItem steals the reference end @@ -311,10 +311,10 @@ function array2py(A::AbstractArray{T, N}, dim::Integer, i::Integer) where {T, N} else # dim < N: store multidimensional array as list of lists len = size(A, dim) s = stride(A, dim) - o = PyObject(@pycheckn ccall((@pysym :PyList_New), PyPtr, (Int,), len)) + o = PyObject(@pycheckn @pyccall(:PyList_New, PyPtr, (Int,), len)) for j = 0:len-1 oi = array2py(A, dim+1, i+j*s) - @pycheckz ccall((@pysym :PyList_SetItem), Cint, (PyPtr,Int,PyPtr), + @pycheckz @pyccall(:PyList_SetItem, Cint, (PyPtr,Int,PyPtr), o, j, oi) pyincref(oi) # PyList_SetItem steals the reference end @@ -334,24 +334,24 @@ function py2array(T, A::Array{TA,N}, o::PyObject, A[i] = convert(T, o) return A elseif dim == N - len = @pycheckz ccall((@pysym :PySequence_Size), Int, (PyPtr,), o) + len = @pycheckz @pyccall(:PySequence_Size, Int, (PyPtr,), o) if len != size(A, dim) error("dimension mismatch in py2array") end s = stride(A, dim) for j = 0:len-1 - A[i+j*s] = convert(T, PyObject(ccall((@pysym :PySequence_GetItem), + A[i+j*s] = convert(T, PyObject(@pyccall(:PySequence_GetItem, PyPtr, (PyPtr, Int), o, j))) end return A else # dim < N: recursively extract list of lists into A - len = @pycheckz ccall((@pysym :PySequence_Size), Int, (PyPtr,), o) + len = @pycheckz @pyccall(:PySequence_Size, Int, (PyPtr,), o) if len != size(A, dim) error("dimension mismatch in py2array") end s = stride(A, dim) for j = 0:len-1 - py2array(T, A, PyObject(ccall((@pysym :PySequence_GetItem), + py2array(T, A, PyObject(@pyccall(:PySequence_GetItem, PyPtr, (PyPtr, Int), o, j)), dim+1, i+j*s) end @@ -365,18 +365,18 @@ function pyarray_dims(o::PyObject, forcelist=true) if !(forcelist || pyisinstance(o, @pyglobalobj :PyList_Type)) return () # too many non-List types can pretend to be sequences end - len = ccall((@pysym :PySequence_Size), Int, (PyPtr,), o) + len = @pyccall(:PySequence_Size, Int, (PyPtr,), o) if len == 0 return (0,) end - dims0 = pyarray_dims(PyObject(ccall((@pysym :PySequence_GetItem), + dims0 = pyarray_dims(PyObject(@pyccall(:PySequence_GetItem, PyPtr, (PyPtr, Int), o, 0)), false) if isempty(dims0) # not a nested sequence return (len,) end for j = 1:len-1 - dims = pyarray_dims(PyObject(ccall((@pysym :PySequence_GetItem), + dims = pyarray_dims(PyObject(@pyccall(:PySequence_GetItem, PyPtr, (PyPtr, Int), o, j)), false) if dims != dims0 @@ -395,7 +395,7 @@ function py2array(T, o::PyObject) end function convert(::Type{Vector{T}}, o::PyObject) where T - len = ccall((@pysym :PySequence_Size), Int, (PyPtr,), o) + len = @pyccall(:PySequence_Size, Int, (PyPtr,), o) if len < 0 || # not a sequence len+1 < 0 # object pretending to be a sequence of infinite length pyerr_clear() @@ -421,7 +421,7 @@ include("numpy.jl") function is_mapping_object(o::PyObject) pyisinstance(o, @pyglobalobj :PyDict_Type) || (pyquery((@pyglobal :PyMapping_Check), o) && - ccall((@pysym :PyObject_HasAttrString), Cint, (PyPtr,Ptr{UInt8}), o, "items") == 1) + @pyccall(:PyObject_HasAttrString, Cint, (PyPtr,Ptr{UInt8}), o, "items") == 1) end """ @@ -445,7 +445,7 @@ mutable struct PyDict{K,V,isdict} <: AbstractDict{K,V} end PyDict{K,V}(o::PyObject) where {K,V} = PyDict{K,V,pyisinstance(o, @pyglobalobj :PyDict_Type)}(o) -PyDict{K,V}() where {K,V} = PyDict{K,V,true}(PyObject(@pycheckn ccall((@pysym :PyDict_New), PyPtr, ()))) +PyDict{K,V}() where {K,V} = PyDict{K,V,true}(PyObject(@pycheckn @pyccall(:PyDict_New, PyPtr, ()))) PyDict(o::PyObject) = PyDict{PyAny,PyAny}(o) PyObject(d::PyDict) = d.o @@ -458,13 +458,13 @@ convert(::Type{PyDict}, o::PyObject) = PyDict(o) convert(::Type{PyDict{K,V}}, o::PyObject) where {K,V} = PyDict{K,V}(o) unsafe_convert(::Type{PyPtr}, d::PyDict) = d.o.o -haskey(d::PyDict{K,V,true}, key) where {K,V} = 1 == ccall(@pysym(:PyDict_Contains), Cint, (PyPtr, PyPtr), d, PyObject(key)) -keys(::Type{T}, d::PyDict{K,V,true}) where {T,K,V} = convert(Vector{T}, PyObject(@pycheckn ccall((@pysym :PyDict_Keys), PyPtr, (PyPtr,), d))) -values(::Type{T}, d::PyDict{K,V,true}) where {T,K,V} = convert(Vector{T}, PyObject(@pycheckn ccall((@pysym :PyDict_Values), PyPtr, (PyPtr,), d))) +haskey(d::PyDict{K,V,true}, key) where {K,V} = 1 == @pyccall(:PyDict_Contains, Cint, (PyPtr, PyPtr), d, PyObject(key)) +keys(::Type{T}, d::PyDict{K,V,true}) where {T,K,V} = convert(Vector{T}, PyObject(@pycheckn @pyccall(:PyDict_Keys, PyPtr, (PyPtr,), d))) +values(::Type{T}, d::PyDict{K,V,true}) where {T,K,V} = convert(Vector{T}, PyObject(@pycheckn @pyccall(:PyDict_Values, PyPtr, (PyPtr,), d))) keys(::Type{T}, d::PyDict{K,V,false}) where {T,K,V} = convert(Vector{T}, pycall(d.o["keys"], PyObject)) values(::Type{T}, d::PyDict{K,V,false}) where {T,K,V} = convert(Vector{T}, pycall(d.o["values"], PyObject)) -haskey(d::PyDict{K,V,false}, key) where {K,V} = 1 == ccall(@pysym(:PyMapping_HasKey), Cint, (PyPtr, PyPtr), d, PyObject(key)) +haskey(d::PyDict{K,V,false}, key) where {K,V} = 1 == @pyccall(:PyMapping_HasKey, Cint, (PyPtr, PyPtr), d, PyObject(key)) similar(d::PyDict{K,V}) where {K,V} = Dict{pyany_toany(K),pyany_toany(V)}() eltype(::Type{PyDict{K,V}}) where {K,V} = Pair{pyany_toany(K),pyany_toany(V)} @@ -474,7 +474,7 @@ Base.keytype(::Type{PyDict{K,V}}) where {K,V} = pyany_toany(K) Base.valtype(::Type{PyDict{K,V}}) where {K,V} = pyany_toany(V) function setindex!(d::PyDict, v, k) - @pycheckz ccall((@pysym :PyObject_SetItem), Cint, (PyPtr, PyPtr, PyPtr), + @pycheckz @pyccall(:PyObject_SetItem, Cint, (PyPtr, PyPtr, PyPtr), d, PyObject(k), PyObject(v)) v end @@ -483,12 +483,12 @@ get(d::PyDict{K,V}, k, default) where {K,V} = get(d.o, V, k, default) function pop!(d::PyDict{K,V,true}, k) where {K,V} v = d[k] - @pycheckz ccall(@pysym(:PyDict_DelItem), Cint, (PyPtr, PyPtr), d, PyObject(k)) + @pycheckz @pyccall(:PyDict_DelItem, Cint, (PyPtr, PyPtr), d, PyObject(k)) return v end function pop!(d::PyDict{K,V,false}, k) where {K,V} v = d[k] - @pycheckz ccall(@pysym(:PyObject_DelItem), Cint, (PyPtr, PyPtr), d, PyObject(k)) + @pycheckz @pyccall(:PyObject_DelItem, Cint, (PyPtr, PyPtr), d, PyObject(k)) return v end @@ -501,18 +501,18 @@ function pop!(d::PyDict, k, default) end function delete!(d::PyDict{K,V,true}, k) where {K,V} - e = ccall(@pysym(:PyDict_DelItem), Cint, (PyPtr, PyPtr), d, PyObject(k)) + e = @pyccall(:PyDict_DelItem, Cint, (PyPtr, PyPtr), d, PyObject(k)) e == -1 && pyerr_clear() # delete! ignores errors in Julia return d end function delete!(d::PyDict{K,V,false}, k) where {K,V} - e = ccall(@pysym(:PyObject_DelItem), Cint, (PyPtr, PyPtr), d, PyObject(k)) + e = @pyccall(:PyObject_DelItem, Cint, (PyPtr, PyPtr), d, PyObject(k)) e == -1 && pyerr_clear() # delete! ignores errors in Julia return d end function empty!(d::PyDict{K,V,true}) where {K,V} - @pycheck ccall((@pysym :PyDict_Clear), Cvoid, (PyPtr,), d) + @pycheck @pyccall(:PyDict_Clear, Cvoid, (PyPtr,), d) return d end function empty!(d::PyDict{K,V,false}) where {K,V} @@ -523,8 +523,8 @@ function empty!(d::PyDict{K,V,false}) where {K,V} return d end -length(d::PyDict{K,V,true}) where {K,V} = @pycheckz ccall(@pysym(:PyDict_Size), Int, (PyPtr,), d) -length(d::PyDict{K,V,false}) where {K,V} = @pycheckz ccall(@pysym(:PyObject_Size), Int, (PyPtr,), d) +length(d::PyDict{K,V,true}) where {K,V} = @pycheckz @pyccall(:PyDict_Size, Int, (PyPtr,), d) +length(d::PyDict{K,V,false}) where {K,V} = @pycheckz @pyccall(:PyObject_Size, Int, (PyPtr,), d) isempty(d::PyDict) = length(d) == 0 @@ -540,7 +540,7 @@ end Base.start(d::PyDict{K,V,true}) where {K,V} = PyDict_Iterator(Ref{PyPtr}(), Ref{PyPtr}(), Ref(0), 0, length(d)) Base.done(d::PyDict{K,V,true}, itr::PyDict_Iterator) where {K,V} = itr.i >= itr.len function Base.next(d::PyDict{K,V,true}, itr::PyDict_Iterator) where {K,V} - if 0 == ccall((@pysym :PyDict_Next), Cint, + if 0 == @pyccall(:PyDict_Next, Cint, (PyPtr, Ref{Int}, Ref{PyPtr}, Ref{PyPtr}), d, itr.pa, itr.ka, itr.va) error("unexpected end of PyDict_Next") @@ -558,13 +558,13 @@ end Base.start(d::PyDict{K,V,false}) where {K,V} = start(pycall(d.o["items"], PyObject)) Base.done(d::PyDict{K,V,false}, s) where {K,V} = done(d.o, s) function Base.next(d::PyDict{K,V,false}, s) where {K,V} - nxt = PyObject(@pycheck ccall((@pysym :PyIter_Next), PyPtr, (PyPtr,), s[2])) + nxt = PyObject(@pycheck @pyccall(:PyIter_Next, PyPtr, (PyPtr,), s[2])) return (convert(Pair{K,V}, s[1]), (nxt, s[2])) end else function Base.iterate(d::PyDict{K,V,true}, itr=PyDict_Iterator(Ref{PyPtr}(), Ref{PyPtr}(), Ref(0), 0, length(d))) where {K,V} itr.i >= itr.len && return nothing - if 0 == ccall((@pysym :PyDict_Next), Cint, + if 0 == @pyccall(:PyDict_Next, Cint, (PyPtr, Ref{Int}, Ref{PyPtr}, Ref{PyPtr}), d, itr.pa, itr.ka, itr.va) error("unexpected end of PyDict_Next") @@ -595,9 +595,9 @@ end # Dictionary conversions (copies) function PyObject(d::AbstractDict) - o = PyObject(@pycheckn ccall((@pysym :PyDict_New), PyPtr, ())) + o = PyObject(@pycheckn @pyccall(:PyDict_New, PyPtr, ())) for k in keys(d) - @pycheckz ccall((@pysym :PyDict_SetItem), Cint, (PyPtr,PyPtr,PyPtr), + @pycheckz @pyccall(:PyDict_SetItem, Cint, (PyPtr,PyPtr,PyPtr), o, PyObject(k), PyObject(d[k])) end return o @@ -701,7 +701,7 @@ pymp_query(o::PyObject) = pyisinstance(o, mpf) ? BigFloat : pyisinstance(o, mpc) const LongInt = @static (Sys.WORD_SIZE==32) ? Union{Int64,UInt64,Int128,UInt128,BigInt} : Union{Int128,UInt128,BigInt} function PyObject(i::LongInt) - PyObject(@pycheckn ccall((@pysym :PyLong_FromString), PyPtr, + PyObject(@pycheckn @pyccall(:PyLong_FromString, PyPtr, (Ptr{UInt8}, Ptr{Cvoid}, Cint), String(string(i)), C_NULL, 10)) end @@ -762,8 +762,8 @@ function pysequence_query(o::PyObject) # scipy define "fake" sequence types with intmax lengths and other # problems if pyisinstance(o, @pyglobalobj :PyTuple_Type) - len = @pycheckz ccall((@pysym :PySequence_Size), Int, (PyPtr,), o) - return typetuple(pytype_query(PyObject(ccall((@pysym :PySequence_GetItem), PyPtr, (PyPtr,Int), o,i-1)), PyAny) for i = 1:len) + len = @pycheckz @pyccall(:PySequence_Size, Int, (PyPtr,), o) + return typetuple(pytype_query(PyObject(@pyccall(:PySequence_GetItem, PyPtr, (PyPtr,Int), o,i-1)), PyAny) for i = 1:len) elseif pyisinstance(o, pyxrange[]) return AbstractRange elseif ispybytearray(o) diff --git a/src/exception.jl b/src/exception.jl index 1b750fd3..d36b2ec9 100644 --- a/src/exception.jl +++ b/src/exception.jl @@ -16,9 +16,9 @@ struct PyError <: Exception exc = Array{PyPtr}(undef, 3) pexc = convert(UInt, pointer(exc)) # equivalent of passing C pointers &exc[1], &exc[2], &exc[3]: - ccall((@pysym :PyErr_Fetch), Cvoid, (UInt,UInt,UInt), + @pyccall(:PyErr_Fetch, Cvoid, (UInt,UInt,UInt), pexc, pexc + sizeof(PyPtr), pexc + 2*sizeof(PyPtr)) - ccall((@pysym :PyErr_NormalizeException), Cvoid, (UInt,UInt,UInt), + @pyccall(:PyErr_NormalizeException, Cvoid, (UInt,UInt,UInt), pexc, pexc + sizeof(PyPtr), pexc + 2*sizeof(PyPtr)) new(msg, PyObject(exc[1]), PyObject(exc[2]), PyObject(exc[3])) end @@ -51,10 +51,10 @@ end # Conversion of Python exceptions into Julia exceptions # whether a Python exception has occurred -pyerr_occurred() = ccall((@pysym :PyErr_Occurred), PyPtr, ()) != C_NULL +pyerr_occurred() = @pyccall(:PyErr_Occurred, PyPtr, ()) != C_NULL # call to discard Python exceptions -pyerr_clear() = ccall((@pysym :PyErr_Clear), Cvoid, ()) +pyerr_clear() = @pyccall(:PyErr_Clear, Cvoid, ()) function pyerr_check(msg::AbstractString, val::Any) pyerr_occurred() && throw(PyError(msg)) @@ -126,12 +126,12 @@ end function pyraise(e) eT = typeof(e) pyeT = haskey(pyexc::Dict, eT) ? pyexc[eT] : pyexc[Exception] - ccall((@pysym :PyErr_SetString), Cvoid, (PyPtr, Cstring), + @pyccall(:PyErr_SetString, Cvoid, (PyPtr, Cstring), pyeT, string("Julia exception: ", e)) end function pyraise(e::PyError) - ccall((@pysym :PyErr_Restore), Cvoid, (PyPtr, PyPtr, PyPtr), + @pyccall(:PyErr_Restore, Cvoid, (PyPtr, PyPtr, PyPtr), e.T, e.val, e.traceback) e.T.o = e.val.o = e.traceback.o = C_NULL # refs were stolen end diff --git a/src/gc.jl b/src/gc.jl index 2492f46a..3f798699 100644 --- a/src/gc.jl +++ b/src/gc.jl @@ -15,7 +15,7 @@ const pycall_gc = Dict{PyPtr,Any}() function weakref_callback(callback::PyPtr, wo::PyPtr) delete!(pycall_gc, wo) - ccall((@pysym :Py_DecRef), Cvoid, (PyPtr,), wo) + @pyccall(:Py_DecRef, Cvoid, (PyPtr,), wo) return pyincref_(pynothing[]) end @@ -34,11 +34,11 @@ function pyembed(po::PyObject, jo::Any) cf = @cfunction(weakref_callback, PyPtr, (PyPtr,PyPtr)) weakref_callback_meth[] = PyMethodDef("weakref_callback", cf, METH_O) copy!(weakref_callback_obj, - PyObject(@pycheckn ccall((@pysym :PyCFunction_NewEx), PyPtr, + PyObject(@pycheckn @pyccall(:PyCFunction_NewEx, PyPtr, (Ref{PyMethodDef}, Ptr{Cvoid}, Ptr{Cvoid}), weakref_callback_meth, C_NULL, C_NULL))) end - wo = @pycheckn ccall((@pysym :PyWeakref_NewRef), PyPtr, (PyPtr,PyPtr), + wo = @pycheckn @pyccall(:PyWeakref_NewRef, PyPtr, (PyPtr,PyPtr), po, weakref_callback_obj) pycall_gc[wo] = jo return po diff --git a/src/io.jl b/src/io.jl index 91c28625..c4fde8e7 100644 --- a/src/io.jl +++ b/src/io.jl @@ -10,7 +10,7 @@ # IO objects should raise IOError for unsupported operations or failed IO function ioraise(e) if isa(e, MethodError) || isa(e, ErrorException) - ccall((@pysym :PyErr_SetString), Cvoid, (PyPtr, Cstring), + @pyccall(:PyErr_SetString, Cvoid, (PyPtr, Cstring), (pyexc::Dict)[PyIOError], string("Julia exception: ", e)) else diff --git a/src/numpy.jl b/src/numpy.jl index 542b8b9b..c6c87271 100644 --- a/src/numpy.jl +++ b/src/numpy.jl @@ -50,11 +50,11 @@ function npyinitialize() error("numpy.core.multiarray required for multidimensional Array conversions - ", e) end if pyversion.major < 3 - PyArray_API = @pycheck ccall((@pysym :PyCObject_AsVoidPtr), + PyArray_API = @pycheck @pyccall(:PyCObject_AsVoidPtr, Ptr{Ptr{Cvoid}}, (PyPtr,), npy_multiarray["_ARRAY_API"]) else - PyArray_API = @pycheck ccall((@pysym :PyCapsule_GetPointer), + PyArray_API = @pycheck @pyccall(:PyCapsule_GetPointer, Ptr{Ptr{Cvoid}}, (PyPtr,Ptr{Cvoid}), npy_multiarray["_ARRAY_API"], C_NULL) end @@ -189,7 +189,7 @@ function NpyArray(a::StridedArray{T}, revdims::Bool) where T<:NPY_TYPES @npyinitialize size_a = revdims ? reverse(size(a)) : size(a) strides_a = revdims ? reverse(strides(a)) : strides(a) - p = @pycheck ccall(npy_api[:PyArray_New], PyPtr, + p = @pycheck @ccall(npy_api[:PyArray_New], PyPtr, (PyPtr,Cint,Ptr{Int},Cint, Ptr{Int},Ptr{T}, Cint,Cint,PyPtr), npy_api[:PyArray_Type], ndims(a), Int[size_a...], npy_type(T), @@ -449,7 +449,7 @@ function convert(::Type{Array{T, 1}}, o::PyObject) where T<:NPY_TYPES try copy(PyArray{T, 1}(o, PyArray_Info(o))) # will check T and N vs. info catch - len = @pycheckz ccall((@pysym :PySequence_Size), Int, (PyPtr,), o) + len = @pycheckz @pyccall(:PySequence_Size, Int, (PyPtr,), o) A = Array{pyany_toany(T)}(undef, len) py2array(T, A, o, 1, 1) end diff --git a/src/pybuffer.jl b/src/pybuffer.jl index 06295261..518fe7df 100644 --- a/src/pybuffer.jl +++ b/src/pybuffer.jl @@ -41,7 +41,7 @@ function pydecref(o::PyBuffer) # note that PyBuffer_Release sets o.obj to NULL, and # is a no-op if o.obj is already NULL # TODO change to `Ref{PyBuffer}` when 0.6 is dropped. - ccall(@pysym(:PyBuffer_Release), Cvoid, (Any,), o) + @pyccall(:PyBuffer_Release, Cvoid, (Any,), o) o end @@ -88,7 +88,7 @@ end # TODO change to `Ref{PyBuffer}` when 0.6 is dropped. iscontiguous(b::PyBuffer) = - 1 == ccall((@pysym :PyBuffer_IsContiguous), Cint, + 1 == @pyccall(:PyBuffer_IsContiguous, Cint, (Any, Cchar), b, 'A') ############################################################################# @@ -108,7 +108,7 @@ const PyBUF_INDIRECT = convert(Cint, 0x0100) | PyBUF_STRIDES function PyBuffer(o::Union{PyObject,PyPtr}, flags=PyBUF_SIMPLE) b = PyBuffer() # TODO change to `Ref{PyBuffer}` when 0.6 is dropped. - @pycheckz ccall((@pysym :PyObject_GetBuffer), Cint, + @pycheckz @pyccall(:PyObject_GetBuffer, Cint, (PyPtr, Any, Cint), o, b, flags) return b end diff --git a/src/pydates.jl b/src/pydates.jl index e8c62c9c..6c2d6ccb 100644 --- a/src/pydates.jl +++ b/src/pydates.jl @@ -65,7 +65,7 @@ const DateTime_FromDateAndTime = Ref{Ptr{Cvoid}}(0) const Delta_FromDelta = Ref{Ptr{Cvoid}}(0) function init_datetime() # emulate PyDateTime_IMPORT: - PyDateTimeAPI = unsafe_load(@pycheckn ccall((@pysym :PyCapsule_Import), + PyDateTimeAPI = unsafe_load(@pycheckn @pyccall(:PyCapsule_Import, Ptr{PyDateTime_CAPI}, (Ptr{UInt8}, Cint), "datetime.datetime_CAPI", 0)) DateType[] = PyDateTimeAPI.DateType @@ -77,13 +77,13 @@ function init_datetime() end PyObject(d::Dates.Date) = - PyObject(@pycheckn ccall(Date_FromDate[], PyPtr, + PyObject(@pycheckn @ccall(Date_FromDate[], PyPtr, (Cint, Cint, Cint, PyPtr), Dates.year(d), Dates.month(d), Dates.day(d), DateType[])) PyObject(d::Dates.DateTime) = - PyObject(@pycheckn ccall(DateTime_FromDateAndTime[], PyPtr, + PyObject(@pycheckn @ccall(DateTime_FromDateAndTime[], PyPtr, (Cint, Cint, Cint, Cint, Cint, Cint, Cint, PyPtr, PyPtr), Dates.year(d), Dates.month(d), Dates.day(d), @@ -92,7 +92,7 @@ PyObject(d::Dates.DateTime) = pynothing[], DateTimeType[])) PyDelta_FromDSU(days, seconds, useconds) = - PyObject(@pycheckn ccall(Delta_FromDelta[], PyPtr, + PyObject(@pycheckn @ccall(Delta_FromDelta[], PyPtr, (Cint, Cint, Cint, Cint, PyPtr), days, seconds, useconds, 1, DeltaType[])) diff --git a/src/pyeval.jl b/src/pyeval.jl index 83eac728..b1f23013 100644 --- a/src/pyeval.jl +++ b/src/pyeval.jl @@ -5,7 +5,7 @@ const Py_eval_input = 258 const _maindict = PyDict{String,PyObject,false}(PyNULL()) # cache of __main__ module dictionary function maindict() if ispynull(_maindict.o) - _maindict.o = pyincref(@pycheckn ccall((@pysym :PyModule_GetDict), PyPtr, (PyPtr,), pyimport("__main__"))) + _maindict.o = pyincref(@pycheckn @pyccall(:PyModule_GetDict, PyPtr, (PyPtr,), pyimport("__main__"))) end return _maindict end @@ -15,17 +15,12 @@ end # and a current "file name" to use for stack traces function pyeval_(s::AbstractString, globals=maindict(), locals=maindict(), input_type=Py_eval_input, fname="PyCall") sb = String(s) # use temp var to prevent gc before we are done with o - sigatomic_begin() - try - o = PyObject(@pycheckn ccall((@pysym :Py_CompileString), PyPtr, - (Cstring, Cstring, Cint), - sb, fname, input_type)) - return PyObject(@pycheckn ccall((@pysym :PyEval_EvalCode), - PyPtr, (PyPtr, PyPtr, PyPtr), - o, globals, locals)) - finally - sigatomic_end() - end + o = PyObject(@pycheckn @pyccall(:Py_CompileString, PyPtr, + (Cstring, Cstring, Cint), + sb, fname, input_type)) + return PyObject(@pycheckn @pyccall(:PyEval_EvalCode, + PyPtr, (PyPtr, PyPtr, PyPtr), + o, globals, locals)) end """ diff --git a/src/pyfncall.jl b/src/pyfncall.jl index 95cdd5ad..9e742e43 100644 --- a/src/pyfncall.jl +++ b/src/pyfncall.jl @@ -18,12 +18,12 @@ friendly format but you don't have the python tuple to hold the arguments """ function _pycall!(ret::PyObject, o::Union{PyObject,PyPtr}, args, nargs::Int=length(args), kw::Union{Ptr{Cvoid}, PyObject}=C_NULL) - pyargsptr = @pycheckn ccall((@pysym :PyTuple_New), PyPtr, (Int,), nargs) + pyargsptr = @pycheckn @pyccall(:PyTuple_New, PyPtr, (Int,), nargs) try for i = 1:nargs pyarg = PyObject(args[i]) pyincref(pyarg) # PyTuple_SetItem steals the reference - @pycheckz ccall((@pysym :PyTuple_SetItem), Cint, + @pycheckz @pyccall(:PyTuple_SetItem, Cint, (PyPtr,Int,PyPtr), pyargsptr, i-1, pyarg) end return __pycall!(ret, pyargsptr, o, kw) #::PyObject @@ -39,15 +39,10 @@ Sets `ret.o` to the result of the call, and returns `ret::PyObject`. """ function __pycall!(ret::PyObject, pyargsptr::PyPtr, o::Union{PyObject,PyPtr}, kw::Union{Ptr{Cvoid}, PyObject}) - sigatomic_begin() - try - retptr = @pycheckn ccall((@pysym :PyObject_Call), PyPtr, (PyPtr,PyPtr,PyPtr), o, - pyargsptr, kw) - pydecref_(ret.o) - ret.o = retptr - finally - sigatomic_end() - end + retptr = @pycheckn @pyccall(:PyObject_Call, PyPtr, (PyPtr,PyPtr,PyPtr), o, + pyargsptr, kw) + pydecref_(ret.o) + ret.o = retptr return ret #::PyObject end diff --git a/src/pyinit.jl b/src/pyinit.jl index 7515b12c..234e4ec2 100644 --- a/src/pyinit.jl +++ b/src/pyinit.jl @@ -135,11 +135,11 @@ function __init__() # some modules (e.g. IPython) expect sys.argv to be set @static if VERSION >= v"0.7.0-DEV.1963" ref0 = Ref{UInt32}(0) - GC.@preserve ref0 ccall(@pysym(:PySys_SetArgvEx), Cvoid, + GC.@preserve ref0 @pyccall(:PySys_SetArgvEx, Cvoid, (Cint, Ref{Ptr{Cvoid}}, Cint), 1, pointer_from_objref(ref0), 0) else - ccall(@pysym(:PySys_SetArgvEx), Cvoid, (Cint, Ptr{Cwstring}, Cint), + @pyccall(:PySys_SetArgvEx, Cvoid, (Cint, Ptr{Cwstring}, Cint), 1, [""], 0) end diff --git a/src/pyiterator.jl b/src/pyiterator.jl index ccce277e..0b693f60 100644 --- a/src/pyiterator.jl +++ b/src/pyiterator.jl @@ -4,40 +4,25 @@ # Iterating over Python objects in Julia function _start(po::PyObject) - sigatomic_begin() - try - o = PyObject(@pycheckn ccall((@pysym :PyObject_GetIter), PyPtr, (PyPtr,), po)) - nxt = PyObject(@pycheck ccall((@pysym :PyIter_Next), PyPtr, (PyPtr,), o)) + o = PyObject(@pycheckn @pyccall(:PyObject_GetIter, PyPtr, (PyPtr,), po)) + nxt = PyObject(@pycheck @pyccall(:PyIter_Next, PyPtr, (PyPtr,), o)) - return (nxt,o) - finally - sigatomic_end() - end + return (nxt,o) end @static if VERSION < v"0.7.0-DEV.5126" # julia#25261 Base.start(po::PyObject) = _start(po) function Base.next(po::PyObject, s) - sigatomic_begin() - try - nxt = PyObject(@pycheck ccall((@pysym :PyIter_Next), PyPtr, (PyPtr,), s[2])) - return (convert(PyAny, s[1]), (nxt, s[2])) - finally - sigatomic_end() - end + nxt = PyObject(@pycheck @pyccall(:PyIter_Next, PyPtr, (PyPtr,), s[2])) + return (convert(PyAny, s[1]), (nxt, s[2])) end Base.done(po::PyObject, s) = ispynull(s[1]) else function Base.iterate(po::PyObject, s=_start(po)) ispynull(s[1]) && return nothing - sigatomic_begin() - try - nxt = PyObject(@pycheck ccall((@pysym :PyIter_Next), PyPtr, (PyPtr,), s[2])) - return (convert(PyAny, s[1]), (nxt, s[2])) - finally - sigatomic_end() - end + nxt = PyObject(@pycheck @pyccall(:PyIter_Next, PyPtr, (PyPtr,), s[2])) + return (convert(PyAny, s[1]), (nxt, s[2])) end end @@ -139,12 +124,12 @@ end @static if isdefined(Base.Broadcast, :broadcastable) function Base.Broadcast.broadcastable(o::PyObject) - iter = ccall((@pysym :PyObject_GetIter), PyPtr, (PyPtr,), o) + iter = @pyccall(:PyObject_GetIter, PyPtr, (PyPtr,), o) if iter == C_NULL pyerr_clear() return Ref(o) else - ccall(@pysym(:Py_DecRef), Cvoid, (PyPtr,), iter) + @pyccall(:Py_DecRef, Cvoid, (PyPtr,), iter) return collect(o) end end diff --git a/src/pyoperators.jl b/src/pyoperators.jl index 87f48f6e..dadc1dd3 100644 --- a/src/pyoperators.jl +++ b/src/pyoperators.jl @@ -10,13 +10,13 @@ for (op,py) in ((:+,:PyNumber_Add), (:-,:PyNumber_Subtract), (:*,:PyNumber_Multi qpy = QuoteNode(py) @eval begin $op(a::PyObject, b::PyObject) = - PyObject(@pycheckn ccall((@pysym $qpy), PyPtr, (PyPtr, PyPtr), a, b)) + PyObject(@pycheckn @pyccall($qpy, PyPtr, (PyPtr, PyPtr), a, b)) $op(a::PyObject, b) = $op(a, PyObject(b)) $op(a, b::PyObject) = $op(PyObject(a), b) end end -^(a::PyObject, b::PyObject) = PyObject(@pycheckn ccall((@pysym :PyNumber_Power), PyPtr, (PyPtr, PyPtr, PyPtr), a, b, pynothing[])) +^(a::PyObject, b::PyObject) = PyObject(@pycheckn @pyccall(:PyNumber_Power, PyPtr, (PyPtr, PyPtr, PyPtr), a, b, pynothing[])) ^(a::PyObject, b) = a^PyObject(b) ^(a, b::PyObject) = PyObject(a)^b ^(a::PyObject, b::Integer) = a^PyObject(b) @@ -30,7 +30,7 @@ for (op,py) in ((:+,:PyNumber_InPlaceAdd), (:-,:PyNumber_InPlaceSubtract), (:*,: qpy = QuoteNode(py) @eval function Base.broadcast!(::typeof($op), a::PyObject, a′::PyObject, b) a.o == a′.o || throw(MethodError(broadcast!, ($op, a, a', b))) - PyObject(@pycheckn ccall((@pysym $qpy), PyPtr, (PyPtr, PyPtr), a,PyObject(b))) + PyObject(@pycheckn @pyccall($qpy, PyPtr, (PyPtr, PyPtr), a,PyObject(b))) end end @@ -39,7 +39,7 @@ import Base: abs,~ for (op,py) in ((:+,:PyNumber_Positive), (:-,:PyNumber_Negative), (:abs,:PyNumber_Absolute), (:~, :PyNumber_Invert)) qpy = QuoteNode(py) - @eval $op(a::PyObject) = PyObject(@pycheckn ccall((@pysym $qpy), PyPtr, (PyPtr,), a)) + @eval $op(a::PyObject) = PyObject(@pycheckn @pyccall($qpy, PyPtr, (PyPtr,), a)) end ######################################################################### @@ -64,10 +64,10 @@ for (op,py) in ((:<, Py_LT), (:<=, Py_LE), (:(==), Py_EQ), (:!=, Py_NE), unsafe_pyjlwrap_to_objref(o2.o)) else if $(op == :isless || op == :isequal) - return Bool(@pycheckz ccall((@pysym :PyObject_RichCompareBool), Cint, + return Bool(@pycheckz @pyccall(:PyObject_RichCompareBool, Cint, (PyPtr, PyPtr, Cint), o1, o2, $py)) else # other operations may return a PyObject - return PyAny(PyObject(@pycheckn ccall((@pysym :PyObject_RichCompare), PyPtr, + return PyAny(PyObject(@pycheckn @pyccall(:PyObject_RichCompare, PyPtr, (PyPtr, PyPtr, Cint), o1, o2, $py))) end end diff --git a/src/pytype.jl b/src/pytype.jl index a05d5f8c..9ce18626 100644 --- a/src/pytype.jl +++ b/src/pytype.jl @@ -312,8 +312,8 @@ function PyTypeObject!(init::Function, t::PyTypeObject, name::AbstractString, ba t.tp_new = @pyglobal :PyType_GenericNew end # TODO change to `Ref{PyTypeObject}` when 0.6 is dropped. - @pycheckz ccall((@pysym :PyType_Ready), Cint, (Any,), t) - ccall((@pysym :Py_IncRef), Cvoid, (Any,), t) + @pycheckz @pyccall(:PyType_Ready, Cint, (Any,), t) + @pyccall(:Py_IncRef, Cvoid, (Any,), t) return t end @@ -373,13 +373,13 @@ function pyjlwrap_getattr(self_::PyPtr, attr__::PyPtr) return pystealref!(PyObject(nothing)) elseif startswith(attr, "__") # TODO: handle __code__/func_code (issue #268) - return ccall(@pysym(:PyObject_GenericGetAttr), PyPtr, (PyPtr,PyPtr), self_, attr__) + return @pyccall(:PyObject_GenericGetAttr, PyPtr, (PyPtr,PyPtr), self_, attr__) else fidx = Base.fieldindex(typeof(f), Symbol(attr), false) if fidx != 0 return pyreturn(getfield(f, fidx)) else - return ccall(@pysym(:PyObject_GenericGetAttr), PyPtr, (PyPtr,PyPtr), self_, attr__) + return @pyccall(:PyObject_GenericGetAttr, PyPtr, (PyPtr,PyPtr), self_, attr__) end end catch e @@ -404,7 +404,7 @@ function pyjlwrap_type!(init::Function, to::PyTypeObject, name::AbstractString) PyTypeObject!(to, name, sz) do t::PyTypeObject # TODO change to `Ref{PyTypeObject}` when 0.6 is dropped. t.tp_base = ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), jlWrapType) - ccall((@pysym :Py_IncRef), Cvoid, (Any,), jlWrapType) + @pyccall(:Py_IncRef, Cvoid, (Any,), jlWrapType) init(t) end end @@ -418,7 +418,7 @@ pyjlwrap_type(init::Function, name::AbstractString) = # to wrap isbits types in Python objects anyway.) function pyjlwrap_new(pyT::PyTypeObject, value::Any) # TODO change to `Ref{PyTypeObject}` when 0.6 is dropped. - o = PyObject(@pycheckn ccall((@pysym :_PyObject_New), + o = PyObject(@pycheckn @pyccall(:_PyObject_New, PyPtr, (Any,), pyT)) p = convert(Ptr{Ptr{Cvoid}}, o.o) if isimmutable(value) @@ -443,7 +443,7 @@ function pyjlwrap_new(x::Any) end # TODO change to `Ref{PyTypeObject}` when 0.6 is dropped. -is_pyjlwrap(o::PyObject) = jlWrapType.tp_new != C_NULL && ccall((@pysym :PyObject_IsInstance), Cint, (PyPtr, Any), o, jlWrapType) == 1 +is_pyjlwrap(o::PyObject) = jlWrapType.tp_new != C_NULL && @pyccall(:PyObject_IsInstance, Cint, (PyPtr, Any), o, jlWrapType) == 1 ################################################################ # Fallback conversion: if we don't have a better conversion function, diff --git a/src/serialize.jl b/src/serialize.jl index 42b4563d..211a4954 100644 --- a/src/serialize.jl +++ b/src/serialize.jl @@ -30,7 +30,7 @@ does not contain valid Unicode), or from the default conversion of a """ function pybytes(b::Union{String,DenseVector{UInt8}}) b isa String || stride(b,1) == 1 || throw(ArgumentError("pybytes requires stride-1 byte arrays")) - PyObject(@pycheckn ccall(@pysym(PyString_FromStringAndSize), + PyObject(@pycheckn @pyccall(PyString_FromStringAndSize, PyPtr, (Ptr{UInt8}, Int), b, sizeof(b))) end