Skip to content

Commit ddb54a8

Browse files
aplavinstevengj
andauthored
fix getproperty exceptions (#997)
* raise proper exception in getproperty * Update src/PyCall.jl * Update src/PyCall.jl * whoops * also fix setproperty * Update src/PyCall.jl * Update src/PyCall.jl * Update src/PyCall.jl * Update src/PyCall.jl Co-authored-by: Steven G. Johnson <[email protected]>
1 parent d5d3d07 commit ddb54a8

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

src/PyCall.jl

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,13 @@ end
298298
function _getproperty(o::PyObject, s::Union{AbstractString,Symbol})
299299
ispynull(o) && throw(ArgumentError("ref of NULL PyObject"))
300300
p = ccall((@pysym :PyObject_GetAttrString), PyPtr, (PyPtr, Cstring), o, s)
301-
p == C_NULL && pyerr_clear()
301+
if p == C_NULL && pyerr_occurred()
302+
e = pyerror("PyObject_GetAttrString")
303+
if PyPtr(e.T) != @pyglobalobjptr(:PyExc_AttributeError)
304+
throw(e)
305+
end
306+
pyerr_clear()
307+
end
302308
return p
303309
end
304310

@@ -327,15 +333,17 @@ setproperty!(o::PyObject, s::Symbol, v) = _setproperty!(o,s,v)
327333
setproperty!(o::PyObject, s::AbstractString, v) = _setproperty!(o,s,v)
328334

329335
function _setproperty!(o::PyObject, s::Union{Symbol,AbstractString}, v)
330-
if ispynull(o)
331-
throw(ArgumentError("assign of NULL PyObject"))
332-
end
333-
if -1 == ccall((@pysym :PyObject_SetAttrString), Cint,
334-
(PyPtr, Cstring, PyPtr), o, s, PyObject(v))
336+
ispynull(o) && throw(ArgumentError("assign of NULL PyObject"))
337+
p = ccall((@pysym :PyObject_SetAttrString), Cint, (PyPtr, Cstring, PyPtr), o, s, PyObject(v))
338+
if p == -1 && pyerr_occurred()
339+
e = pyerror("PyObject_SetAttrString")
340+
if PyPtr(e.T) != @pyglobalobjptr(:PyExc_AttributeError)
341+
throw(e)
342+
end
335343
pyerr_clear()
336344
throw(KeyError(s))
337345
end
338-
o
346+
return o
339347
end
340348

341349
function getindex(o::PyObject, s::T) where T<:Union{Symbol, AbstractString}

test/runtests.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,3 +829,26 @@ end
829829
@test py"bar2" == 2
830830
end
831831
end
832+
833+
@testset "proper exception raised" begin
834+
py"""
835+
class A:
836+
def __getattr__(self, name):
837+
if name == "a":
838+
raise ValueError(name)
839+
else:
840+
raise AttributeError()
841+
842+
def __setattr__(self, name, value):
843+
if value == 0:
844+
raise ValueError(value)
845+
else:
846+
raise AttributeError()
847+
"""
848+
a = py"A"()
849+
@test_throws PyCall.PyError a.a
850+
@test_throws KeyError a.b
851+
852+
@test_throws PyCall.PyError a.a = 0
853+
@test_throws KeyError a.a = 1
854+
end

0 commit comments

Comments
 (0)