diff --git a/REQUIRE b/REQUIRE index a08ef4f1..32656555 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,4 +1,4 @@ julia 0.5 -Compat 0.27.0 +Compat 0.32.0 Conda 0.2 MacroTools 0.3 diff --git a/deps/build.jl b/deps/build.jl index ea57d865..46f6251f 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -10,8 +10,6 @@ import Conda immutable UseCondaPython <: Exception end -try # make sure deps.jl file is removed on error - ######################################################################### # Fix the environment for running `python`, and setts IO encoding to UTF-8. @@ -36,7 +34,7 @@ function pythonenv(cmd::Cmd) setenv(cmd, env) end -pyvar(python::AbstractString, mod::AbstractString, var::AbstractString) = chomp(readstring(pythonenv(`$python -c "import $mod; print($mod.$var)"`))) +pyvar(python::AbstractString, mod::AbstractString, var::AbstractString) = chomp(read(pythonenv(`$python -c "import $mod; print($mod.$var)"`), String)) pyconfigvar(python::AbstractString, var::AbstractString) = pyvar(python, "distutils.sysconfig", "get_config_var('$var')") pyconfigvar(python, var, default) = let v = pyconfigvar(python, var) @@ -113,7 +111,7 @@ function find_libpython(python::AbstractString) print(s, "\n\n") end println(STDERR, "---------------------------------- get_config_vars ---------------------------------------") - print(STDERR, readstring(`python -c "import distutils.sysconfig; print(distutils.sysconfig.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) @@ -142,76 +140,6 @@ include("depsutils.jl") ######################################################################### -const python = try - let py = get(ENV, "PYTHON", isfile("PYTHON") ? readchomp("PYTHON") : - Compat.Sys.islinux() || Sys.ARCH ∉ (:i686, :x86_64) ? "python" : ""), - vers = isempty(py) ? v"0.0" : convert(VersionNumber, pyconfigvar(py,"VERSION","0.0")) - if vers < v"2.7" - if isempty(py) - throw(UseCondaPython()) - else - error("Python version $vers < 2.7 is not supported") - end - end - - # check word size of Python via sys.maxsize, since a common error - # on Windows is to link a 64-bit Julia to a 32-bit Python. - pywordsize = parse(UInt64, pysys(py, "maxsize")) > (UInt64(1)<<32) ? 64 : 32 - if pywordsize != Sys.WORD_SIZE - error("$py is $(pywordsize)-bit, but Julia is $(Sys.WORD_SIZE)-bit") - end - - py - end -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", - "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", - "$e1\nusing the Python distribution in the Conda package") - end - abspath(Conda.PYTHONDIR, "python" * (Compat.Sys.iswindows() ? ".exe" : "")) - else - error("No system-wide Python was found; got the following error:\n", - "$e1") - end -end - -use_conda = dirname(python) == abspath(Conda.PYTHONDIR) -if use_conda - Conda.add("numpy") -end - -const (libpython, libpy_name) = find_libpython(python) -const programname = pysys(python, "executable") - -# Get PYTHONHOME, either from the environment or from Python -# itself (if it is not in the environment or if we are using Conda) -PYTHONHOME = if !haskey(ENV, "PYTHONHOME") || use_conda - # PYTHONHOME tells python where to look for both pure python - # and binary modules. When it is set, it replaces both - # `prefix` and `exec_prefix` and we thus need to set it to - # both in case they differ. This is also what the - # documentation recommends. However, they are documented - # to always be the same on Windows, where it causes - # problems if we try to include both. - exec_prefix = pysys(python, "exec_prefix") - Compat.Sys.iswindows() ? exec_prefix : pysys(python, "prefix") * ":" * exec_prefix -else - ENV["PYTHONHOME"] -end - -# cache the Python version as a Julia VersionNumber -const pyversion = VersionNumber(pyvar(python, "platform", "python_version()")) - -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") -end - # A couple of key strings need to be stored as constants so that # they persist throughout the life of the program. In Python 3, # they need to be wchar_t* data. @@ -221,7 +149,7 @@ wstringconst(s) = string("Base.cconvert(Cwstring, \"", escape_string(s), "\")") # to prevent unnecessary recompilation and to minimize # problems in the unlikely event of read-only directories. function writeifchanged(filename, str) - if !isfile(filename) || readstring(filename) != str + if !isfile(filename) || read(filename, String) != str info(abspath(filename), " has been updated") write(filename, str) else @@ -229,7 +157,78 @@ function writeifchanged(filename, str) end end -writeifchanged("deps.jl", """ +try # make sure deps.jl file is removed on error + python = try + let py = get(ENV, "PYTHON", isfile("PYTHON") ? readchomp("PYTHON") : + Compat.Sys.islinux() || Sys.ARCH ∉ (:i686, :x86_64) ? "python" : ""), + vers = isempty(py) ? v"0.0" : convert(VersionNumber, pyconfigvar(py,"VERSION","0.0")) + if vers < v"2.7" + if isempty(py) + throw(UseCondaPython()) + else + error("Python version $vers < 2.7 is not supported") + end + end + + # check word size of Python via sys.maxsize, since a common error + # on Windows is to link a 64-bit Julia to a 32-bit Python. + pywordsize = parse(UInt64, pysys(py, "maxsize")) > (UInt64(1)<<32) ? 64 : 32 + if pywordsize != Sys.WORD_SIZE + error("$py is $(pywordsize)-bit, but Julia is $(Sys.WORD_SIZE)-bit") + end + + py + end + 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", + "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", + "$e1\nusing the Python distribution in the Conda package") + end + abspath(Conda.PYTHONDIR, "python" * (Compat.Sys.iswindows() ? ".exe" : "")) + else + error("No system-wide Python was found; got the following error:\n", + "$e1") + end + end + + use_conda = dirname(python) == abspath(Conda.PYTHONDIR) + if use_conda + Conda.add("numpy") + end + + (libpython, libpy_name) = find_libpython(python) + programname = pysys(python, "executable") + + # Get PYTHONHOME, either from the environment or from Python + # itself (if it is not in the environment or if we are using Conda) + PYTHONHOME = if !haskey(ENV, "PYTHONHOME") || use_conda + # PYTHONHOME tells python where to look for both pure python + # and binary modules. When it is set, it replaces both + # `prefix` and `exec_prefix` and we thus need to set it to + # both in case they differ. This is also what the + # documentation recommends. However, they are documented + # to always be the same on Windows, where it causes + # problems if we try to include both. + exec_prefix = pysys(python, "exec_prefix") + Compat.Sys.iswindows() ? exec_prefix : pysys(python, "prefix") * ":" * exec_prefix + else + ENV["PYTHONHOME"] + end + + # 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") + + if pyversion < v"2.7" + error("Python 2.7 or later is required for PyCall") + end + + writeifchanged("deps.jl", """ const python = "$(escape_string(python))" const libpython = "$(escape_string(libpy_name))" const pyprogramname = "$(escape_string(programname))" @@ -242,16 +241,16 @@ writeifchanged("deps.jl", """ const conda = $use_conda """) -# Make subsequent builds (e.g. Pkg.update) use the same Python by default: -writeifchanged("PYTHON", isfile(programname) ? programname : python) + # Make subsequent builds (e.g. Pkg.update) use the same Python by default: + writeifchanged("PYTHON", isfile(programname) ? programname : python) -######################################################################### + ######################################################################### catch -# remove deps.jl (if it exists) on an error, so that PyCall will -# not load until it is properly configured. -isfile("deps.jl") && rm("deps.jl") -rethrow() + # remove deps.jl (if it exists) on an error, so that PyCall will + # not load until it is properly configured. + isfile("deps.jl") && rm("deps.jl") + rethrow() end diff --git a/src/PyCall.jl b/src/PyCall.jl index bab1c1b4..583eb475 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -432,6 +432,7 @@ end pyimport(name::Symbol) = pyimport(string(name)) # convert expressions like :math or :(scipy.special) into module name strings +modulename(s::QuoteNode) = modulename(s.value) modulename(s::Symbol) = string(s) function modulename(e::Expr) if e.head == :. @@ -462,8 +463,15 @@ end macro pyimport(name, optional_varname...) mname = modulename(name) Name = pyimport_name(name, optional_varname) + quoteName = Expr(:quote, Name) + # VERSION 0.7 + @static if isdefined(Base, Symbol("@isdefined")) + isdef_check = :(isdefined($__module__, $quoteName)) + else + isdef_check = :(isdefined($quoteName)) + end quote - if !isdefined($(Expr(:quote, Name))) + if !$isdef_check const $(esc(Name)) = pywrap(pyimport($mname)) elseif !isa($(esc(Name)), Module) error("@pyimport: ", $(Expr(:quote, Name)), " already defined") diff --git a/src/conversions.jl b/src/conversions.jl index 9a6a7efb..76032ba4 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -565,13 +565,13 @@ function convert{K,V}(::Type{Dict{K,V}}, o::PyObject) end ######################################################################### -# Range: integer ranges are converted to xrange, -# while other ranges (<: AbstractVector) are converted to lists +# AbstractRange: integer ranges are converted to xrange, +# while other ranges (<: AbstractVector) are converted to lists xrange(start, stop, step) = pycall(pyxrange[], PyObject, start, stop, step) -function PyObject{T<:Integer}(r::Range{T}) +function PyObject{T<:Integer}(r::AbstractRange{T}) s = step(r) f = first(r) l = last(r) + s @@ -583,7 +583,7 @@ function PyObject{T<:Integer}(r::Range{T}) end end -function convert{T<:Range}(::Type{T}, o::PyObject) +function convert{T<:AbstractRange}(::Type{T}, o::PyObject) v = PyVector(o) len = length(v) if len == 0 @@ -722,7 +722,7 @@ function pysequence_query(o::PyObject) 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]) elseif pyisinstance(o, pyxrange[]) - return Range + return AbstractRange elseif ispybytearray(o) return Vector{UInt8} else diff --git a/src/io.jl b/src/io.jl index 8dd84f86..a36383bc 100644 --- a/src/io.jl +++ b/src/io.jl @@ -108,7 +108,7 @@ function pyio_initialize() String(read(pyio_jl(self), nb < 0 ? typemax(Int) : nb)) : pybytes(read(pyio_jl(self), nb < 0 ? typemax(Int) : nb))) readall(self) = - @with_ioraise(self[:istextio] ? readstring(pyio_jl(self)) : + @with_ioraise(self[:istextio] ? read(pyio_jl(self), String) : pybytes(read(pyio_jl(self)))) readinto(self, b) = @with_ioraise(pybytes(readbytes!(pyio_jl(self), b))) write(self, b) = @with_ioraise(write(pyio_jl(self), b)) diff --git a/src/numpy.jl b/src/numpy.jl index 2b5f55eb..281438d4 100644 --- a/src/numpy.jl +++ b/src/numpy.jl @@ -74,7 +74,7 @@ function npyinitialize() # Parse __multiarray_api.h to obtain length and meaning of PyArray_API try hdrfile = open(joinpath(inc, "numpy", "__multiarray_api.h")) - hdr = readstring(hdrfile); + hdr = read(hdrfile, String) close(hdrfile) catch e error("could not read __multiarray_api.h to parse PyArray_API ", e) diff --git a/src/pybuffer.jl b/src/pybuffer.jl index 4055296e..430a55d7 100644 --- a/src/pybuffer.jl +++ b/src/pybuffer.jl @@ -40,7 +40,8 @@ end function pydecref(o::PyBuffer) # note that PyBuffer_Release sets o.obj to NULL, and # is a no-op if o.obj is already NULL - ccall(@pysym(:PyBuffer_Release), Void, (Ptr{PyBuffer},), &o) + # TODO change to `Ref{PyBuffer}` when 0.6 is dropped. + ccall(@pysym(:PyBuffer_Release), Void, (Any,), o) o end @@ -85,9 +86,10 @@ function Base.stride(b::PyBuffer, d::Integer) return Int(unsafe_load(b.buf.strides, d)) end +# TODO change to `Ref{PyBuffer}` when 0.6 is dropped. iscontiguous(b::PyBuffer) = 1 == ccall((@pysym :PyBuffer_IsContiguous), Cint, - (Ptr{PyBuffer}, Cchar), &b, 'A') + (Any, Cchar), b, 'A') ############################################################################# # pybuffer constant values from Include/object.h @@ -105,8 +107,9 @@ const PyBUF_INDIRECT = convert(Cint, 0x0100) | PyBUF_STRIDES # construct a PyBuffer from a PyObject, if possible 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, - (PyPtr, Ptr{PyBuffer}, Cint), o, &b, flags) + (PyPtr, Any, Cint), o, b, flags) return b end diff --git a/src/pyclass.jl b/src/pyclass.jl index e9016bfc..e5526b9e 100644 --- a/src/pyclass.jl +++ b/src/pyclass.jl @@ -156,7 +156,7 @@ Multiple dispatch works, too: """ macro pydef(class_expr) class_name, _, _ = parse_pydef_toplevel(class_expr) - :(const $(esc(class_name)) = @pydef_object($(esc(class_expr)))) + esc(:(const $class_name = $PyCall.@pydef_object($class_expr))) end """ diff --git a/src/pyinit.jl b/src/pyinit.jl index 622e1913..f07b6126 100644 --- a/src/pyinit.jl +++ b/src/pyinit.jl @@ -23,6 +23,18 @@ const pyxrange = Ref{PyPtr}(0) ######################################################################### +type EmptyStringList + x::Int32 + ptr::Ptr{Int32} + function EmptyStringList() + obj = new(0) + obj.ptr = pointer_from_objref(obj) + return obj + end +end +Base.unsafe_convert(::Type{Ptr{UInt32}}, x::EmptyStringList) = + Ptr{UInt32}(pointer_from_objref(x) + fieldoffset(EmptyStringList, 2)) + function __init__() # issue #189 libpy_handle = libpython === nothing ? C_NULL : @@ -87,15 +99,7 @@ function __init__() if !already_inited # some modules (e.g. IPython) expect sys.argv to be set - if pyversion.major < 3 - argv_s = "" - argv = unsafe_convert(Ptr{UInt8}, argv_s) - ccall(@pysym(:PySys_SetArgvEx), Void, (Cint,Ptr{Ptr{UInt8}},Cint), 1, &argv, 0) - else - argv_s = Cwchar_t[0] - argv = unsafe_convert(Ptr{Cwchar_t}, argv_s) - ccall(@pysym(:PySys_SetArgvEx), Void, (Cint, Ptr{Ptr{Cwchar_t}}, Cint), 1, &argv, 0) - end + ccall(@pysym(:PySys_SetArgvEx), Void, (Cint, Ptr{UInt32}, Cint), 1, EmptyStringList(), 0) # Some Python code checks sys.ps1 to see if it is running # interactively, and refuses to be interactive otherwise. diff --git a/src/pyiterator.jl b/src/pyiterator.jl index e3880d33..1366c105 100644 --- a/src/pyiterator.jl +++ b/src/pyiterator.jl @@ -49,8 +49,8 @@ const jlWrapIteratorType = PyTypeObject() function jlwrap_iterator(o::Any) if jlWrapIteratorType.tp_name == C_NULL # lazily initialize pyjlwrap_type!(jlWrapIteratorType, "PyCall.jlwrap_iterator") do t - t.tp_iter = cfunction(pyincref_, PyPtr, (PyPtr,)) # new reference to same object - t.tp_iternext = cfunction(pyjlwrap_iternext, PyPtr, (PyPtr,)) + t.tp_iter = cfunction(pyincref_, PyPtr, Tuple{PyPtr}) # new reference to same object + t.tp_iternext = cfunction(pyjlwrap_iternext, PyPtr, Tuple{PyPtr}) end end return pyjlwrap_new(jlWrapIteratorType, (o, Ref(start(o)))) diff --git a/src/pytype.jl b/src/pytype.jl index 6ea5a5c5..d827f073 100644 --- a/src/pytype.jl +++ b/src/pytype.jl @@ -68,15 +68,15 @@ end function PyGetSetDef(name::AbstractString, get::Function,set::Function, doc::AbstractString="") PyGetSetDef(gstring_ptr(name, name), - cfunction(get, PyPtr, (PyPtr,Ptr{Void})), - cfunction(set, Int, (PyPtr,PyPtr,Ptr{Void})), + cfunction(get, PyPtr, Tuple{PyPtr,Ptr{Void}}), + cfunction(set, Int, Tuple{PyPtr,PyPtr,Ptr{Void}}), 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, (PyPtr,Ptr{Void})), + cfunction(get, PyPtr, Tuple{PyPtr,Ptr{Void}}), C_NULL, isempty(doc) ? NULL_UInt8_Ptr : gstring_ptr(name, doc), C_NULL) @@ -319,8 +319,9 @@ function PyTypeObject!(init::Function, t::PyTypeObject, name::AbstractString, ba if t.tp_new == C_NULL t.tp_new = @pyglobal :PyType_GenericNew end - @pycheckz ccall((@pysym :PyType_Ready), Cint, (Ptr{PyTypeObject},), &t) - ccall((@pysym :Py_IncRef), Void, (Ptr{PyTypeObject},), &t) + # 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) return t end @@ -422,13 +423,13 @@ 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, (PyPtr,)) - pyjlwrap_repr_ptr = cfunction(pyjlwrap_repr, PyPtr, (PyPtr,)) - pyjlwrap_hash_ptr = cfunction(pyjlwrap_hash, UInt, (PyPtr,)) - pyjlwrap_hash32_ptr = cfunction(pyjlwrap_hash32, UInt32, (PyPtr,)) - pyjlwrap_call_ptr = cfunction(pyjlwrap_call, PyPtr, (PyPtr,PyPtr,PyPtr)) - pyjlwrap_getattr_ptr = cfunction(pyjlwrap_getattr, PyPtr, (PyPtr,PyPtr)) - pyjlwrap_getiter_ptr = cfunction(pyjlwrap_getiter, PyPtr, (PyPtr,)) + pyjlwrap_dealloc_ptr = cfunction(pyjlwrap_dealloc, Void, 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}) + pyjlwrap_call_ptr = cfunction(pyjlwrap_call, PyPtr, Tuple{PyPtr,PyPtr,PyPtr}) + pyjlwrap_getattr_ptr = cfunction(pyjlwrap_getattr, PyPtr, Tuple{PyPtr,PyPtr}) + pyjlwrap_getiter_ptr = cfunction(pyjlwrap_getiter, PyPtr, Tuple{PyPtr}) # detect at runtime whether we are using Stackless Python try @@ -453,8 +454,9 @@ end 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 - t.tp_base = ccall(:jl_value_ptr, Ptr{Void}, (Ptr{PyTypeObject},), &jlWrapType) - ccall((@pysym :Py_IncRef), Void, (Ptr{PyTypeObject},), &jlWrapType) + # 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) init(t) end end @@ -467,8 +469,9 @@ pyjlwrap_type(init::Function, name::AbstractString) = # since, the jl_value_t* may be to a temporary copy. But don't need # 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), - PyPtr, (Ptr{PyTypeObject},), &pyT)) + PyPtr, (Any,), pyT)) pycall_gc[o.o] = value p = convert(Ptr{Ptr{Void}}, o.o) unsafe_store!(p, ccall(:jl_value_ptr, Ptr{Void}, (Any,), value), 3) @@ -479,7 +482,8 @@ function pyjlwrap_new(x::Any) pyjlwrap_new(jlWrapType, x) end -is_pyjlwrap(o::PyObject) = jlWrapType.tp_new != C_NULL && ccall((@pysym :PyObject_IsInstance), Cint, (PyPtr,Ptr{PyTypeObject}), o, &jlWrapType) == 1 +# 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 ################################################################ # Fallback conversion: if we don't have a better conversion function, diff --git a/test/runtests.jl b/test/runtests.jl index 6015a30e..46d65cd6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -81,7 +81,9 @@ let d = PyDict(Dict(1 => "hello", 34 => "yes" )) @test eltype(d) == eltype(typeof(d)) == Pair{Int, String} end -let d = Dict(zip(1:1000, 1:1000)), f = (k,v) -> iseven(k) +let d = Dict(zip(1:1000, 1:1000)), f + f(k,v) = iseven(k) # For 0.6 + f(kv) = iseven(kv[1]) # For 0.7 @test filter(f, d) == filter(f, PyDict(d)) == filter!(f, PyDict(d)) == Dict(zip(2:2:1000, 2:2:1000)) end @@ -108,6 +110,9 @@ array2py2arrayeq(x) = PyCall.py2array(Float64,PyCall.array2py(x)) == x @test collect(PyObject([1,"hello",5])) == [1,"hello",5] @test try @eval (@pyimport os.path) catch ex + if VERSION >= v"0.7.0-DEV.1729" + ex = (ex::LoadError).error + end isa(ex, ArgumentError) end @@ -166,7 +171,7 @@ let buf = IOBuffer(false, true), obuf = PyObject(buf) @test String(take!(buf)) == "hello" obuf[:writelines](["first\n", "second\n", "third"]) @test String(take!(buf)) == "first\nsecond\nthird" - obuf[:write](convert(Vector{UInt8}, "möre stuff")) + obuf[:write](b"möre stuff") @test String(take!(buf)) == "möre stuff" @test isopen(buf) == !obuf[:closed] == true obuf[:close]() @@ -178,8 +183,8 @@ let buf = IOBuffer("hello\nagain"), obuf = PyObject(buf) @test obuf[:readlines]() == ["hello\n", "again"] end let buf = IOBuffer("hello\nagain"), obuf = PyObject(buf) - @test Vector{UInt8}(obuf[:read](5)) == convert(Vector{UInt8}, "hello") - @test Vector{UInt8}(obuf[:readall]()) == convert(Vector{UInt8}, "\nagain") + @test Vector{UInt8}(obuf[:read](5)) == b"hello" + @test Vector{UInt8}(obuf[:readall]()) == b"\nagain" end let buf = IOBuffer("hello\nagain"), obuf = PyTextIO(buf) @test obuf[:encoding] == "UTF-8" @@ -196,7 +201,7 @@ let nm = tempname() pf[:write](pyutf8(nm)) pf[:flush]() end - @test readstring(nm) == nm + @test read(nm, String) == nm end # issue #112 @@ -420,9 +425,9 @@ end # @pycall macro expands correctly _pycall = GlobalRef(PyCall,:pycall) -@test macroexpand(:(@pycall foo(bar)::T)) == :($(_pycall)(foo, T, bar)) -@test macroexpand(:(@pycall foo(bar, args...)::T)) == :($(_pycall)(foo, T, bar, args...)) -@test macroexpand(:(@pycall foo(bar; kwargs...)::T)) == :($(_pycall)(foo, T, bar; kwargs...)) +@test macroexpand(@__MODULE__, :(@pycall foo(bar)::T)) == :($(_pycall)(foo, T, bar)) +@test macroexpand(@__MODULE__, :(@pycall foo(bar, args...)::T)) == :($(_pycall)(foo, T, bar, args...)) +@test macroexpand(@__MODULE__, :(@pycall foo(bar; kwargs...)::T)) == :($(_pycall)(foo, T, bar; kwargs...)) # basic @pywith functionality @@ -432,7 +437,7 @@ try @pywith pybuiltin("open")(fname,"w") as f begin f[:write]("test") end - open(readstring,fname)=="test" + open(io->read(io, String), fname)=="test" end finally rm(fname,force=true)