Skip to content

Commit 706f81f

Browse files
author
Christopher Doris
committed
adds pyhasitem and 3-arg pygetitem and corresponding Base methods
1 parent f36d104 commit 706f81f

File tree

4 files changed

+85
-5
lines changed

4 files changed

+85
-5
lines changed

docs/src/pythoncall-reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pyexec
5151
pygetattr
5252
pygetitem
5353
pyhasattr
54+
pyhasitem
5455
pyhash
5556
pyhelp
5657
pyimport

docs/src/releasenotes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Release Notes
22

33
## Unreleased
4+
* Adds `pyhasitem` and 3-arg `pygetitem`.
5+
* Extends `Base.get`, `Base.get!`, `Base.haskey` and 2-arg `Base.hash` for `Py`.
6+
* `PyArray` can now have any element type when the underlying array is of Python objects.
47
* Bug fixes.
58

69
## v0.8.0 (2022-03-17)

src/Py.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,25 @@ Base.setindex!(x::Py, v, i...) = (pysetitem(x, i, v); x)
353353

354354
Base.delete!(x::Py, i) = (pydelitem(x, i); x)
355355

356+
Base.haskey(x::Py, i) = pyhasitem(x, i)
357+
358+
Base.get(x::Py, i, d) = pygetitem(x, i, d)
359+
360+
function Base.get(f::Base.Callable, x::Py, i)
361+
v = pygetitem(x, i, nothing)
362+
v === nothing ? f() : v
363+
end
364+
365+
Base.get!(x::Py, i, d) = get(x, i) do
366+
pysetitem(x, i, d)
367+
pygetitem(x, i)
368+
end
369+
370+
Base.get!(f::Base.Callable, x::Py, i) = get(x, i) do
371+
pysetitem(x, i, f())
372+
pygetitem(x, i)
373+
end
374+
356375
Base.eltype(::Type{Py}) = Py
357376

358377
Base.IteratorSize(::Type{Py}) = Base.SizeUnknown()

src/abstract/object.jl

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,24 @@ export pyascii
3030
pyhasattr(x, k)
3131
3232
Equivalent to `hasattr(x, k)` in Python.
33+
34+
Tests if `getattr(x, k)` raises an `AttributeError`.
3335
"""
34-
pyhasattr(x, k) = errcheck(@autopy x k C.PyObject_HasAttr(getptr(x_), getptr(k_))) == 1
36+
# pyhasattr(x, k) = errcheck(@autopy x k C.PyObject_HasAttr(getptr(x_), getptr(k_))) == 1
37+
function pyhasattr(x, k)
38+
ptr = @autopy x k C.PyObject_GetAttr(getptr(x_), getptr(k_))
39+
if iserrset(ptr)
40+
if errmatches(pybuiltins.AttributeError)
41+
errclear()
42+
return false
43+
else
44+
pythrow()
45+
end
46+
else
47+
decref(ptr)
48+
return true
49+
end
50+
end
3551
export pyhasattr
3652

3753
"""
@@ -45,8 +61,12 @@ pygetattr(x, k) = pynew(errcheck(@autopy x k C.PyObject_GetAttr(getptr(x_), getp
4561
function pygetattr(x, k, d)
4662
ptr = @autopy x k C.PyObject_GetAttr(getptr(x_), getptr(k_))
4763
if iserrset(ptr)
48-
errclear()
49-
return d
64+
if errmatches(pybuiltins.AttributeError)
65+
errclear()
66+
return d
67+
else
68+
pythrow()
69+
end
5070
else
5171
return pynew(ptr)
5272
end
@@ -118,11 +138,48 @@ pylen(x) = errcheck(@autopy x C.PyObject_Length(getptr(x_)))
118138
export pylen
119139

120140
"""
121-
pygetitem(x, k)
141+
pyhasitem(x, k)
142+
143+
Test if `pygetitem(x, k)` raises a `KeyError` or `AttributeError`.
144+
"""
145+
function pyhasitem(x, k)
146+
ptr = @autopy x k C.PyObject_GetItem(getptr(x_), getptr(k_))
147+
if iserrset(ptr)
148+
if errmatches(pybuiltins.KeyError) || errmatches(pybuiltins.IndexError)
149+
errclear()
150+
return false
151+
else
152+
pythrow()
153+
end
154+
else
155+
decref(ptr)
156+
return true
157+
end
158+
end
159+
export pyhasitem
160+
161+
"""
162+
pygetitem(x, k, [d])
163+
164+
Equivalent `x[k]` in Python.
122165
123-
Equivalent to `getitem(x, k)` or `x[k]` in Python.
166+
If `d` is specified, it is returned if the item does not exist (i.e. if `x[k]` raises a
167+
`KeyError` or `IndexError`).
124168
"""
125169
pygetitem(x, k) = pynew(errcheck(@autopy x k C.PyObject_GetItem(getptr(x_), getptr(k_))))
170+
function pygetitem(x, k, d)
171+
ptr = @autopy x k C.PyObject_GetItem(getptr(x_), getptr(k_))
172+
if iserrset(ptr)
173+
if errmatches(pybuiltins.KeyError) || errmatches(pybuiltins.IndexError)
174+
errclear()
175+
return d
176+
else
177+
pythrow()
178+
end
179+
else
180+
return pynew(ptr)
181+
end
182+
end
126183
export pygetitem
127184

128185
"""

0 commit comments

Comments
 (0)