Skip to content

Commit 06a074f

Browse files
author
Christopher Doris
committed
reimplement conversion of buffers/arrays to julia arrays
1 parent b4b5fc9 commit 06a074f

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

docs/src/conversion-to-julia.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ The following table specifies the conversion rules in place. If the initial Pyth
1818
| :----------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------- |
1919
| **Top priority (wrapped values).** | |
2020
| `juliacall.AnyValue` | `Any` |
21+
| `juliacall.As` | `Any` |
2122
| **Very high priority (arrays).** | |
22-
| Objects satisfying the buffer or array interface (inc. `bytes`, `bytearray`, `array.array`, `numpy.ndarray`) | `PyArray` |
23+
| Objects satisfying the buffer or array interface (inc. `bytes`, `bytearray`, `array.array`, `numpy.ndarray`) | `PyArray`, `Array`, `AbstractArray` |
2324
| **High priority (canonical conversions).** | |
2425
| `None` | `Nothing` |
2526
| `bool` | `Bool` |

src/convert.jl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,17 @@ function pyconvert_get_rules(type::Type, pytype::Py)
140140
omro_ = filter(t -> pyisin(t, omro), mro)
141141
@assert length(omro) == length(omro_)
142142
@assert all(pyis(x,y) for (x,y) in zip(omro, omro_))
143-
# TODO: special cases (buffer protocol, etc.)
144143

145144
# get the names of the types in the MRO of pytype
146145
mro = String["$(t.__module__)/$(t.__qualname__)" for t in mro]
147146

147+
# add special names
148+
# currently we don't care where they go because they are tested in their own priority (200)
149+
pyhasattr(pytype, "__array_struct__") && push!(mro, "<arraystruct>")
150+
pyhasattr(pytype, "__array_interface__") && push!(mro, "<arrayinterface>")
151+
pyhasattr(pytype, "__array__") && push!(mro, "<array>")
152+
C.PyType_CheckBuffer(getptr(pytype)) && push!(mro, "<buffer>")
153+
148154
# get corresponding rules
149155
rules = PyConvertRule[rule for tname in mro for rule in get!(Vector{PyConvertRule}, PYCONVERT_RULES, tname)]
150156

@@ -276,6 +282,10 @@ function init_pyconvert()
276282
pyconvert_add_rule("juliacall/As", Any, pyconvert_rule_jlas, 300)
277283
pyconvert_add_rule("juliacall/ValueBase", Any, pyconvert_rule_jlvalue, 300)
278284
# priority 200: arrays
285+
pyconvert_add_rule("<arraystruct>", AbstractArray, pyconvert_rule_array, 200)
286+
pyconvert_add_rule("<arrayinterface>", AbstractArray, pyconvert_rule_array, 200)
287+
pyconvert_add_rule("<array>", AbstractArray, pyconvert_rule_array, 200)
288+
pyconvert_add_rule("<buffer>", AbstractArray, pyconvert_rule_array, 200)
279289
# priority 100: canonical
280290
pyconvert_add_rule("builtins/NoneType", Nothing, pyconvert_rule_none, 100)
281291
pyconvert_add_rule("builtins/bool", Bool, pyconvert_rule_bool, 100)

src/pywrap/PyArray.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@ end
6464

6565
pyconvert_rule_array(::Type{A}, x::Py) where {A<:PyArray} = pyarray_make(A, x, copy=false)
6666

67+
function pyconvert_rule_array(::Type{A}, x::Py) where {A<:AbstractArray}
68+
r = pyconvert_rule_array(PyArray, x)
69+
if pyconvert_isunconverted(r)
70+
return pyconvert_unconverted()
71+
else
72+
return pyconvert_tryconvert(A, pyconvert_result(PyArray, r))
73+
end
74+
end
75+
6776
abstract type PyArraySource end
6877

6978
function pyarray_make(::Type{A}, x::Py; array::Bool=true, buffer::Bool=true, copy::Bool=true) where {A<:PyArray}

0 commit comments

Comments
 (0)