# Conversion to Julia

## Conversion Rules

The following table specifies the conversion rules used whenever converting a Python object to a Julia object. If the initial Python type matches the "From" column and the desired type `T`

intersects with the "To" column, then that conversion is attempted. Conversions are tried in priority order, then in specificity order.

From Julia, one can convert Python objects to a desired type using `pyconvert(T, x)`

for example.

From Python, the arguments to a Julia function will be converted according to these rules with `T=Any`

.

From | To |
---|---|

Top priority (wrapped values). | |

`juliacall.AnyValue` | `Any` |

Very high priority (arrays). | |

Objects satisfying the buffer or array interface (inc. `bytes` , `bytearray` , `array.array` , `numpy.ndarray` ) | `PyArray` |

High priority (canonical conversions). | |

`None` | `Nothing` |

`bool` | `Bool` |

`numbers.Integral` (inc. `int` ) | `Integer` (prefers `Int` , or `BigInt` on overflow) |

`float` | `Float64` |

`complex` | `Complex{Float64}` |

`range` | `StepRange` |

`str` | `String` |

`tuple` | `Tuple` |

`collections.abc.Mapping` (inc. `dict` ) | `PyDict` |

`collections.abc.Sequence` (inc. `list` ) | `PyList` |

`collections.abc.Set` (inc. `set` , `frozenset` ) | `PySet` |

`io.IOBase` (includes open files) | `PyIO` |

`BaseException` | `PyException` |

`datetime.date` /`datetime.time` /`datetime.datetime` | `Date` /`Time` /`DateTime` |

`datetime.timedelta` | `Microsecond` (or `Millisecond` or `Second` on overflow) |

`numpy.intXX` /`numpy.uintXX` /`numpy.floatXX` | `IntXX` /`UIntXX` /`FloatXX` |

Standard priority (other reasonable conversions). | |

`None` | `Missing` |

`bytes` | `Vector{UInt8}` , `Vector{Int8}` , `String` |

`str` | `String` , `Symbol` , `Char` , `Vector{UInt8}` , `Vector{Int8}` |

`range` | `UnitRange` |

`collections.abc.Mapping` | `Dict` |

`collections.abc.Iterable` | `Vector` , `Set` , `Tuple` , `NamedTuple` , `Pair` |

`datetime.timedelta` | `Dates.CompoundPeriod` |

`numbers.Integral` | `Integer` , `Rational` , `Real` , `Number` |

`numbers.Real` | `AbstractFloat` , `Number` , `Missing` /`Nothing` (if NaN) |

`numbers.Complex` | `Complex` , `Number` |

`ctypes.c_int` and other integers | `Integer` , `Rational` , `Real` , `Number` |

`ctypes.c_float` /`ctypes.c_double` | `Cfloat` /`Cdouble` , `AbstractFloat` , `Real` , `Number` |

`ctypes.c_voidp` | `Ptr{Cvoid}` , `Ptr` |

`ctypes.c_char_p` | `Cstring` , `Ptr{Cchar}` , `Ptr` |

`ctypes.c_wchar_p` | `Cwstring` , `Ptr{Cwchar}` , `Ptr` |

`numpy.intXX` /`numpy.uintXX` /`numpy.floatXX` | `Integer` , `Rational` , `Real` , `Number` |

Objects satisfying the buffer or array interface | `Array` , `AbstractArray` |

Low priority (fallback to `Py` ). | |

Anything | `Py` |

Bottom priority (must be explicitly specified by excluding `Py` ). | |

Objects satisfying the buffer interface | `PyBuffer` |

Anything | `PyRef` |

See here for an explanation of the `Py*`

wrapper types (`PyList`

, `PyIO`

, etc).

## Custom rules

To add a custom conversion rule, you must define a function to do the conversion and call `pyconvert_add_rule`

to register it.

You must not do this while precompiling, so these calls will normally be in the `__init__`

function of your module.

`PythonCall.pyconvert_add_rule`

— Function`pyconvert_add_rule(tname::String, T::Type, func::Function, priority::PyConvertPriority=PYCONVERT_PRIORITY_NORMAL)`

Add a new conversion rule for `pyconvert`

.

**Arguments**

`tname`

is a string of the form`"__module__:__qualname__"`

identifying a Python type`t`

, such as`"builtins:dict"`

. This rule only applies to Python objects of this type.`T`

is a Julia type, such that this rule only applies when the target type intersects with`T`

.`func`

is the function implementing the rule.`priority`

determines whether to prioritise this rule above others.

When `pyconvert(R, x)`

is called, all rules such that `typeintersect(T, R) != Union{}`

and `pyisinstance(x, t)`

are considered. These rules are sorted first by priority, then by the specificity of `t`

(e.g. `bool`

is more specific than `int`

is more specific than `object`

) then by the order they were added. The rules are tried in turn until one succeeds.

**Implemeting func**

`func`

is called as `func(S, x::Py)`

for some `S <: T`

.

It must return one of:

`pyconvert_return(ans)`

where`ans`

is the result of the conversion (and must be an`S`

).`pyconvert_unconverted()`

if the conversion was not possible (e.g. converting a`list`

to`Vector{Int}`

might fail if some of the list items are not integers).

The target type `S`

is never a union or the empty type, i.e. it is always a data type or union-all.

**Priority**

Most rules should have priority `PYCONVERT_PRIORITY_NORMAL`

(the default) which is for any reasonable conversion rule.

Use priority `PYCONVERT_PRIORITY_CANONICAL`

for **canonical** conversion rules. Immutable objects may be canonically converted to their corresponding Julia type, such as `int`

to `Integer`

. Mutable objects **must** be converted to a wrapper type, such that the original Python object can be retrieved. For example a `list`

is canonically converted to `PyList`

and not to a `Vector`

. There should not be more than one canonical conversion rule for a given Python type.

Other priorities are reserved for internal use.