Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document pyconvert_add_rule #125

Closed
jverzani opened this issue Feb 28, 2022 · 5 comments
Closed

Document pyconvert_add_rule #125

jverzani opened this issue Feb 28, 2022 · 5 comments

Comments

@jverzani
Copy link

Well, I wanted this to be an "issue", but really I have a request for wee bit of help. I asked this on discourse (https://discourse.julialang.org/t/pythoncall-equivalent-to-pycalls-pytype-mapping/77086) but found no answers.

I want to see if I can use PythonCall to replace PyCall with SymPy.jl and to do so am looking for someway to automatically convert the underlying sympy objects into julia objects (such as Py, though with a type from SymPy.) I think the right approach is pyconvert_add_rule but can't seem to get it working. As a test case, my current use of PyCall::pytype_mapping to do this is basically: pytype_mapping(sympy.core.basic.Basic, Sym).

@cjdoris
Copy link
Collaborator

cjdoris commented Mar 2, 2022

Ah sorry I do hang out on discourse but don't necessarily see everything.

I have now documented pyconvert_add_rule here: https://cjdoris.github.io/PythonCall.jl/dev/conversion-to-julia/#py2jl-conversion-custom

You'll need to use PythonCall from the main branch (pkg> add PythonCall#main) for now until I make a release, because I changed the function a little before documenting it.

@jverzani
Copy link
Author

jverzani commented Mar 2, 2022

Awesome. Thanks so much!

@jverzani jverzani closed this as completed Mar 2, 2022
@jverzani
Copy link
Author

jverzani commented Mar 2, 2022

Sorry to trouble you again, but you could guide me as to why the following fails to convert to Sym type of the last line:

using PythonCall # [6099a3de] PythonCall v0.6.1 `https://github.com/cjdoris/PythonCall.jl.git#main`
struct Sym{P}
    py::P
end

sympy = pyimport("sympy")
x = sympy.symbols("x")
x.__module__ # Python str: 'sympy.core.symbol'
x.__class__  # ython ManagedProperties: <class 'sympy.core.symbol.Symbol'>

pyconvert_sym(::Type{S}, x::Py) where {S} = PythonCall.pyconvert_return(Sym(x))::S
PythonCall.pyconvert_add_rule("sympy.core.symbol:Symbol", Sym, pyconvert_sym)

x = sympy.symbols("x")

@cjdoris
Copy link
Collaborator

cjdoris commented Mar 2, 2022

Ah, PythonCall does not automatically convert Python objects to Julia ones when you do things like call Python functions. This differs from PyCall. So you must do one of:

  • pyconvert(Any, sympy.symbols("x"))
  • pyconvert(Sym, sympy.symbols("x"))
  • Sym(sympy.symbols("x")) - this of course doesn't require you to define a pyconvert rule first

Also, as the Important paragraph in the documentation for pyconvert_add_rule says, you are not allowed to return anything which references x from your conversion rule. So you must return Sym(Py(x)) or add an inner constructor like Sym(x) = new(Py(x)) to Sym.

@jverzani
Copy link
Author

jverzani commented Mar 2, 2022

Thanks for the clarification. Most appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants