Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/PyCall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export pyinitialize, pyfinalize, pycall, pyimport, pybuiltin, PyObject,
pysym, PyPtr, pyincref, pydecref, pyversion, PyArray, PyArray_Info,
pyerr_check, pyerr_clear, pytype_query, PyAny, @pyimport, PyWrapper,
PyDict, pyisinstance, pywrap, pytypeof, pyeval, pyhassym,
PyVector, pystring, pyraise
PyVector, pystring, pyraise, pytype_mapping

import Base.size, Base.ndims, Base.similar, Base.copy, Base.getindex,
Base.setindex!, Base.stride, Base.convert, Base.pointer,
Expand Down Expand Up @@ -494,7 +494,16 @@ abstract PyWrapper
# still provide w["foo"] low-level access to unconverted members:
getindex(w::PyWrapper, s) = getindex(w.___jl_PyCall_PyObject___, s)

typesymbol(T::DataType) = T.name.name
function typesymbol(T::DataType)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed typesymbol to get the fully qualified typename, or the eval below failed with the addition of custom user types from other modules

sym = Expr(:., :Main, Expr(:quote, T.name.name))
m = T.name.module
ex = sym
while m !== Main
ex = ex.args[1] = Expr(:., :Main, Expr(:quote, module_name(m)))
m = module_parent(m)
end
sym
end
typesymbol(T) = :Any # punt

# we skip wrapping Julia reserved words (which cannot be type members)
Expand Down
20 changes: 19 additions & 1 deletion src/conversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,18 @@ macro return_not_None(ex)
end
end

let
pytype_queries = Array((PyObject,Type),0)
global pytype_mapping, pytype_query
function pytype_mapping(py::PyObject, jl::Type)
for (i,(p,j)) in enumerate(pytype_queries)
if p == py
pytype_queries[i] = (py,jl)
return pytype_queries
end
end
push!(pytype_queries, (py,jl))
end
function pytype_query(o::PyObject, default::Type)
# TODO: Use some kind of hashtable (e.g. based on PyObject_Type(o)).
# (A bit tricky to correctly handle Tuple and other containers.)
Expand All @@ -683,8 +695,14 @@ function pytype_query(o::PyObject, default::Type)
@return_not_None pyptr_query(o)
@return_not_None pynothing_query(o)
@return_not_None pymp_query(o)
for (py,jl) in pytype_queries
if pyisinstance(o, py)
return jl
end
end
return default
end
end

pytype_query(o::PyObject) = pytype_query(o, PyObject)

Expand All @@ -697,7 +715,7 @@ function convert(::Type{PyAny}, o::PyObject)
if T == PyObject && is_pyjlwrap(o)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure if this needed to be handled differently given the above extension to pytype_query, so I left is alone

return unsafe_pyjlwrap_to_objref(o.o)
end
convert(pytype_query(o), o)
convert(T, o)
catch
pyerr_clear() # just in case
o
Expand Down