diff --git a/src/PyCall.jl b/src/PyCall.jl index f164d5a9..bc451cae 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -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, @@ -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) + 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) diff --git a/src/conversions.jl b/src/conversions.jl index 388f67f2..4dc02905 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -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.) @@ -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) @@ -697,7 +715,7 @@ function convert(::Type{PyAny}, o::PyObject) if T == PyObject && is_pyjlwrap(o) return unsafe_pyjlwrap_to_objref(o.o) end - convert(pytype_query(o), o) + convert(T, o) catch pyerr_clear() # just in case o