From 359d6697d47d6d0e5ff384c748bc2f579d5456a9 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Sun, 12 May 2013 18:08:20 -0400 Subject: [PATCH 1/3] allow custom pytype return values example usage (for SymPy): type Sym x::PyCall.PyObject end Sym(s::Sym) = s convert(::Type{Sym}, o::PyCall.PyObject) = Sym(o) PyCall.pytype_query_add(sympy.basic[Basic], Sym) --- src/PyCall.jl | 10 +++++++++- src/conversions.jl | 12 +++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index f164d5a9..3eb32582 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -494,7 +494,15 @@ 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 + while m !== Main + sym.args[1] = Expr(:., sym.args[1], 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..62dfddaa 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -669,6 +669,10 @@ macro return_not_None(ex) end end +let +pytype_queries = Array((PyObject,Type),0) +global pytype_query_add, pytype_query +pytype_query_add(py::PyObject, jl::Type) = push!(pytype_queries, (py,jl)) 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 +687,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 +707,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 From 93fc92eadde61e7f2832bb48aacdccd5821e1a68 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 13 May 2013 00:41:02 -0400 Subject: [PATCH 2/3] in typesymbol, visit the module hierarchy without reversing the order --- src/PyCall.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index 3eb32582..f716101e 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -497,8 +497,9 @@ getindex(w::PyWrapper, s) = getindex(w.___jl_PyCall_PyObject___, s) function typesymbol(T::DataType) sym = Expr(:., :Main, Expr(:quote, T.name.name)) m = T.name.module + ex = sym while m !== Main - sym.args[1] = Expr(:., sym.args[1], Expr(:quote, module_name(m))) + ex = ex.args[1] = Expr(:., :Main, Expr(:quote, module_name(m))) m = module_parent(m) end sym From 4cc450229b41ab68fe8be3a8d9b9811a94f0f274 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 31 May 2013 18:10:43 -0400 Subject: [PATCH 3/3] make pytype_query_add more dictionary like and rename it pytype_mapping --- src/PyCall.jl | 2 +- src/conversions.jl | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index f716101e..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, diff --git a/src/conversions.jl b/src/conversions.jl index 62dfddaa..4dc02905 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -671,8 +671,16 @@ end let pytype_queries = Array((PyObject,Type),0) -global pytype_query_add, pytype_query -pytype_query_add(py::PyObject, jl::Type) = push!(pytype_queries, (py,jl)) +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.)