Skip to content

Add an option for more aggressive conversion #355

Open
@LilithHafner

Description

@LilithHafner

Is your feature request related to a problem? Please describe.
I have users that are passing in python objects of unknown type and Julia code that expects native Julia objects. When trying to migrate from PyCall to PythonCall, I find the conversions defined here do not convert user provided objects into the most native equivalent Julia type.

Describe the solution you'd like
I would like an option to convert an arbitrary Python object to a Julia object with eager semantics. For example,

julia> eager_pyconvert(Any, pyeval("[1.0, 2.0, 3.0]", Main))
3-element Vector{Float64}:
 1.0
 2.0
 3.0

julia> pyconvert(Any, pyeval("[1.0, 2.0, 3.0]", Main)) # Current (if type is unknown)
3-element PyList{Any}:
 1.0
 2.0
 3.0

julia> pyconvert(Array, pyeval("[1.0, 2.0, 3.0]", Main)) # Current (if type is known)
3-element Vector{Float64}:
 1.0
 2.0
 3.0

julia> py"[1.0, 2.0, 3.0]" # PyCall
3-element Vector{Float64}:
 1.0
 2.0
 3.0

By "eager semantics" I mean it will convert to as specific a target type as possible. Or, equivalently, opt out of types defined by PythonCall.jl.

Describe alternatives you've considered
Coming up with a "magic type" that can be passed to the existing pyconvert function

types(m) = (x for x in (getglobal(m, n) for n in names(m)) if x isa Type && x !== Any)
BaseTypes = BaseTypes = Union{types(Core)..., types(Base)...}
pyconvert(BaseTypes, pyeval("[1.0, 2.0, 3.0]", Main))

Fails because PyList <: BaseTypes.

Restricting to concrete types segfaults julia

types(m) = (x for x in (getglobal(m, n) for n in names(m)) if x isa Type && !isabstracttype(x))
BaseTypes = Union{types(Core)..., types(Base)...}
pyconvert(BaseTypes, pyeval("[1.0, 2.0, 3.0]", Main))
# [68187] signal (11.2): Segmentation fault: 11
# in expression starting at REPL[41]:1
# ...

Home rolling conversion rules for specific types feels like reinventing the wheel and hard to maintain.

Additional context
Basically, I'd like to opt into the conversion behavior of PyCall.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions