diff --git a/src/PyCall.jl b/src/PyCall.jl index 48c28697..615f1171 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -316,7 +316,11 @@ function trygetproperty(o::PyObject, s::AbstractString, d) return p == C_NULL ? d : PyObject(p) end -propertynames(o::PyObject) = ispynull(o) ? Symbol[] : map(x->Symbol(first(x)), PyIterator{PyObject}(pycall(inspect."getmembers", PyObject, o))) +function propertynames(o::PyObject) + ispynull(o) && return Symbol[] + names = @pycheckn ccall((@pysym :PyObject_Dir), PyObject, (PyPtr,), o) + return convert(Vector{Symbol}, names) +end # avoiding method ambiguity setproperty!(o::PyObject, s::Symbol, v) = _setproperty!(o,s,v) @@ -366,8 +370,7 @@ hasproperty(o::PyObject, s::AbstractString) = pyhasproperty(o, s) ######################################################################### -keys(o::PyObject) = Symbol[m[1] for m in pycall(inspect."getmembers", - PyVector{Tuple{Symbol,PyObject}}, o)] +@deprecate keys(o::PyObject) propertynames(o) ######################################################################### # Create anonymous composite w = pywrap(o) wrapping the object o diff --git a/test/runtests.jl b/test/runtests.jl index dff36dbc..2e826080 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -295,17 +295,22 @@ const PyInt = pyversion < v"3" ? Int : Clonglong class A: class B: C = 1 + @property + def D(self): + raise NotImplementedError """ A = py"A" @test hasproperty(A, "B") @test getproperty(A, "B") == py"A.B" @test :B in propertynames(A) @static if VERSION >= v"0.7-" + @test :D in propertynames(A.B) @test A.B.C == 1 @test_throws KeyError A.X end setproperty!(py"A.B", "C", 2) @test py"A.B.C" == 2 + @test_deprecated keys(A) # buffers let b = PyCall.PyBuffer(pyutf8("test string")) @@ -317,7 +322,7 @@ const PyInt = pyversion < v"3" ? Int : Clonglong let o = PyObject(1+2im) @test PyCall.hasproperty(o, :real) # replace by Base.hasproperty in the future - @test :real in keys(o) + @test :real in propertynames(o) @test o.real == 1 end