JuliaPy / PythonCall.jl

Python and Julia in harmony.
https://juliapy.github.io/PythonCall.jl/stable/
MIT License
722 stars 61 forks source link

Undesirable Conversion of Unicode Keyword Arguments #329

Closed johnzl-777 closed 1 year ago

johnzl-777 commented 1 year ago

Affects: JuliaCall

Describe the bug The Bloqade.jl library has a function rydberg_h that has several keyword arguments using unicode characters.

The following bug was discovered where one of those keyword arguments is a U+03D5 phi but at some point juliacall seems to turn that into a U+03C6 phi, causing Julia to complain that theres no function that matches rydberg_h.

A minimal working example would be the following (assuming Bloqade.jl is already installed in the Julia environment):

from juliacall import Main as jl
from juliacall import Pkg as jlPkg
from math import pi

jl.seval("using Bloqade")

atoms = jl.Bloqade.generate_sites(jl.Bloqade.SquareLattice(), 3, 4, scale=4.5)
hamiltonian = jl.Bloqade.rydberg_h(atoms, Ω=4*2*pi, Δ=10*2*pi, ϕ=0.0)

Which produces the following error:

---------------------------------------------------------------------------
JuliaError                                Traceback (most recent call last)
Cell In[4], line 4
      1 jl.seval("using Bloqade")
      3 atoms = jl.Bloqade.generate_sites(jl.Bloqade.SquareLattice(), 3, 4, scale=4.5)
----> 4 hamiltonian = jl.Bloqade.rydberg_h(atoms, Ω=4*2*pi, Δ=10*2*pi, ϕ=0.0)

File [~/.julia/packages/PythonCall/1f5yE/src/jlwrap/any.jl:208](https://file+.vscode-resource.vscode-cdn.net/Users/jlong/Desktop/vrige-debug/~/.julia/packages/PythonCall/1f5yE/src/jlwrap/any.jl:208), in __call__(self, *args, **kwargs)
    206     return ValueBase.__dir__(self) + self._jl_callmethod($(pyjl_methodnum(pyjlany_dir)))
    207 def __call__(self, *args, **kwargs):
--> 208     return self._jl_callmethod($(pyjl_methodnum(pyjlany_call)), args, kwargs)
    209 def __len__(self):
    210     return self._jl_callmethod($(pyjl_methodnum(pyjlany_op(length))))

JuliaError: MethodError: no method matching rydberg_h(::AtomList{2, Float64}; φ::Float64, Ω::Float64, Δ::Float64)

Closest candidates are:
  rydberg_h(::Any; C, Ω, ϕ, Δ) got unsupported keyword argument "φ"
   @ BloqadeExpr [~/.julia/packages/BloqadeExpr/yw55x/src/interface.jl:85](https://file+.vscode-resource.vscode-cdn.net/Users/jlong/Desktop/vrige-debug/~/.julia/packages/BloqadeExpr/yw55x/src/interface.jl:85)
  rydberg_h(::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any) got unsupported keyword arguments "φ", "Ω", "Δ"
   @ BloqadeExpr [~/.julia/packages/BloqadeExpr/yw55x/src/interface.jl:89](https://file+.vscode-resource.vscode-cdn.net/Users/jlong/Desktop/vrige-debug/~/.julia/packages/BloqadeExpr/yw55x/src/interface.jl:89)

Stacktrace:
 [1] kwerr(::NamedTuple{(:φ, :Ω, :Δ), Tuple{Float64, Float64, Float64}}, ::Function, ::AtomList{2, Float64})
   @ Base [./error.jl:165](https://file+.vscode-resource.vscode-cdn.net/Users/jlong/Desktop/vrige-debug/error.jl:165)
 [2] pyjlany_call(self::typeof(rydberg_h), args_::Py, kwargs_::Py)
   @ PythonCall [~/.julia/packages/PythonCall/1f5yE/src/jlwrap/any.jl:34](https://file+.vscode-resource.vscode-cdn.net/Users/jlong/Desktop/vrige-debug/~/.julia/packages/PythonCall/1f5yE/src/jlwrap/any.jl:34)
 [3] _pyjl_callmethod(f::Any, self_::Ptr{PythonCall.C.PyObject}, args_::Ptr{PythonCall.C.PyObject}, nargs::Int64)
   @ PythonCall [~/.julia/packages/PythonCall/1f5yE/src/jlwrap/base.jl:69](https://file+.vscode-resource.vscode-cdn.net/Users/jlong/Desktop/vrige-debug/~/.julia/packages/PythonCall/1f5yE/src/jlwrap/base.jl:69)
 [4] _pyjl_callmethod(o::Ptr{PythonCall.C.PyObject}, args::Ptr{PythonCall.C.PyObject})
   @ PythonCall.C [~/.julia/packages/PythonCall/1f5yE/src/cpython/jlwrap.jl:47](https://file+.vscode-resource.vscode-cdn.net/Users/jlong/Desktop/vrige-debug/~/.julia/packages/PythonCall/1f5yE/src/cpython/jlwrap.jl:47)

Your system

Additional context I'm testing this in a Jupyter Notebook in VSCode with conda but the bug was originally discovered while being used in Pycharm with conda.

johnzl-777 commented 1 year ago

I suspect this probably has something to do with this python limitation: https://pyjulia.readthedocs.io/en/stable/limitations.html#mismatch-in-valid-set-of-identifiers (not juliacall docs but I could definitely understand the same limitation across the board) in which case, is there a possible workaround without having to rewrite the function with ASCII-only (or at least, Python unicode friendly) keyword arguments?

cjdoris commented 1 year ago

Indeed it's the same issue as with PyJulia - python normalises unicode identifiers. I think strings aren't normalised like this so you can do

jl.Bloqade.rydberg_h(atoms, **{'Ω': 4*2*pi, 'Δ': 10*2*pi, 'ϕ': 0.0})
johnzl-777 commented 1 year ago

This works perfectly, thanks!