From 5b48211bccfc479945e9fa4e17d67e77059fb9dc Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 7 Mar 2018 13:01:54 -0500 Subject: [PATCH 1/2] silence 0.7 deprecation warnings --- README.md | 2 +- REQUIRE | 2 +- deps/build.jl | 28 +++++++-------- deps/depsutils.jl | 6 ++-- src/PyCall.jl | 52 ++++++++++++--------------- src/callback.jl | 36 +++++++------------ src/conversions.jl | 48 ++++++++++++------------- src/exception.jl | 12 +++---- src/gc.jl | 2 +- src/io.jl | 2 +- src/numpy.jl | 32 ++++++++--------- src/pybuffer.jl | 12 +++---- src/pydates.jl | 19 +++++----- src/pyinit.jl | 14 ++++---- src/pyiterator.jl | 2 +- src/pytype.jl | 90 +++++++++++++++++++++++----------------------- src/serialize.jl | 7 ++-- src/startup.jl | 26 +++++++------- test/runtests.jl | 54 +++++++++++++--------------- 19 files changed, 215 insertions(+), 231 deletions(-) diff --git a/README.md b/README.md index 29f5fa53..140fc798 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,7 @@ Here are solutions to some common problems: * As mentioned above, use `foo[:bar]` and `foo[:bar](...)` rather than `foo.bar` and `foo.bar(...)`, respectively, to access attributes and methods of Python objects. -* By default, PyCall [doesn't include the current directory in the Python search path](https://github.com/stevengj/PyCall.jl/issues/48). If you want to do that (in order to load a Python module from the current directory), just run `unshift!(PyVector(pyimport("sys")["path"]), "")`. +* By default, PyCall [doesn't include the current directory in the Python search path](https://github.com/stevengj/PyCall.jl/issues/48). If you want to do that (in order to load a Python module from the current directory), just run `pushfirst!(PyVector(pyimport("sys")["path"]), "")`. ## Python object interfaces diff --git a/REQUIRE b/REQUIRE index e45c1126..57bfba40 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,4 +1,4 @@ julia 0.6 -Compat 0.32.0 +Compat 0.55.0 Conda 0.2 MacroTools 0.3 diff --git a/deps/build.jl b/deps/build.jl index 30a8e69d..5d463e50 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -6,7 +6,7 @@ # will probably need to re-run Pkg.build("PyCall"). using Compat -import Conda +import Conda, Compat.Libdl struct UseCondaPython <: Exception end @@ -53,9 +53,9 @@ function find_libpython(python::AbstractString) v = pyconfigvar(python,"VERSION","") libs = [ dlprefix*"python"*v, dlprefix*"python" ] lib = pyconfigvar(python, "LIBRARY") - lib != "None" && unshift!(libs, splitext(lib)[1]) + lib != "None" && pushfirst!(libs, splitext(lib)[1]) lib = pyconfigvar(python, "LDLIBRARY") - lib != "None" && unshift!(unshift!(libs, basename(lib)), lib) + lib != "None" && pushfirst!(pushfirst!(libs, basename(lib)), lib) libs = unique(libs) # it is ridiculous that it is this hard to find the path of libpython @@ -106,13 +106,13 @@ function find_libpython(python::AbstractString) end if "yes" == get(ENV, "PYCALL_DEBUG_BUILD", "no") # print out extra info to help with remote debugging - println(STDERR, "------------------------------------- exceptions -----------------------------------------") + println(stderr, "------------------------------------- exceptions -----------------------------------------") for s in error_strings print(s, "\n\n") end - println(STDERR, "---------------------------------- get_config_vars ---------------------------------------") - print(STDERR, read(`python -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_vars())"`, String)) - println(STDERR, "--------------------------------- directory contents -------------------------------------") + println(stderr, "---------------------------------- get_config_vars ---------------------------------------") + print(stderr, read(`python -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_vars())"`, String)) + println(stderr, "--------------------------------- directory contents -------------------------------------") for libpath in libpaths if isdir(libpath) print(libpath, ":\n") @@ -123,7 +123,7 @@ function find_libpython(python::AbstractString) end end end - println(STDERR, "------------------------------------------------------------------------------------------") + println(stderr, "------------------------------------------------------------------------------------------") end error(""" @@ -150,10 +150,10 @@ wstringconst(s) = string("Base.cconvert(Cwstring, \"", escape_string(s), "\")") # problems in the unlikely event of read-only directories. function writeifchanged(filename, str) if !isfile(filename) || read(filename, String) != str - info(abspath(filename), " has been updated") + @info string(abspath(filename), " has been updated") write(filename, str) else - info(abspath(filename), " has not changed") + @info string(abspath(filename), " has not changed") end end @@ -161,7 +161,7 @@ try # make sure deps.jl file is removed on error python = try let py = get(ENV, "PYTHON", isfile("PYTHON") ? readchomp("PYTHON") : (Compat.Sys.isunix() && !Compat.Sys.isapple()) || Sys.ARCH ∉ (:i686, :x86_64) ? "python" : ""), - vers = isempty(py) ? v"0.0" : convert(VersionNumber, pyconfigvar(py,"VERSION","0.0")) + vers = isempty(py) ? v"0.0" : VersionNumber(pyconfigvar(py,"VERSION","0.0")) if vers < v"2.7" if isempty(py) throw(UseCondaPython()) @@ -182,10 +182,10 @@ try # make sure deps.jl file is removed on error catch e1 if Sys.ARCH in (:i686, :x86_64) if isa(e1, UseCondaPython) - info("Using the Python distribution in the Conda package by default.\n", + @info string("Using the Python distribution in the Conda package by default.\n", "To use a different Python version, set ENV[\"PYTHON\"]=\"pythoncommand\" and re-run Pkg.build(\"PyCall\").") else - info( "No system-wide Python was found; got the following error:\n", + @info string( "No system-wide Python was found; got the following error:\n", "$e1\nusing the Python distribution in the Conda package") end abspath(Conda.PYTHONDIR, "python" * (Compat.Sys.iswindows() ? ".exe" : "")) @@ -222,7 +222,7 @@ try # make sure deps.jl file is removed on error # cache the Python version as a Julia VersionNumber pyversion = VersionNumber(pyvar(python, "platform", "python_version()")) - info("PyCall is using $python (Python $pyversion) at $programname, libpython = $libpy_name") + @info "PyCall is using $python (Python $pyversion) at $programname, libpython = $libpy_name" if pyversion < v"2.7" error("Python 2.7 or later is required for PyCall") diff --git a/deps/depsutils.jl b/deps/depsutils.jl index 322e88a8..acf0defd 100644 --- a/deps/depsutils.jl +++ b/deps/depsutils.jl @@ -1,3 +1,5 @@ +import Compat.Libdl + hassym(lib, sym) = Libdl.dlsym_e(lib, sym) != C_NULL # call dlsym_e on a sequence of symbols and return the symbol that gives @@ -20,9 +22,9 @@ end function Py_SetPythonHome(libpy, PYTHONHOME, wPYTHONHOME, pyversion) if !isempty(PYTHONHOME) if pyversion.major < 3 - ccall(Libdl.dlsym(libpy, :Py_SetPythonHome), Void, (Cstring,), PYTHONHOME) + ccall(Libdl.dlsym(libpy, :Py_SetPythonHome), Cvoid, (Cstring,), PYTHONHOME) else - ccall(Libdl.dlsym(libpy, :Py_SetPythonHome), Void, (Ptr{Cwchar_t},), wPYTHONHOME) + ccall(Libdl.dlsym(libpy, :Py_SetPythonHome), Cvoid, (Ptr{Cwchar_t},), wPYTHONHOME) end end end diff --git a/src/PyCall.jl b/src/PyCall.jl index 19bd784b..1dd4228b 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -2,6 +2,8 @@ __precompile__() module PyCall +using Compat + export pycall, pyimport, pybuiltin, PyObject, PyReverseDims, PyPtr, pyincref, pydecref, pyversion, PyArray, PyArray_Info, pyerr_check, pyerr_clear, pytype_query, PyAny, @pyimport, PyDict, @@ -14,24 +16,19 @@ import Base: size, ndims, similar, copy, getindex, setindex!, stride, convert, pointer, summary, convert, show, haskey, keys, values, eltype, get, delete!, empty!, length, isempty, start, done, next, filter!, hash, splice!, pop!, ==, isequal, push!, - unshift!, shift!, append!, insert!, prepend!, mimewritable + append!, insert!, prepend!, mimewritable, unsafe_convert +import Compat: pushfirst!, popfirst! -# Python C API is not interrupt-save. In principle, we should +# 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 -## Compatibility import for v0.5 -using Compat import Conda -import Base.unsafe_convert import MacroTools # because of issue #270 - -if isdefined(Base, :Iterators) - import Base.Iterators: filter -end +import Base.Iterators: filter ######################################################################### @@ -47,7 +44,7 @@ include("startup.jl") # while we're at it. struct PyObject_struct ob_refcnt::Int - ob_type::Ptr{Void} + ob_type::Ptr{Cvoid} end const PyPtr = Ptr{PyObject_struct} # type for PythonObject* in ccall @@ -71,7 +68,7 @@ mutable struct PyObject o::PyPtr # the actual PyObject* function PyObject(o::PyPtr) po = new(o) - finalizer(po, pydecref) + finalizer(pydecref, po) return po end end @@ -93,13 +90,13 @@ someobject)`. This procedure will properly handle Python's reference counting PyNULL() = PyObject(PyPtr_NULL) function pydecref(o::PyObject) - ccall(@pysym(:Py_DecRef), Void, (PyPtr,), o.o) + ccall(@pysym(:Py_DecRef), Cvoid, (PyPtr,), o.o) o.o = PyPtr_NULL o end function pyincref_(o::PyPtr) - ccall((@pysym :Py_IncRef), Void, (PyPtr,), o) + ccall((@pysym :Py_IncRef), Cvoid, (PyPtr,), o) return o end @@ -134,10 +131,10 @@ end pyisinstance(o::PyObject, t::PyObject) = t.o != C_NULL && ccall((@pysym :PyObject_IsInstance), Cint, (PyPtr,PyPtr), o, t.o) == 1 -pyisinstance(o::PyObject, t::Union{Ptr{Void},PyPtr}) = +pyisinstance(o::PyObject, t::Union{Ptr{Cvoid},PyPtr}) = t != C_NULL && ccall((@pysym :PyObject_IsInstance), Cint, (PyPtr,PyPtr), o, t) == 1 -pyquery(q::Ptr{Void}, o::PyObject) = +pyquery(q::Ptr{Cvoid}, o::PyObject) = ccall(q, Cint, (PyPtr,), o) == 1 # conversion to pass PyObject as ccall arguments: @@ -347,19 +344,19 @@ end # during import. struct ACTIVATION_CONTEXT_BASIC_INFORMATION - handle::Ptr{Void} + handle::Ptr{Cvoid} dwFlags::UInt32 end const ActivationContextBasicInformation = 1 const QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS = 0x10 - const PyActCtx = Ref{Ptr{Void}}(C_NULL) + const PyActCtx = Ref{Ptr{Cvoid}}(C_NULL) function ComputePyActCtx() if PyActCtx[] == C_NULL some_address_in_libpython = @pyglobal(:PyImport_ImportModule) ActCtxBasicInfo = Ref{ACTIVATION_CONTEXT_BASIC_INFORMATION}() succeeded = ccall(:QueryActCtxW,stdcall,Bool, - (UInt32,Ptr{Void},Ptr{Void},Culong,Ptr{Void},Csize_t,Ptr{Csize_t}), + (UInt32,Ptr{Cvoid},Ptr{Cvoid},Culong,Ptr{Cvoid},Csize_t,Ptr{Csize_t}), QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS, some_address_in_libpython, C_NULL, ActivationContextBasicInformation, ActCtxBasicInfo, sizeof(ActCtxBasicInfo), C_NULL) @@ -370,9 +367,9 @@ end end function ActivatePyActCtx() - cookie = Ref{Ptr{Void}}() + cookie = Ref{Ptr{Cvoid}}() succeeded = ccall(:ActivateActCtx,stdcall, Bool, - (Ptr{Void}, Ptr{Ptr{Void}}), + (Ptr{Cvoid}, Ptr{Ptr{Cvoid}}), ComputePyActCtx(), cookie) @assert succeeded cookie[] @@ -380,7 +377,7 @@ end function DeactivatePyActCtx(cookie) succeeded = ccall(:DeactivateActCtx, stdcall, Bool, - (UInt32, Ptr{Void}), 0, cookie) + (UInt32, Ptr{Cvoid}), 0, cookie) @assert succeeded end else @@ -614,7 +611,7 @@ function pyimport_conda(modulename::AbstractString, condapkg::AbstractString, pyimport(modulename) catch e if conda - info("Installing $modulename via the Conda $condapkg package...") + @info "Installing $modulename via the Conda $condapkg package..." isempty(channel) || Conda.add_channel(channel) Conda.add(condapkg) pyimport(modulename) @@ -622,7 +619,7 @@ function pyimport_conda(modulename::AbstractString, condapkg::AbstractString, aconda = anaconda_conda() if !isempty(aconda) try - info("Installing $modulename via Anaconda's $aconda...") + @info "Installing $modulename via Anaconda's $aconda..." isempty(channel) || run(`$aconda config --add channels $channel --force`) run(`$aconda install -y $condapkg`) catch e2 @@ -797,7 +794,7 @@ function splice!(a::PyObject, i::Integer) end pop!(a::PyObject) = splice!(a, length(a)) -shift!(a::PyObject) = splice!(a, 1) +popfirst!(a::PyObject) = splice!(a, 1) function empty!(a::PyObject) for i in length(a):-1:1 @@ -819,7 +816,7 @@ function insert!(a::PyObject, i::Integer, item) a end -unshift!(a::PyObject, item) = insert!(a, 1, item) +pushfirst!(a::PyObject, item) = insert!(a, 1, item) function prepend!(a::PyObject, items) if isa(items,PyObject) && items.o == a.o @@ -880,10 +877,7 @@ end ######################################################################### # Expose Python docstrings to the Julia doc system -if isdefined(Docs, :getdoc) # Introduced in Julia .6 - Docs.getdoc(o::PyObject) = Text(String(o["__doc__"])) -end - +Docs.getdoc(o::PyObject) = Text(String(o["__doc__"])) ######################################################################### diff --git a/src/callback.jl b/src/callback.jl index bda1ea58..a6b506a1 100644 --- a/src/callback.jl +++ b/src/callback.jl @@ -15,7 +15,7 @@ function pymethod(f::Function, name::AbstractString, flags::Integer) def = gensym("PyMethodDef") @eval const $def = PyMethodDef[PyMethodDef($name, $f, $flags)] PyObject(@pycheckn ccall((@pysym :PyCFunction_NewEx), PyPtr, - (Ptr{PyMethodDef}, Ptr{Void}, Ptr{Void}), + (Ptr{PyMethodDef}, Ptr{Cvoid}, Ptr{Cvoid}), eval(def), C_NULL, C_NULL)) end @@ -37,28 +37,18 @@ function _pyjlwrap_call(f, args_::PyPtr, kw_::PyPtr) try jlargs = julia_args(f, args) - # on 0.6 we need to use invokelatest to get execution in newest world - @static if isdefined(Base, :invokelatest) - if kw_ == C_NULL - ret = PyObject(Base.invokelatest(f, jlargs...)) - else - kw = PyDict{Symbol,PyObject}(pyincref(kw_)) - kwargs = [ (k,julia_kwarg(f,k,v)) for (k,v) in kw ] - - # 0.6 `invokelatest` doesn't support kwargs, instead - # use a closure over kwargs. see: - # https://github.com/JuliaLang/julia/pull/22646 - f_kw_closure() = f(jlargs...; kwargs...) - ret = PyObject(Core._apply_latest(f_kw_closure)) - end - else # 0.5 support - if kw_ == C_NULL - ret = PyObject(f(jlargs...)) - else - kw = PyDict{Symbol,PyAny}(pyincref(kw_)) - kwargs = [ (k,julia_kwarg(f,k,v)) for (k,v) in kw ] - ret = PyObject(f(jlargs...; kwargs...)) - end + # we need to use invokelatest to get execution in newest world + if kw_ == C_NULL + ret = PyObject(Base.invokelatest(f, jlargs...)) + else + kw = PyDict{Symbol,PyObject}(pyincref(kw_)) + kwargs = [ (k,julia_kwarg(f,k,v)) for (k,v) in kw ] + + # 0.6 `invokelatest` doesn't support kwargs, instead + # use a closure over kwargs. see: + # https://github.com/JuliaLang/julia/pull/22646 + f_kw_closure() = f(jlargs...; kwargs...) + ret = PyObject(Core._apply_latest(f_kw_closure)) end return pystealref!(ret) diff --git a/src/conversions.jl b/src/conversions.jl index ba4afb2c..28325ca2 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -20,7 +20,7 @@ PyObject(c::Complex) = PyObject(@pycheckn ccall((@pysym :PyComplex_FromDoubles), PyPtr, (Cdouble,Cdouble), real(c), imag(c))) -PyObject(n::Void) = pyerr_check("PyObject(nothing)", pyincref(pynothing[])) +PyObject(n::Nothing) = pyerr_check("PyObject(nothing)", pyincref(pynothing[])) # conversions to Julia types from PyObject @@ -53,7 +53,7 @@ function convert(::Type{T}, po_::PyObject) where T<:Complex end) end -convert(::Type{Void}, po::PyObject) = nothing +convert(::Type{Nothing}, po::PyObject) = nothing ######################################################################### # String conversions (both bytes arrays and unicode strings) @@ -111,23 +111,23 @@ end PyObject(p::Ptr) = pycall(c_void_p_Type, PyObject, UInt(p)) -function convert(::Type{Ptr{Void}}, po::PyObject) +function convert(::Type{Ptr{Cvoid}}, po::PyObject) if pyisinstance(po, c_void_p_Type) v = po["value"] # ctypes stores the NULL pointer specially, grrr - pynothing_query(v) == Void ? C_NULL : - convert(Ptr{Void}, convert(UInt, po["value"])) + pynothing_query(v) == Nothing ? C_NULL : + convert(Ptr{Cvoid}, convert(UInt, po["value"])) elseif pyisinstance(po, @pyglobalobj(:PyCapsule_Type)) @pycheck ccall((@pysym :PyCapsule_GetPointer), - Ptr{Void}, (PyPtr,Ptr{UInt8}), + Ptr{Cvoid}, (PyPtr,Ptr{UInt8}), po, ccall((@pysym :PyCapsule_GetName), Ptr{UInt8}, (PyPtr,), po)) else - convert(Ptr{Void}, convert(UInt, po)) + convert(Ptr{Cvoid}, convert(UInt, po)) end end -pyptr_query(po::PyObject) = pyisinstance(po, c_void_p_Type) || pyisinstance(po, @pyglobalobj(:PyCapsule_Type)) ? Ptr{Void} : Union{} +pyptr_query(po::PyObject) = pyisinstance(po, c_void_p_Type) || pyisinstance(po, @pyglobalobj(:PyCapsule_Type)) ? Ptr{Cvoid} : Union{} ######################################################################### # for automatic conversions, I pass Vector{PyAny}, NTuple{N, PyAny}, etc., @@ -136,7 +136,7 @@ pyptr_query(po::PyObject) = pyisinstance(po, c_void_p_Type) || pyisinstance(po, # I want to use a union, but this seems to confuse Julia's method # dispatch for the convert function in some circumstances -# const PyAny = Union{PyObject, Int, Bool, Float64, Complex128, AbstractString, Function, Dict, Tuple, Array} +# const PyAny = Union{PyObject, Int, Bool, Float64, ComplexF64, AbstractString, Function, Dict, Tuple, Array} abstract type PyAny end function pyany_toany(T::Type) @@ -263,13 +263,13 @@ function splice!(a::PyVector{T}, indices::AbstractVector{I}) where {T,I<:Integer v end pop!(a::PyVector) = pop!(a.o) -shift!(a::PyVector) = shift!(a.o) +popfirst!(a::PyVector) = popfirst!(a.o) empty!(a::PyVector) = empty!(a.o) # only works for List subtypes: push!(a::PyVector, item) = push!(a.o, item) insert!(a::PyVector, i::Integer, item) = insert!(a.o, i, item) -unshift!(a::PyVector, item) = unshift!(a.o, item) +pushfirst!(a::PyVector, item) = pushfirst!(a.o, item) prepend!(a::PyVector, items) = prepend!(a.o, items) append!(a::PyVector{T}, items) where {T} = PyVector{T}(append!(a.o, items)) @@ -374,7 +374,7 @@ end function py2array(T, o::PyObject) dims = pyarray_dims(o) - A = Array{pyany_toany(T)}(dims) + A = Array{pyany_toany(T)}(uninitialized, dims) py2array(T, A, o, 1, 1) end @@ -385,7 +385,7 @@ function convert(::Type{Vector{T}}, o::PyObject) where T pyerr_clear() throw(ArgumentError("expected Python sequence")) end - py2array(T, Array{pyany_toany(T)}(len), o, 1, 1) + py2array(T, Array{pyany_toany(T)}(uninitialized, len), o, 1, 1) end convert(::Type{Array}, o::PyObject) = map(identity, py2array(PyAny, o)) @@ -415,7 +415,7 @@ This returns a PyDict, which is a no-copy wrapper around a Python dictionary. Alternatively, you can specify the return type of a `pycall` as PyDict. """ -mutable struct PyDict{K,V,isdict} <: Associative{K,V} +mutable struct PyDict{K,V,isdict} <: AbstractDict{K,V} o::PyObject # isdict = true for python dict, otherwise is a generic Mapping object @@ -433,10 +433,10 @@ PyDict{K,V}() where {K,V} = PyDict{K,V,true}(PyObject(@pycheckn ccall((@pysym :P PyDict(o::PyObject) = PyDict{PyAny,PyAny}(o) PyObject(d::PyDict) = d.o PyDict() = PyDict{PyAny,PyAny}() -PyDict(d::Associative{K,V}) where {K,V} = PyDict{K,V}(PyObject(d)) -PyDict(d::Associative{Any,Any}) = PyDict{PyAny,PyAny}(PyObject(d)) -PyDict(d::Associative{Any,V}) where {V} = PyDict{PyAny,V}(PyObject(d)) -PyDict(d::Associative{K,Any}) where {K} = PyDict{K,PyAny}(PyObject(d)) +PyDict(d::AbstractDict{K,V}) where {K,V} = PyDict{K,V}(PyObject(d)) +PyDict(d::AbstractDict{Any,Any}) = PyDict{PyAny,PyAny}(PyObject(d)) +PyDict(d::AbstractDict{Any,V}) where {V} = PyDict{PyAny,V}(PyObject(d)) +PyDict(d::AbstractDict{K,Any}) where {K} = PyDict{K,PyAny}(PyObject(d)) 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 @@ -495,7 +495,7 @@ function delete!(d::PyDict{K,V,false}, k) where {K,V} end function empty!(d::PyDict{K,V,true}) where {K,V} - @pycheck ccall((@pysym :PyDict_Clear), Void, (PyPtr,), d) + @pycheck ccall((@pysym :PyDict_Clear), Cvoid, (PyPtr,), d) return d end function empty!(d::PyDict{K,V,false}) where {K,V} @@ -547,7 +547,7 @@ end ######################################################################### # Dictionary conversions (copies) -function PyObject(d::Associative) +function PyObject(d::AbstractDict) o = PyObject(@pycheckn ccall((@pysym :PyDict_New), PyPtr, ())) for k in keys(d) @pycheckz ccall((@pysym :PyDict_SetItem), Cint, (PyPtr,PyPtr,PyPtr), @@ -655,7 +655,7 @@ const LongInt = @static (Sys.WORD_SIZE==32) ? Union{Int64,UInt64,Int128,UInt128, function PyObject(i::LongInt) PyObject(@pycheckn ccall((@pysym :PyLong_FromString), PyPtr, - (Ptr{UInt8}, Ptr{Void}, Cint), + (Ptr{UInt8}, Ptr{Cvoid}, Cint), String(string(i)), C_NULL, 10)) end @@ -687,7 +687,7 @@ pyint_query(o::PyObject) = pyisinstance(o, @pyglobalobj PyInt_Type) ? pyfloat_query(o::PyObject) = pyisinstance(o, @pyglobalobj :PyFloat_Type) || pyisinstance(o, npy_floating) ? Float64 : Union{} pycomplex_query(o::PyObject) = - pyisinstance(o, @pyglobalobj :PyComplex_Type) || pyisinstance(o, npy_complexfloating) ? Complex128 : Union{} + pyisinstance(o, @pyglobalobj :PyComplex_Type) || pyisinstance(o, npy_complexfloating) ? ComplexF64 : Union{} pystring_query(o::PyObject) = pyisinstance(o, @pyglobalobj PyString_Type) ? AbstractString : pyisinstance(o, @pyglobalobj :PyUnicode_Type) ? String : Union{} @@ -695,7 +695,7 @@ pystring_query(o::PyObject) = pyisinstance(o, @pyglobalobj PyString_Type) ? Abst # we never automatically convert to Function. pyfunction_query(o::PyObject) = Union{} -pynothing_query(o::PyObject) = o.o == pynothing[] ? Void : Union{} +pynothing_query(o::PyObject) = o.o == pynothing[] ? Nothing : Union{} # We refrain from converting all objects that support the mapping protocol (PyMapping_Check) # to avoid converting types like Pandas `DataFrame` that are only lossily @@ -741,7 +741,7 @@ macro return_not_None(ex) end end -const pytype_queries = Array{Tuple{PyObject,Type}}(0) +const pytype_queries = Tuple{PyObject,Type}[] """ pytype_mapping(pytype, jltype) diff --git a/src/exception.jl b/src/exception.jl index 8f3f54af..81184d1e 100644 --- a/src/exception.jl +++ b/src/exception.jl @@ -13,12 +13,12 @@ mutable struct PyError <: Exception # PyErr_Occurred returns non-NULL, and clears the Python error # indicator. function PyError(msg::AbstractString) - exc = Array{PyPtr}(3) + exc = Array{PyPtr}(uninitialized, 3) pexc = convert(UInt, pointer(exc)) # equivalent of passing C pointers &exc[1], &exc[2], &exc[3]: - ccall((@pysym :PyErr_Fetch), Void, (UInt,UInt,UInt), + ccall((@pysym :PyErr_Fetch), Cvoid, (UInt,UInt,UInt), pexc, pexc + sizeof(PyPtr), pexc + 2*sizeof(PyPtr)) - ccall((@pysym :PyErr_NormalizeException), Void, (UInt,UInt,UInt), + ccall((@pysym :PyErr_NormalizeException), Cvoid, (UInt,UInt,UInt), pexc, pexc + sizeof(PyPtr), pexc + 2*sizeof(PyPtr)) new(msg, exc[1], exc[2], exc[3]) end @@ -49,7 +49,7 @@ end # Conversion of Python exceptions into Julia exceptions # call to discard Python exceptions -pyerr_clear() = ccall((@pysym :PyErr_Clear), Void, ()) +pyerr_clear() = ccall((@pysym :PyErr_Clear), Cvoid, ()) function pyerr_check(msg::AbstractString, val::Any) if ccall((@pysym :PyErr_Occurred), PyPtr, ()) != C_NULL @@ -123,12 +123,12 @@ end function pyraise(e) eT = typeof(e) pyeT = haskey(pyexc::Dict, eT) ? pyexc[eT] : pyexc[Exception] - ccall((@pysym :PyErr_SetString), Void, (PyPtr, Cstring), + ccall((@pysym :PyErr_SetString), Cvoid, (PyPtr, Cstring), pyeT, string("Julia exception: ", e)) end function pyraise(e::PyError) - ccall((@pysym :PyErr_Restore), Void, (PyPtr, PyPtr, PyPtr), + ccall((@pysym :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 2dc05b53..82434aa0 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), Void, (PyPtr,), wo) + ccall((@pysym :Py_DecRef), Cvoid, (PyPtr,), wo) return pyincref_(pynothing[]) end diff --git a/src/io.jl b/src/io.jl index 5d7a07d3..c9182acb 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), Void, (PyPtr, Cstring), + ccall((@pysym :PyErr_SetString), Cvoid, (PyPtr, Cstring), (pyexc::Dict)[PyIOError], string("Julia exception: ", e)) else diff --git a/src/numpy.jl b/src/numpy.jl index 56c92289..33b415fb 100644 --- a/src/numpy.jl +++ b/src/numpy.jl @@ -17,7 +17,7 @@ # # The result of npy_api_initialize, below, is to produce the following # tables of API pointers: -const npy_api = Dict{Symbol, Ptr{Void}}() +const npy_api = Dict{Symbol, Ptr{Cvoid}}() # need a global to cache pyimport("numpy.core.multiarray"), in order # to ensure the module is not garbage-collected as long as we are using it @@ -51,11 +51,11 @@ function npyinitialize() end if pyversion.major < 3 PyArray_API = @pycheck ccall((@pysym :PyCObject_AsVoidPtr), - Ptr{Ptr{Void}}, (PyPtr,), + Ptr{Ptr{Cvoid}}, (PyPtr,), npy_multiarray["_ARRAY_API"]) else PyArray_API = @pycheck ccall((@pysym :PyCapsule_GetPointer), - Ptr{Ptr{Void}}, (PyPtr,Ptr{Void}), + Ptr{Ptr{Cvoid}}, (PyPtr,Ptr{Cvoid}), npy_multiarray["_ARRAY_API"], C_NULL) end @@ -160,11 +160,11 @@ npy_type(::Type{UInt64}) = NPY_ULONGLONG npy_type(::Type{Float16}) = NPY_HALF npy_type(::Type{Float32}) = NPY_FLOAT npy_type(::Type{Float64}) = NPY_DOUBLE -npy_type(::Type{Complex64}) = NPY_CFLOAT -npy_type(::Type{Complex128}) = NPY_CDOUBLE +npy_type(::Type{ComplexF32}) = NPY_CFLOAT +npy_type(::Type{ComplexF64}) = NPY_CDOUBLE npy_type(::Type{PyPtr}) = NPY_OBJECT -const NPY_TYPES = Union{Bool,Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64,Float16,Float32,Float64,Complex64,Complex128,PyPtr} +const NPY_TYPES = Union{Bool,Int8,UInt8,Int16,UInt16,Int32,UInt32,Int64,UInt64,Float16,Float32,Float64,ComplexF32,ComplexF64,PyPtr} # conversions from __array_interface__ type strings to supported Julia types const npy_typestrs = Dict( "b1"=>Bool, @@ -173,8 +173,8 @@ const npy_typestrs = Dict( "b1"=>Bool, "i4"=>Int32, "u4"=>UInt32, "i8"=>Int64, "u8"=>UInt64, "f2"=>Float16, "f4"=>Float32, - "f8"=>Float64, "c8"=>Complex64, - "c16"=>Complex128, "O"=>PyPtr, + "f8"=>Float64, "c8"=>ComplexF32, + "c16"=>ComplexF64, "O"=>PyPtr, "O$(div(Sys.WORD_SIZE,8))"=>PyPtr) ######################################################################### @@ -232,7 +232,7 @@ mutable struct PyArray_Info native::Bool # native byte order? sz::Vector{Int} st::Vector{Int} # strides, in multiples of bytes! - data::Ptr{Void} + data::Ptr{Cvoid} readonly::Bool function PyArray_Info(a::PyObject) @@ -257,7 +257,7 @@ mutable struct PyArray_Info || (ENDIAN_BOM == 0x01020304 && typestr[1] == '>') || typestr[1] == '|', sz, st, - convert(Ptr{Void}, datatuple[1]), + convert(Ptr{Cvoid}, datatuple[1]), datatuple[2]) end end @@ -334,16 +334,16 @@ end size(a::PyArray) = a.dims ndims(a::PyArray{T,N}) where {T,N} = N -similar(a::PyArray, T, dims::Dims) = Array{T}(dims) +similar(a::PyArray, T, dims::Dims) = Array{T}(uninitialized, dims) function copy(a::PyArray{T,N}) where {T,N} if N > 1 && a.c_contig # equivalent to f_contig with reversed dims B = unsafe_wrap(Array, a.data, ntuple((n -> a.dims[N - n + 1]), N)) return permutedims(B, (N:-1:1)) end - A = Array{T}(a.dims) + A = Array{T}(uninitialized, a.dims) if a.f_contig - ccall(:memcpy, Void, (Ptr{T}, Ptr{T}, Int), A, a, sizeof(T)*length(a)) + ccall(:memcpy, Cvoid, (Ptr{T}, Ptr{T}, Int), A, a, sizeof(T)*length(a)) return A else return copy!(A, a) @@ -446,7 +446,7 @@ function convert(::Type{Array{T, 1}}, o::PyObject) where T<:NPY_TYPES 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) - A = Array{pyany_toany(T)}(len) + A = Array{pyany_toany(T)}(uninitialized, len) py2array(T, A, o, 1, 1) end end @@ -457,7 +457,7 @@ function convert(::Type{Array{T}}, o::PyObject) where T<:NPY_TYPES try copy(PyArray{T, length(info.sz)}(o, info)) # will check T == info.T catch - return py2array(T, Array{pyany_toany(T)}(info.sz...), o, 1, 1) + return py2array(T, Array{pyany_toany(T)}(uninitialized, info.sz...), o, 1, 1) end catch py2array(T, o) @@ -474,7 +474,7 @@ function convert(::Type{Array{T,N}}, o::PyObject) where {T<:NPY_TYPES,N} if nd != N throw(ArgumentError("cannot convert $(nd)d array to $(N)d")) end - return py2array(T, Array{pyany_toany(T)}(info.sz...), o, 1, 1) + return py2array(T, Array{pyany_toany(T)}(uninitialized, info.sz...), o, 1, 1) end catch A = py2array(T, o) diff --git a/src/pybuffer.jl b/src/pybuffer.jl index 4f12144f..11141b2c 100644 --- a/src/pybuffer.jl +++ b/src/pybuffer.jl @@ -7,7 +7,7 @@ # mirror of Py_buffer struct in Python Include/object.h struct Py_buffer - buf::Ptr{Void} + buf::Ptr{Cvoid} obj::PyPtr len::Cssize_t itemsize::Cssize_t @@ -21,9 +21,9 @@ struct Py_buffer # some opaque padding fields to account for differences between # Python versions (the structure changed in Python 2.7 and 3.3) - internal0::Ptr{Void} - internal1::Ptr{Void} - internal2::Ptr{Void} + internal0::Ptr{Cvoid} + internal1::Ptr{Cvoid} + internal2::Ptr{Cvoid} end mutable struct PyBuffer @@ -32,7 +32,7 @@ mutable struct PyBuffer b = new(Py_buffer(C_NULL, C_NULL, 0, 0, 0, 0, C_NULL, C_NULL, C_NULL, C_NULL, C_NULL, C_NULL, C_NULL)) - finalizer(b, pydecref) + finalizer(pydecref, b) return b end end @@ -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), Void, (Any,), o) + ccall(@pysym(:PyBuffer_Release), Cvoid, (Any,), o) o end diff --git a/src/pydates.jl b/src/pydates.jl index e42e3913..e2fa9775 100644 --- a/src/pydates.jl +++ b/src/pydates.jl @@ -1,5 +1,6 @@ # Conversion functions for date and time objects in the Python datetime # module and the Julia Dates module. +import Compat.Dates # Unfortunately, the Python C API (in Python/Include/datetime.h) is somewhat # painful to call from Julia because it consists mainly of macros that @@ -17,12 +18,12 @@ struct PyDateTime_CAPI TZInfoType::PyPtr # function pointers: - Date_FromDate::Ptr{Void} - DateTime_FromDateAndTime::Ptr{Void} - Time_FromTime::Ptr{Void} - Delta_FromDelta::Ptr{Void} - DateTime_FromTimestamp::Ptr{Void} - Date_FromTimestamp::Ptr{Void} + Date_FromDate::Ptr{Cvoid} + DateTime_FromDateAndTime::Ptr{Cvoid} + Time_FromTime::Ptr{Cvoid} + Delta_FromDelta::Ptr{Cvoid} + DateTime_FromTimestamp::Ptr{Cvoid} + Date_FromTimestamp::Ptr{Cvoid} end struct PyDateTime_Delta{H} # H = Clong in Python 2, Py_hash_t in Python 3 @@ -51,9 +52,9 @@ const PyDate_HEAD = sizeof(Int)+sizeof(PyPtr)+sizeof(Py_hash_t)+1 const DateType = Ref{PyPtr}(0) const DateTimeType = Ref{PyPtr}(0) const DeltaType = Ref{PyPtr}(0) -const Date_FromDate = Ref{Ptr{Void}}(0) -const DateTime_FromDateAndTime = Ref{Ptr{Void}}(0) -const Delta_FromDelta = Ref{Ptr{Void}}(0) +const Date_FromDate = Ref{Ptr{Cvoid}}(0) +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), diff --git a/src/pyinit.jl b/src/pyinit.jl index 9f363cdb..13a752e4 100644 --- a/src/pyinit.jl +++ b/src/pyinit.jl @@ -34,19 +34,19 @@ function __init__() Py_SetPythonHome(libpy_handle, PYTHONHOME, wPYTHONHOME, pyversion) if !isempty(pyprogramname) if pyversion.major < 3 - ccall((@pysym :Py_SetProgramName), Void, (Cstring,), pyprogramname) + ccall((@pysym :Py_SetProgramName), Cvoid, (Cstring,), pyprogramname) else - ccall((@pysym :Py_SetProgramName), Void, (Ptr{Cwchar_t},), wpyprogramname) + ccall((@pysym :Py_SetProgramName), Cvoid, (Ptr{Cwchar_t},), wpyprogramname) end end - ccall((@pysym :Py_InitializeEx), Void, (Cint,), 0) + ccall((@pysym :Py_InitializeEx), Cvoid, (Cint,), 0) end # Will get reinitialized properly on first use Compat.Sys.iswindows() && (PyActCtx[] = C_NULL) # Make sure python wasn't upgraded underneath us - new_pyversion = convert(VersionNumber, split(unsafe_string(ccall(@pysym(:Py_GetVersion), + new_pyversion = VersionNumber(split(unsafe_string(ccall(@pysym(:Py_GetVersion), Ptr{UInt8}, ())))[1]) if new_pyversion.major != pyversion.major @@ -89,11 +89,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) - Base.@gc_preserve ref0 ccall(@pysym(:PySys_SetArgvEx), Void, - (Cint, Ref{Ptr{Void}}, Cint), + GC.@preserve ref0 ccall(@pysym(:PySys_SetArgvEx), Cvoid, + (Cint, Ref{Ptr{Cvoid}}, Cint), 1, pointer_from_objref(ref0), 0) else - ccall(@pysym(:PySys_SetArgvEx), Void, (Cint, Ptr{Cwstring}, Cint), + ccall(@pysym(:PySys_SetArgvEx), Cvoid, (Cint, Ptr{Cwstring}, Cint), 1, [""], 0) end diff --git a/src/pyiterator.jl b/src/pyiterator.jl index da8330db..191ccc12 100644 --- a/src/pyiterator.jl +++ b/src/pyiterator.jl @@ -29,7 +29,7 @@ done(po::PyObject, s) = s[1].o == C_NULL # issue #216 function Base.collect(::Type{T}, o::PyObject) where T - a = Array{T}(0) + a = T[] for x in o push!(a, x) end diff --git a/src/pytype.jl b/src/pytype.jl index c538c0f3..bc35306c 100644 --- a/src/pytype.jl +++ b/src/pytype.jl @@ -15,7 +15,7 @@ end struct PyMethodDef ml_name::Ptr{UInt8} - ml_meth::Ptr{Void} + ml_meth::Ptr{Cvoid} ml_flags::Cint ml_doc::Ptr{UInt8} # may be NULL end @@ -60,23 +60,23 @@ PyMethodDef() = PyMethodDef(NULL_UInt8_Ptr, C_NULL, struct PyGetSetDef name::Ptr{UInt8} - get::Ptr{Void} - set::Ptr{Void} # may be NULL for read-only members + get::Ptr{Cvoid} + set::Ptr{Cvoid} # may be NULL for read-only members doc::Ptr{UInt8} # may be NULL - closure::Ptr{Void} # pass-through thunk, may be NULL + closure::Ptr{Cvoid} # pass-through thunk, may be NULL end function PyGetSetDef(name::AbstractString, get::Function,set::Function, doc::AbstractString="") PyGetSetDef(gstring_ptr(name, name), - cfunction(get, PyPtr, Tuple{PyPtr,Ptr{Void}}), - cfunction(set, Int, Tuple{PyPtr,PyPtr,Ptr{Void}}), + cfunction(get, PyPtr, Tuple{PyPtr,Ptr{Cvoid}}), + cfunction(set, Int, Tuple{PyPtr,PyPtr,Ptr{Cvoid}}), isempty(doc) ? NULL_UInt8_Ptr : gstring_ptr(name, doc), C_NULL) end function PyGetSetDef(name::AbstractString, get::Function, doc::AbstractString="") PyGetSetDef(gstring_ptr(name, name), - cfunction(get, PyPtr, Tuple{PyPtr,Ptr{Void}}), + cfunction(get, PyPtr, Tuple{PyPtr,Ptr{Cvoid}}), C_NULL, isempty(doc) ? NULL_UInt8_Ptr : gstring_ptr(name, doc), C_NULL) @@ -190,63 +190,63 @@ mutable struct PyTypeObject tp_basicsize::Int # required, = sizeof(instance) tp_itemsize::Int - tp_dealloc::Ptr{Void} - tp_print::Ptr{Void} - tp_getattr::Ptr{Void} - tp_setattr::Ptr{Void} - tp_compare::Ptr{Void} - tp_repr::Ptr{Void} + tp_dealloc::Ptr{Cvoid} + tp_print::Ptr{Cvoid} + tp_getattr::Ptr{Cvoid} + tp_setattr::Ptr{Cvoid} + tp_compare::Ptr{Cvoid} + tp_repr::Ptr{Cvoid} - tp_as_number::Ptr{Void} - tp_as_sequence::Ptr{Void} - tp_as_mapping::Ptr{Void} + tp_as_number::Ptr{Cvoid} + tp_as_sequence::Ptr{Cvoid} + tp_as_mapping::Ptr{Cvoid} - tp_hash::Ptr{Void} - tp_call::Ptr{Void} - tp_str::Ptr{Void} - tp_getattro::Ptr{Void} - tp_setattro::Ptr{Void} + tp_hash::Ptr{Cvoid} + tp_call::Ptr{Cvoid} + tp_str::Ptr{Cvoid} + tp_getattro::Ptr{Cvoid} + tp_setattro::Ptr{Cvoid} - tp_as_buffer::Ptr{Void} + tp_as_buffer::Ptr{Cvoid} tp_flags::Clong # Required, should default to Py_TPFLAGS_DEFAULT tp_doc::Ptr{UInt8} # normally set in example code, but may be NULL - tp_traverse::Ptr{Void} + tp_traverse::Ptr{Cvoid} - tp_clear::Ptr{Void} + tp_clear::Ptr{Cvoid} - tp_richcompare::Ptr{Void} + tp_richcompare::Ptr{Cvoid} tp_weaklistoffset::Int # added in Python 2.2: - tp_iter::Ptr{Void} - tp_iternext::Ptr{Void} + tp_iter::Ptr{Cvoid} + tp_iternext::Ptr{Cvoid} tp_methods::Ptr{PyMethodDef} tp_members::Ptr{PyMemberDef} tp_getset::Ptr{PyGetSetDef} - tp_base::Ptr{Void} + tp_base::Ptr{Cvoid} tp_dict::PyPtr - tp_descr_get::Ptr{Void} - tp_descr_set::Ptr{Void} + tp_descr_get::Ptr{Cvoid} + tp_descr_set::Ptr{Cvoid} tp_dictoffset::Int - tp_init::Ptr{Void} - tp_alloc::Ptr{Void} - tp_new::Ptr{Void} - tp_free::Ptr{Void} - tp_is_gc::Ptr{Void} + tp_init::Ptr{Cvoid} + tp_alloc::Ptr{Cvoid} + tp_new::Ptr{Cvoid} + tp_free::Ptr{Cvoid} + tp_is_gc::Ptr{Cvoid} tp_bases::PyPtr tp_mro::PyPtr tp_cache::PyPtr tp_subclasses::PyPtr tp_weaklist::PyPtr - tp_del::Ptr{Void} + tp_del::Ptr{Cvoid} # added in Python 2.6: tp_version_tag::Cuint @@ -255,8 +255,8 @@ mutable struct PyTypeObject tp_allocs::Int tp_frees::Int tp_maxalloc::Int - tp_prev::Ptr{Void} - tp_next::Ptr{Void} + tp_prev::Ptr{Cvoid} + tp_next::Ptr{Cvoid} # Julia-specific fields, after the end of the Python structure: @@ -321,7 +321,7 @@ function PyTypeObject!(init::Function, t::PyTypeObject, name::AbstractString, ba end # TODO change to `Ref{PyTypeObject}` when 0.6 is dropped. @pycheckz ccall((@pysym :PyType_Ready), Cint, (Any,), t) - ccall((@pysym :Py_IncRef), Void, (Any,), t) + ccall((@pysym :Py_IncRef), Cvoid, (Any,), t) return t end @@ -343,7 +343,7 @@ function pyjlwrap_dealloc(o::PyPtr) end unsafe_pyjlwrap_to_objref(o::PyPtr) = - unsafe_pointer_to_objref(unsafe_load(convert(Ptr{Ptr{Void}}, o), 3)) + unsafe_pointer_to_objref(unsafe_load(convert(Ptr{Ptr{Cvoid}}, o), 3)) pyjlwrap_repr(o::PyPtr) = pystealref!(PyObject(o != C_NULL ? string("") @@ -415,7 +415,7 @@ function pyjlwrap_init() PyMemberDef(C_NULL,0,0,0,C_NULL)) # all cfunctions must be compiled at runtime - pyjlwrap_dealloc_ptr = cfunction(pyjlwrap_dealloc, Void, Tuple{PyPtr}) + pyjlwrap_dealloc_ptr = cfunction(pyjlwrap_dealloc, Cvoid, Tuple{PyPtr}) pyjlwrap_repr_ptr = cfunction(pyjlwrap_repr, PyPtr, Tuple{PyPtr}) pyjlwrap_hash_ptr = cfunction(pyjlwrap_hash, UInt, Tuple{PyPtr}) pyjlwrap_hash32_ptr = cfunction(pyjlwrap_hash32, UInt32, Tuple{PyPtr}) @@ -447,8 +447,8 @@ function pyjlwrap_type!(init::Function, to::PyTypeObject, name::AbstractString) sz = sizeof(Py_jlWrap) + sizeof(PyPtr) # must be > base type 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{Void}, (Any,), jlWrapType) - ccall((@pysym :Py_IncRef), Void, (Any,), jlWrapType) + t.tp_base = ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), jlWrapType) + ccall((@pysym :Py_IncRef), Cvoid, (Any,), jlWrapType) init(t) end end @@ -464,7 +464,7 @@ function pyjlwrap_new(pyT::PyTypeObject, value::Any) # TODO change to `Ref{PyTypeObject}` when 0.6 is dropped. o = PyObject(@pycheckn ccall((@pysym :_PyObject_New), PyPtr, (Any,), pyT)) - p = convert(Ptr{Ptr{Void}}, o.o) + p = convert(Ptr{Ptr{Cvoid}}, o.o) if isimmutable(value) # It is undefined to call `pointer_from_objref` on immutable objects. # The compiler is free to return basically anything since the boxing is not @@ -473,7 +473,7 @@ function pyjlwrap_new(pyT::PyTypeObject, value::Any) # the lifetime of the pointer `ref`. ref = Ref{Any}(value) pycall_gc[o.o] = ref - ptr = unsafe_load(Ptr{Ptr{Void}}(pointer_from_objref(ref))) + ptr = unsafe_load(Ptr{Ptr{Cvoid}}(pointer_from_objref(ref))) else pycall_gc[o.o] = value ptr = pointer_from_objref(value) diff --git a/src/serialize.jl b/src/serialize.jl index 7035b51c..2885b456 100644 --- a/src/serialize.jl +++ b/src/serialize.jl @@ -1,8 +1,11 @@ +using Compat.Serialization +import Compat.Serialization: serialize, deserialize + const _pickle = PyNULL() pickle() = _pickle.o == C_NULL ? copy!(_pickle, pyimport(PyCall.pyversion.major ≥ 3 ? "pickle" : "cPickle")) : _pickle -function Base.serialize(s::AbstractSerializer, pyo::PyObject) +function serialize(s::AbstractSerializer, pyo::PyObject) Serializer.serialize_type(s, PyObject) if pyo.o == C_NULL serialize(s, pyo.o) @@ -24,7 +27,7 @@ pybytes(b::Union{String,Array{UInt8}}) = PyObject(@pycheckn ccall(@pysym(PyStrin PyPtr, (Ptr{UInt8}, Int), b, sizeof(b))) -function Base.deserialize(s::AbstractSerializer, t::Type{PyObject}) +function deserialize(s::AbstractSerializer, t::Type{PyObject}) b = deserialize(s) if isa(b, PyPtr) @assert b == C_NULL diff --git a/src/startup.jl b/src/startup.jl index 59189362..ff4c9190 100644 --- a/src/startup.jl +++ b/src/startup.jl @@ -3,32 +3,32 @@ # and if so do not use the deps.jl file, getting everything we need from the # current process instead. -proc_handle = unsafe_load(cglobal(:jl_exe_handle, Ptr{Void})) +proc_handle = unsafe_load(cglobal(:jl_exe_handle, Ptr{Cvoid})) struct Dl_info dli_fname::Ptr{UInt8} - dli_fbase::Ptr{Void} + dli_fbase::Ptr{Cvoid} dli_sname::Ptr{UInt8} - dli_saddr::Ptr{Void} + dli_saddr::Ptr{Cvoid} end EnumProcessModules(hProcess, lphModule, cb, lpcbNeeded) = ccall(:K32EnumProcessModules, stdcall, Bool, - (Ptr{Void}, Ptr{Ptr{Void}}, UInt32, Ptr{UInt32}), + (Ptr{Cvoid}, Ptr{Ptr{Cvoid}}, UInt32, Ptr{UInt32}), hProcess, lphModule, cb, lpcbNeeded) symbols_present = false @static if Compat.Sys.iswindows() lpcbneeded = Ref{UInt32}() - proc_handle = ccall(:GetCurrentProcess, stdcall, Ptr{Void}, ()) - handles = Vector{Ptr{Void}}(20) + proc_handle = ccall(:GetCurrentProcess, stdcall, Ptr{Cvoid}, ()) + handles = Vector{Ptr{Cvoid}}(20) if EnumProcessModules(proc_handle, handles, sizeof(handles), lpcbneeded) == 0 - resize!(handles, div(lpcbneeded[],sizeof(Ptr{Void}))) + resize!(handles, div(lpcbneeded[],sizeof(Ptr{Cvoid}))) EnumProcessModules(proc_handle, handles, sizeof(handles), lpcbneeded) end # Try to find python if it's in the current process for handle in handles - sym = ccall(:GetProcAddress, stdcall, Ptr{Void}, - (Ptr{Void}, Ptr{UInt8}), handle, "Py_GetVersion") + sym = ccall(:GetProcAddress, stdcall, Ptr{Cvoid}, + (Ptr{Cvoid}, Ptr{UInt8}), handle, "Py_GetVersion") sym != C_NULL || continue symbols_present = true global libpy_handle = handle @@ -51,7 +51,7 @@ else @static if Compat.Sys.iswindows() pathbuf = Vector{UInt16}(1024) ret = ccall(:GetModuleFileNameW, stdcall, UInt32, - (Ptr{Void}, Ptr{UInt16}, UInt32), + (Ptr{Cvoid}, Ptr{UInt16}, UInt32), libpy_handle, pathbuf, length(pathbuf)) @assert ret != 0 libname = String(Base.transcode(UInt8, pathbuf[1:findfirst(pathbuf, 0)-1])) @@ -67,9 +67,9 @@ else some_address_in_main_exe = Libdl.dlsym(proc_handle, Compat.Sys.isapple() ? :_mh_execute_header : :main) dlinfo1 = Ref{Dl_info}() dlinfo2 = Ref{Dl_info}() - ccall(:dladdr, Cint, (Ptr{Void}, Ptr{Dl_info}), some_address_in_libpython, + ccall(:dladdr, Cint, (Ptr{Cvoid}, Ptr{Dl_info}), some_address_in_libpython, dlinfo1) - ccall(:dladdr, Cint, (Ptr{Void}, Ptr{Dl_info}), some_address_in_main_exe, + ccall(:dladdr, Cint, (Ptr{Cvoid}, Ptr{Dl_info}), some_address_in_main_exe, dlinfo2) if dlinfo1[].dli_fbase == dlinfo2[].dli_fbase const libpython = nothing @@ -82,7 +82,7 @@ else const conda = false end -const pyversion = convert(VersionNumber, split(Py_GetVersion(libpy_handle))[1]) +const pyversion = VersionNumber(split(Py_GetVersion(libpy_handle))[1]) # PyUnicode_* may actually be a #define for another symbol, so # we cache the correct dlsym diff --git a/test/runtests.jl b/test/runtests.jl index 7dd7db41..318ad461 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,14 +1,12 @@ using Compat.Test, PyCall, Compat -if isdefined(Base, :Iterators) - filter(f, itr) = collect(Iterators.filter(f, itr)) - filter(f, d::Associative) = Base.filter(f, d) -end +filter(f, itr) = collect(Iterators.filter(f, itr)) +filter(f, d::AbstractDict) = Base.filter(f, d) PYTHONPATH=get(ENV,"PYTHONPATH","") PYTHONHOME=get(ENV,"PYTHONHOME","") PYTHONEXECUTABLE=get(ENV,"PYTHONEXECUTABLE","") -info("Python version $pyversion from $(PyCall.libpython), PYTHONHOME=$(PyCall.PYTHONHOME)\nENV[PYTHONPATH]=$PYTHONPATH\nENV[PYTHONHOME]=$PYTHONHOME\nENV[PYTHONEXECUTABLE]=$PYTHONEXECUTABLE") +@info "Python version $pyversion from $(PyCall.libpython), PYTHONHOME=$(PyCall.PYTHONHOME)\nENV[PYTHONPATH]=$PYTHONPATH\nENV[PYTHONHOME]=$PYTHONHOME\nENV[PYTHONEXECUTABLE]=$PYTHONEXECUTABLE" roundtrip(T, x) = convert(T, PyObject(x)) roundtrip(x) = roundtrip(PyAny, x) @@ -35,7 +33,7 @@ import PyCall.pyany_toany @test roundtripeq("Hello \0\0\0world") @test roundtripeq("Hël\0\0lö") @test roundtripeq(Symbol, :Hello) -@test roundtripeq(C_NULL) && roundtripeq(convert(Ptr{Void}, 12345)) +@test roundtripeq(C_NULL) && roundtripeq(convert(Ptr{Cvoid}, 12345)) @test roundtripeq([1,3,4,5]) && roundtripeq([1,3.2,"hello",true]) @test roundtripeq([1 2 3;4 5 6]) && roundtripeq([1. 2 3;4 5 6]) @test roundtripeq((1,(3.2,"hello"),true)) && roundtripeq(()) @@ -131,16 +129,14 @@ let x = PyVector(PyAny[]) @test x == ["bar"] end -if pyversion >= v"2.7" && isdefined(PyCall, :PyDateTime_CAPI) - @test roundtripeq(Dates.Date(2012,3,4)) - @test roundtripeq(Dates.DateTime(2012,3,4, 7,8,9,11)) - @test roundtripeq(Dates.Millisecond(typemax(Int32))) - @test roundtripeq(Dates.Millisecond(typemin(Int32))) - @test roundtripeq(Dates.Second, Dates.Second(typemax(Int32))) - @test roundtripeq(Dates.Second, Dates.Second(typemin(Int32))) - @test roundtripeq(Dates.Day, Dates.Day(999999999)) # max allowed day timedelta - @test roundtripeq(Dates.Day, Dates.Day(-999999999)) # min allowed day timedelta -end +@test roundtripeq(Dates.Date(2012,3,4)) +@test roundtripeq(Dates.DateTime(2012,3,4, 7,8,9,11)) +@test roundtripeq(Dates.Millisecond(typemax(Int32))) +@test roundtripeq(Dates.Millisecond(typemin(Int32))) +@test roundtripeq(Dates.Second, Dates.Second(typemax(Int32))) +@test roundtripeq(Dates.Second, Dates.Second(typemin(Int32))) +@test roundtripeq(Dates.Day, Dates.Day(999999999)) # max allowed day timedelta +@test roundtripeq(Dates.Day, Dates.Day(-999999999)) # min allowed day timedelta # fixme: is there any nontrivial mimewritable test we can do? @test !mimewritable("text/html", PyObject(1)) @@ -151,7 +147,7 @@ pyutf8(s::PyObject) = pycall(s["encode"], PyObject, "utf-8") pyutf8(s::String) = pyutf8(PyObject(s)) # IO (issue #107) -#@test roundtripeq(STDOUT) # No longer true since #250 +#@test roundtripeq(stdout) # No longer true since #250 let buf = IOBuffer(false, true), obuf = PyObject(buf) @test !obuf[:isatty]() @test obuf[:writable]() @@ -211,7 +207,7 @@ pyanycheck(x::Any) = pyanycheck(typeof(x), PyObject(x)) pyanycheck(T, o::PyObject) = isa(convert(PyAny, o), T) @test pyanycheck(Int, PyVector{PyObject}(PyObject([1]))[1]) @test pyanycheck(Float64, PyVector{PyObject}(PyObject([1.3]))[1]) -@test pyanycheck(Complex128, PyVector{PyObject}(PyObject([1.3+1im]))[1]) +@test pyanycheck(ComplexF64, PyVector{PyObject}(PyObject([1.3+1im]))[1]) @test pyanycheck(Bool, PyVector{PyObject}(PyObject([true]))[1]) # conversions of Int128 and BigInt @@ -282,8 +278,8 @@ end let o = PyObject(Any[8,3]) @test collect(push!(o, 5)) == [8,3,5] @test pop!(o) == 5 && collect(o) == [8,3] - @test shift!(o) == 8 && collect(o) == [3] - @test collect(unshift!(o, 9)) == [9,3] + @test popfirst!(o) == 8 && collect(o) == [3] + @test collect(pushfirst!(o, 9)) == [9,3] @test collect(prepend!(o, [5,4,2])) == [5,4,2,9,3] @test collect(append!(o, [1,6,8])) == [5,4,2,9,3,1,6,8] @test isempty(empty!(o)) @@ -363,16 +359,14 @@ let weakdict = pyimport("weakref")["WeakValueDictionary"] end # Expose python docs to Julia doc system -if isdefined(Docs, :getdoc) - py""" - def foo(): - "foo docstring" - return 0 - """ - foo = py"foo" - # use 'content' since `Text` objects test equality by object identity - @test @doc(foo).content == "foo docstring" -end +py""" +def foo(): + "foo docstring" + return 0 +""" +foo = py"foo" +# use 'content' since `Text` objects test equality by object identity +@test @doc(foo).content == "foo docstring" # binary operators for b in (4, PyObject(4)) From cec1210ff6ae28c0afa535e23bad908ad8c546f1 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 7 Mar 2018 16:23:17 -0500 Subject: [PATCH 2/2] fixed missing compat calls --- deps/build.jl | 10 +++++----- src/PyCall.jl | 6 +++--- src/pybuffer.jl | 2 +- test/runtests.jl | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/deps/build.jl b/deps/build.jl index 5d463e50..bf0f9b59 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -150,10 +150,10 @@ wstringconst(s) = string("Base.cconvert(Cwstring, \"", escape_string(s), "\")") # problems in the unlikely event of read-only directories. function writeifchanged(filename, str) if !isfile(filename) || read(filename, String) != str - @info string(abspath(filename), " has been updated") + Compat.@info string(abspath(filename), " has been updated") write(filename, str) else - @info string(abspath(filename), " has not changed") + Compat.@info string(abspath(filename), " has not changed") end end @@ -182,10 +182,10 @@ try # make sure deps.jl file is removed on error catch e1 if Sys.ARCH in (:i686, :x86_64) if isa(e1, UseCondaPython) - @info string("Using the Python distribution in the Conda package by default.\n", + Compat.@info string("Using the Python distribution in the Conda package by default.\n", "To use a different Python version, set ENV[\"PYTHON\"]=\"pythoncommand\" and re-run Pkg.build(\"PyCall\").") else - @info string( "No system-wide Python was found; got the following error:\n", + Compat.@info string( "No system-wide Python was found; got the following error:\n", "$e1\nusing the Python distribution in the Conda package") end abspath(Conda.PYTHONDIR, "python" * (Compat.Sys.iswindows() ? ".exe" : "")) @@ -222,7 +222,7 @@ try # make sure deps.jl file is removed on error # cache the Python version as a Julia VersionNumber pyversion = VersionNumber(pyvar(python, "platform", "python_version()")) - @info "PyCall is using $python (Python $pyversion) at $programname, libpython = $libpy_name" + Compat.@info "PyCall is using $python (Python $pyversion) at $programname, libpython = $libpy_name" if pyversion < v"2.7" error("Python 2.7 or later is required for PyCall") diff --git a/src/PyCall.jl b/src/PyCall.jl index 1dd4228b..1c28e4bf 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -68,7 +68,7 @@ mutable struct PyObject o::PyPtr # the actual PyObject* function PyObject(o::PyPtr) po = new(o) - finalizer(pydecref, po) + @compat finalizer(pydecref, po) return po end end @@ -611,7 +611,7 @@ function pyimport_conda(modulename::AbstractString, condapkg::AbstractString, pyimport(modulename) catch e if conda - @info "Installing $modulename via the Conda $condapkg package..." + Compat.@info "Installing $modulename via the Conda $condapkg package..." isempty(channel) || Conda.add_channel(channel) Conda.add(condapkg) pyimport(modulename) @@ -619,7 +619,7 @@ function pyimport_conda(modulename::AbstractString, condapkg::AbstractString, aconda = anaconda_conda() if !isempty(aconda) try - @info "Installing $modulename via Anaconda's $aconda..." + Compat.@info "Installing $modulename via Anaconda's $aconda..." isempty(channel) || run(`$aconda config --add channels $channel --force`) run(`$aconda install -y $condapkg`) catch e2 diff --git a/src/pybuffer.jl b/src/pybuffer.jl index 11141b2c..06295261 100644 --- a/src/pybuffer.jl +++ b/src/pybuffer.jl @@ -32,7 +32,7 @@ mutable struct PyBuffer b = new(Py_buffer(C_NULL, C_NULL, 0, 0, 0, 0, C_NULL, C_NULL, C_NULL, C_NULL, C_NULL, C_NULL, C_NULL)) - finalizer(pydecref, b) + @compat finalizer(pydecref, b) return b end end diff --git a/test/runtests.jl b/test/runtests.jl index 318ad461..7ae6ba7f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -6,7 +6,7 @@ filter(f, d::AbstractDict) = Base.filter(f, d) PYTHONPATH=get(ENV,"PYTHONPATH","") PYTHONHOME=get(ENV,"PYTHONHOME","") PYTHONEXECUTABLE=get(ENV,"PYTHONEXECUTABLE","") -@info "Python version $pyversion from $(PyCall.libpython), PYTHONHOME=$(PyCall.PYTHONHOME)\nENV[PYTHONPATH]=$PYTHONPATH\nENV[PYTHONHOME]=$PYTHONHOME\nENV[PYTHONEXECUTABLE]=$PYTHONEXECUTABLE" +Compat.@info "Python version $pyversion from $(PyCall.libpython), PYTHONHOME=$(PyCall.PYTHONHOME)\nENV[PYTHONPATH]=$PYTHONPATH\nENV[PYTHONHOME]=$PYTHONHOME\nENV[PYTHONEXECUTABLE]=$PYTHONEXECUTABLE" roundtrip(T, x) = convert(T, PyObject(x)) roundtrip(x) = roundtrip(PyAny, x)