diff --git a/.github/workflows/TagBot.yml b/.github/workflows/TagBot.yml index d77d3a0c..778c06fe 100644 --- a/.github/workflows/TagBot.yml +++ b/.github/workflows/TagBot.yml @@ -1,9 +1,12 @@ name: TagBot on: - schedule: - - cron: 0 * * * * + issue_comment: + types: + - created + workflow_dispatch: jobs: TagBot: + if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot' runs-on: ubuntu-latest steps: - uses: JuliaRegistries/TagBot@v1 diff --git a/.github/workflows/aot.yml b/.github/workflows/aot.yml index ea23d765..e227a659 100644 --- a/.github/workflows/aot.yml +++ b/.github/workflows/aot.yml @@ -16,8 +16,11 @@ jobs: os: - ubuntu-latest architecture: [x64] - python-version: ['3.8'] - julia-version: ['1.5', 'nightly'] + python-version: ['3.x'] + julia-version: + - '1' + - '1.6' + # - 'nightly' # TODO: reenable fail-fast: false env: PYTHON: python${{ matrix.python-version }} @@ -34,6 +37,9 @@ jobs: architecture: ${{ matrix.architecture }} - run: python --version - run: python -m pip install --user numpy + - name: Install libpython2.7 for `find_libpython` test + run: sudo apt-get install python2.7-dev + if: ${{ matrix.python-version != '2.7' && matrix.os == 'ubuntu-latest' }} - name: Setup julia uses: julia-actions/setup-julia@v1 with: diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index caa1149a..bfebbc80 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -18,11 +18,11 @@ jobs: - macos-latest - windows-latest architecture: [x64] - julia-version: ['1.5'] + julia-version: ['1'] include: - os: windows-latest architecture: x86 - julia-version: '1.5' + julia-version: '1' fail-fast: false env: PYTHON: "" @@ -32,6 +32,9 @@ jobs: ${{ matrix.os }} ${{ matrix.architecture }} steps: - uses: actions/checkout@v1 + - name: Install libpython2.7 for `find_libpython` test + run: sudo apt-get install python2.7-dev + if: ${{ matrix.python-version != '2.7' && matrix.os == 'ubuntu-latest' }} - name: Setup julia uses: julia-actions/setup-julia@v1 with: diff --git a/.github/workflows/system.yml b/.github/workflows/system.yml index e52ef8de..fefb6b4a 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yml @@ -18,25 +18,39 @@ jobs: - macos-latest - windows-latest architecture: [x64] - python-version: ['2.7', '3.8'] - julia-version: ['1.0', '1.5', 'nightly'] + python-version: ['3.x'] + julia-version: + - '1' + - 'nightly' include: + # 32 bit Windows: - os: windows-latest architecture: x86 - python-version: '3.8' - julia-version: '1.5' + python-version: '3.x' + julia-version: '1' + # Sweep python-version and julia-version only on Ubuntu: + - os: ubuntu-latest + architecture: x64 + python-version: '3.9' + julia-version: '1' - os: ubuntu-latest architecture: x64 - python-version: '3.7' + python-version: '3.x' julia-version: '1.5' - os: ubuntu-latest architecture: x64 - python-version: '3.8' + python-version: '3.x' julia-version: '1.4' + # Test Python 2.7 only with a few combinations (TODO: drop 2.7). + # Note that it does not work in macOS: - os: ubuntu-latest architecture: x64 - python-version: '3.8' - julia-version: '1.3' + python-version: '2.7' + julia-version: '1' + - os: windows-2019 + architecture: x64 + python-version: '2.7' + julia-version: '1' fail-fast: false name: Test Julia ${{ matrix.julia-version }} @@ -56,6 +70,9 @@ jobs: if: ${{ matrix.python-version != '2.7' }} - run: virtualenv --version if: ${{ matrix.python-version != '2.7' }} + - name: Install libpython2.7 for `find_libpython` test + run: sudo apt-get install python2.7-dev + if: ${{ matrix.python-version != '2.7' && matrix.os == 'ubuntu-latest' }} - name: Setup julia uses: julia-actions/setup-julia@v1 with: @@ -67,6 +84,12 @@ jobs: PYTHON: python - run: julia test/check_deps_version.jl ${{ matrix.python-version }} - uses: julia-actions/julia-runtest@v1 + env: + # Windows temp directories break the CI: + # https://github.com/actions/runner-images/issues/712 + # so, we use + # https://docs.github.com/en/actions/learn-github-actions/contexts#runner-context + _TMP_DIR: ${{ runner.temp }} - uses: julia-actions/julia-processcoverage@v1 - uses: codecov/codecov-action@v1 with: diff --git a/Project.toml b/Project.toml index 013e8c97..dd7269ee 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "PyCall" uuid = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" authors = ["Steven G. Johnson ", "Yichao Yu ", "Takafumi Arakaki ", "Simon Kornblith ", "Páll Haraldsson ", "Jon Malmaud ", "Jake Bolewski ", "Keno Fischer ", "Joel Mason ", "Jameson Nash ", "The JuliaPy development team"] -version = "1.92.2" +version = "1.96.4" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" @@ -13,13 +13,19 @@ Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b" VersionParsing = "81def892-9a0e-5fdd-b105-ffc91e053289" [compat] -Conda = "1.0" +Conda = "1.9" MacroTools = "0.4, 0.5" VersionParsing = "1.0" -julia = "0.7, 1.0" + +julia = "1.4" +Dates = "<0.0.1, 1" +Libdl = "<0.0.1, 1" +LinearAlgebra = "<0.0.1, 1" +Serialization = "<0.0.1, 1" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [targets] -test = ["Test"] +test = ["Test", "REPL"] diff --git a/README.md b/README.md index 53ba1866..9300647c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,12 @@ install the files. Julia 0.7 or later is required. The latest development version of PyCall is available from . If you want to switch to -this after installing the package, run `Pkg.checkout("PyCall"); Pkg.build("PyCall")`. +this after installing the package, run: + +```julia +Pkg.add(PackageSpec(name="PyCall", rev="master")) +Pkg.build("PyCall") +``` By default on Mac and Windows systems, `Pkg.add("PyCall")` or `Pkg.build("PyCall")` will use the @@ -48,9 +53,9 @@ to the path of the `python` (or `python3` etc.) executable and then re-running ` In Julia: ENV["PYTHON"] = "... path of the python executable ..." - # ENV["PYTHON"] = raw"C:\Python37-x64\python.exe" # example for Windows, "raw" to not have to escape: "C:\\Python37-x64\\python.exe" + # ENV["PYTHON"] = raw"C:\Python310-x64\python.exe" # example for Windows, "raw" to not have to escape: "C:\\Python310-x64\\python.exe" - # ENV["PYTHON"] = "/usr/bin/python3.7" # example for *nix + # ENV["PYTHON"] = "/usr/bin/python3.10" # example for *nix Pkg.build("PyCall") Note also that you will need to re-run `Pkg.build("PyCall")` if your @@ -160,6 +165,8 @@ def sinpi(x): py"sinpi"(1) ``` +You can also execute a whole script `"foo.py"` via `@pyinclude("foo.py")` as if you had pasted it into a `py"""..."""` string. + When creating a Julia module, it is a useful pattern to define Python functions or classes in Julia's `__init__` and then use it in Julia function with `py"..."`. @@ -192,7 +199,7 @@ cannot be accessed outside `MyModule`. Here are solutions to some common problems: -* By default, PyCall [doesn't include the current directory in the Python search path](https://github.com/JuliaPy/PyCall.jl/issues/48). If you want to do that (in order to load a Python module from the current directory), just run `pushfirst!(PyVector(pyimport("sys")."path"), "")`. +* By default, PyCall [doesn't include the current directory in the Python search path](https://github.com/JuliaPy/PyCall.jl/issues/48). If you want to do that (in order to load a Python module from the current directory), just run `pushfirst!(pyimport("sys")."path", "")`. ## Python object interfaces @@ -298,7 +305,7 @@ use `PyDict` as the return type of a `pycall` returning a dictionary, or call `PyDict(o::PyObject)` on a dictionary object `o`. By default, a `PyDict` is an `Any => Any` dictionary (or actually `PyAny => PyAny`) that performs runtime type inference, but if your Python -dictionary has known, fixed types you can insteady use `PyDict{K,V}` given +dictionary has known, fixed types you can instead use `PyDict{K,V}` given the key and value types `K` and `V` respectively. Currently, passing Julia dictionaries to Python makes a copy of the Julia @@ -359,7 +366,8 @@ and also by providing more type information to the Julia compiler. Python's [`eval`](https://docs.python.org/3/library/functions.html#eval) function, and returns the result converted to `PyAny`. Alternatively, `py"..."o` returns the raw `PyObject` (which can then be manually converted if desired). You can interpolate - Julia variables and other expressions into the Python code with `$`, + Julia variables and other expressions into the Python code (except for into + Python strings contained in Python code), with `$`, which interpolates the *value* (converted to `PyObject`) of the given expression---data is not passed as a string, so this is different from ordinary Julia string interpolation. e.g. `py"sum($([1,2,3]))"` calls the @@ -384,10 +392,15 @@ and also by providing more type information to the Julia compiler. `__init__`. Side-effect in Python occurred at top-level Julia scope cannot be used at run-time for precompiled modules. + You can also execute a Python script file `"foo.py"` by running `@pyinclude("foo.py")`, and it will be as if you had pasted the + script into a `py"..."` string. (`@pyinclude` does not support + interpolating Julia variables with `$var`, however — the script + must be pure Python.) + * `pybuiltin(s)`: Look up `s` (a string or symbol) among the global Python builtins. If `s` is a string it returns a `PyObject`, while if `s` is a symbol it returns the builtin converted to `PyAny`. (You can also use `py"s"` - to look up builtins or other Python globas.) + to look up builtins or other Python globals.) Occasionally, you may need to pass a keyword argument to Python that is a [reserved word](https://en.wikipedia.org/wiki/Reserved_word) in Julia. diff --git a/deps/build.jl b/deps/build.jl index f27c7441..52b970c8 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -43,7 +43,7 @@ mkpath(dirname(prefsfile)) try # make sure deps.jl file is removed on error python = try let py = get(ENV, "PYTHON", isfile(prefsfile) ? readchomp(prefsfile) : - (Sys.isunix() && !Sys.isapple()) || Sys.ARCH ∉ (:i686, :x86_64) ? + (Sys.isunix() && !Sys.isapple()) ? whichfirst("python3", "python") : "Conda"), vers = isempty(py) || py == "Conda" ? v"0.0" : vparse(pyconfigvar(py,"VERSION","0.0")) if vers < v"2.7" @@ -64,24 +64,19 @@ try # make sure deps.jl file is removed on error py end catch e1 - if Sys.ARCH in (:i686, :x86_64) - if isa(e1, UseCondaPython) - @info string("Using the Python distribution in the Conda package by default.\n", - "To use a different Python version, set ENV[\"PYTHON\"]=\"pythoncommand\" and re-run Pkg.build(\"PyCall\").") - else - @info string( "No system-wide Python was found; got the following error:\n", - "$e1\nusing the Python distribution in the Conda package") - end - abspath(Conda.PYTHONDIR, "python" * (Sys.iswindows() ? ".exe" : "")) + if isa(e1, UseCondaPython) + @info string("Using the Python distribution in the Conda package by default.\n", + "To use a different Python version, set ENV[\"PYTHON\"]=\"pythoncommand\" and re-run Pkg.build(\"PyCall\").") else - error("No system-wide Python was found; got the following error:\n", - "$e1") + @info string("No system-wide Python was found; got the following error:\n", + "$e1\nusing the Python distribution in the Conda package") end + abspath(Conda.PYTHONDIR, "python" * (Sys.iswindows() ? ".exe" : "")) end use_conda = dirname(python) == abspath(Conda.PYTHONDIR) if use_conda - Conda.add("numpy") + Conda.add("numpy"; satisfied_skip_solve=true) end (libpython, libpy_name) = find_libpython(python) diff --git a/deps/buildutils.jl b/deps/buildutils.jl index 5eb27b94..f090875e 100644 --- a/deps/buildutils.jl +++ b/deps/buildutils.jl @@ -5,7 +5,15 @@ import Conda, Libdl pyvar(python::AbstractString, mod::AbstractString, var::AbstractString) = chomp(read(pythonenv(`$python -c "import $mod; print($mod.$(var))"`), String)) -pyconfigvar(python::AbstractString, var::AbstractString) = pyvar(python, "distutils.sysconfig", "get_config_var('$(var)')") +function pyconfigvar(python::AbstractString, var::AbstractString) + try + pyvar(python, "sysconfig", "get_config_var('$(var)')") + catch e + emsg = sprint(showerror, e) + @warn "Encountered error on using `sysconfig`: $emsg. Falling back to `distutils.sysconfig`." + pyvar(python, "distutils.sysconfig", "get_config_var('$(var)')") + end +end pyconfigvar(python, var, default) = let v = pyconfigvar(python, var) v == "None" ? default : v end diff --git a/deps/depsutils.jl b/deps/depsutils.jl index 35ed1e12..73ae2946 100644 --- a/deps/depsutils.jl +++ b/deps/depsutils.jl @@ -64,8 +64,10 @@ function _preserveas!(dest::Vector{UInt8}, ::Type{Cstring}, x::AbstractString) end function _preserveas!(dest::Vector{UInt8}, ::Type{Cwstring}, x::AbstractString) - s = reinterpret(UInt8, Base.cconvert(Cwstring, x)) - copyto!(resize!(dest, length(s)), s) + s = reinterpret(UInt8, transcode(Cwchar_t, String(x))) + len = length(s) + copyto!(resize!(dest, len + sizeof(Cwchar_t)), s) + dest[len + 1:len + sizeof(Cwchar_t)] .= 0 return pointer(dest) end diff --git a/deps/find_libpython.py b/deps/find_libpython.py index 422a0200..222d9715 100755 --- a/deps/find_libpython.py +++ b/deps/find_libpython.py @@ -264,7 +264,7 @@ def normalize_path(path, suffix=SHLIB_SUFFIX, is_apple=is_apple): Parameters ---------- - path : str ot None + path : str or None A candidate path to a shared library. """ if not path: diff --git a/src/PyCall.jl b/src/PyCall.jl index 51de339b..c7e4e0b1 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -14,7 +14,7 @@ export pycall, pycall!, pyimport, pyimport_e, pybuiltin, PyObject, PyReverseDims pyraise, pytype_mapping, pygui, pygui_start, pygui_stop, pygui_stop_all, @pylab, set!, PyTextIO, @pysym, PyNULL, ispynull, @pydef, pyimport_conda, @py_str, @pywith, @pycall, pybytes, pyfunction, pyfunctionret, - pywrapfn, pysetarg!, pysetargs! + pywrapfn, pysetarg!, pysetargs!, @pyinclude import Base: size, ndims, similar, copy, getindex, setindex!, stride, convert, pointer, summary, convert, show, haskey, keys, values, @@ -309,7 +309,13 @@ end function _getproperty(o::PyObject, s::Union{AbstractString,Symbol}) ispynull(o) && throw(ArgumentError("ref of NULL PyObject")) p = ccall((@pysym :PyObject_GetAttrString), PyPtr, (PyPtr, Cstring), o, s) - p == C_NULL && pyerr_clear() + if p == C_NULL && pyerr_occurred() + e = PyError("PyObject_GetAttrString") + if PyPtr(e.T) != @pyglobalobjptr(:PyExc_AttributeError) + throw(e) + end + pyerr_clear() + end return p end @@ -338,15 +344,17 @@ setproperty!(o::PyObject, s::Symbol, v) = _setproperty!(o,s,v) setproperty!(o::PyObject, s::AbstractString, v) = _setproperty!(o,s,v) function _setproperty!(o::PyObject, s::Union{Symbol,AbstractString}, v) - if ispynull(o) - throw(ArgumentError("assign of NULL PyObject")) - end - if -1 == ccall((@pysym :PyObject_SetAttrString), Cint, - (PyPtr, Cstring, PyPtr), o, s, PyObject(v)) + ispynull(o) && throw(ArgumentError("assign of NULL PyObject")) + p = ccall((@pysym :PyObject_SetAttrString), Cint, (PyPtr, Cstring, PyPtr), o, s, PyObject(v)) + if p == -1 && pyerr_occurred() + e = PyError("PyObject_SetAttrString") + if PyPtr(e.T) != @pyglobalobjptr(:PyExc_AttributeError) + throw(e) + end pyerr_clear() throw(KeyError(s)) end - o + return o end function getindex(o::PyObject, s::T) where T<:Union{Symbol, AbstractString} @@ -510,7 +518,7 @@ function pyimport(name::AbstractString) o = _pyimport(name) if ispynull(o) if pyerr_occurred() - e = pyerror("PyImport_ImportModule") + e = PyError("PyImport_ImportModule") if pyisinstance(e.val, @pyglobalobjptr(:PyExc_ImportError)) # Expand message to help with common user confusions. msg = """ @@ -523,7 +531,7 @@ that you did not install $name in the Python version being used by PyCall. PyCall is currently configured to use the Julia-specific Python distribution installed by the Conda.jl package. To install the $name module, you can use `pyimport_conda("$(escape_string(name))", PKG)`, where PKG is the Anaconda -package the contains the module $name, or alternatively you can use the +package that contains the module $name, or alternatively you can use the Conda package directly (via `using Conda` followed by `Conda.add` etcetera). Alternatively, if you want to use a different Python distribution on your @@ -556,7 +564,7 @@ or alternatively you can use the Conda package directly (via `using Conda` followed by `Conda.add` etcetera). """ end - e = pyerror(string(e.msg, "\n\n", msg, "\n"), e) + e = PyError(string(e.msg, "\n\n", msg, "\n"), e) end throw(e) else @@ -982,17 +990,19 @@ include("serialize.jl") include("pyinit.jl") -######################################################################### -# Precompilation: just an optimization to speed up initialization. -# Here, we precompile functions that are passed to cfunction by __init__, -# for the reasons described in JuliaLang/julia#12256. +const _deepcopy = PyNULL() -precompile(pyjlwrap_call, (PyPtr,PyPtr,PyPtr)) -precompile(pyjlwrap_dealloc, (PyPtr,)) -precompile(pyjlwrap_repr, (PyPtr,)) -precompile(pyjlwrap_hash, (PyPtr,)) -precompile(pyjlwrap_hash32, (PyPtr,)) +function Base.deepcopy_internal(obj::PyObject, stackdict::Base.IdDict) + haskey(stackdict, obj) && return stackdict[obj] + ispynull(_deepcopy) && copy!(_deepcopy, pyimport("copy")."deepcopy") + ret = pycall(_deepcopy, PyObject, obj) + stackdict[obj] = ret + ret +end -# TODO: precompilation of the io.jl functions +######################################################################### + +include("precompile.jl") +######################################################################### end # module PyCall diff --git a/src/exception.jl b/src/exception.jl index 7df89269..a874694c 100644 --- a/src/exception.jl +++ b/src/exception.jl @@ -49,6 +49,19 @@ function show(io::IO, e::PyError) end end +# like pyerror(msg) but type-stable: always returns PyError +function PyError(msg::AbstractString) + ptype, pvalue, ptraceback = Ref{PyPtr}(), Ref{PyPtr}(), Ref{PyPtr}() + # equivalent of passing C pointers &exc[1], &exc[2], &exc[3]: + ccall((@pysym :PyErr_Fetch), Cvoid, (Ref{PyPtr},Ref{PyPtr},Ref{PyPtr}), ptype, pvalue, ptraceback) + ccall((@pysym :PyErr_NormalizeException), Cvoid, (Ref{PyPtr},Ref{PyPtr},Ref{PyPtr}), ptype, pvalue, ptraceback) + return PyError(msg, PyObject(ptype[]), PyObject(pvalue[]), PyObject(ptraceback[])) +end + +# replace the message from another error +PyError(msg::AbstractString, e::PyError) = + PyError(msg, e.T, e.val, e.traceback) + ######################################################################### # Conversion of Python exceptions into Julia exceptions @@ -106,17 +119,12 @@ macro pycheckz(ex) :(@pycheckv $(esc(ex)) -1) end -function pyerror(msg::AbstractString) - ptype, pvalue, ptraceback = Ref{PyPtr}(), Ref{PyPtr}(), Ref{PyPtr}() - # equivalent of passing C pointers &exc[1], &exc[2], &exc[3]: - ccall((@pysym :PyErr_Fetch), Cvoid, (Ref{PyPtr},Ref{PyPtr},Ref{PyPtr}), ptype, pvalue, ptraceback) - ccall((@pysym :PyErr_NormalizeException), Cvoid, (Ref{PyPtr},Ref{PyPtr},Ref{PyPtr}), ptype, pvalue, ptraceback) - pyerror(msg, PyObject(ptype[]), PyObject(pvalue[]), PyObject(ptraceback[])) -end +# like PyError(...) but type-unstable: may unwrap a PyJlError +# if one was thrown by a nested pyjlwrap function. -function pyerror(msg::AbstractString, e::PyError) +pyerror(msg::AbstractString) = pyerror(msg, PyError(msg)) +pyerror(msg::AbstractString, e::PyError) = pyerror(msg, e.T, e.val, e.traceback) -end function pyerror(msg::AbstractString, ptype::PyObject, pvalue::PyObject, ptraceback::PyObject) pargs = _getproperty(pvalue, "args") @@ -140,7 +148,7 @@ end ######################################################################### # Mapping of Julia Exception types to Python exceptions -const pyexc = Dict{DataType, PyPtr}() +const pyexc = IdDict{DataType, PyPtr}() mutable struct PyIOError <: Exception end function pyexc_initialize() @@ -213,7 +221,7 @@ end function pyraise(e, bt = nothing) eT = typeof(e) - pyeT = haskey(pyexc::Dict, eT) ? pyexc[eT] : pyexc[Exception] + pyeT = haskey(pyexc, eT) ? pyexc[eT] : pyexc[Exception] err = PyJlError(e, bt) ccall((@pysym :PyErr_SetObject), Cvoid, (PyPtr, PyPtr), pyeT, PyObject(err)) diff --git a/src/gui.jl b/src/gui.jl index ff76b12e..9ed04316 100644 --- a/src/gui.jl +++ b/src/gui.jl @@ -1,6 +1,6 @@ # GUI event loops and toolkit integration for Python, most importantly # to support plotting in a window without blocking. Currently, we -# support wxWidgets, Qt5, Qt4, and GTK+. +# support wxWidgets, Qt4, Qt5, Qt6, and GTK+. ############################################################################ @@ -26,11 +26,14 @@ pygui_works(gui::Symbol) = gui == :default || (gui == :tk && pyexists(tkinter_name())) || (gui == :qt_pyqt4 && pyexists("PyQt4")) || (gui == :qt_pyqt5 && pyexists("PyQt5")) || + (gui == :qt_pyqt6 && pyexists("PyQt6")) || (gui == :qt_pyside && pyexists("PySide")) || (gui == :qt_pyside2 && pyexists("PySide2")) || + (gui == :qt_pyside6 && pyexists("PySide6")) || (gui == :qt4 && (pyexists("PyQt4") || pyexists("PySide"))) || (gui == :qt5 && (pyexists("PyQt5") || pyexists("PySide2"))) || - (gui == :qt && (pyexists("PyQt5") || pyexists("PyQt4") || pyexists("PySide") || pyexists("PySide2")))) + (gui == :qt6 && (pyexists("PyQt6") || pyexists("PySide6"))) || + (gui == :qt && (pyexists("PyQt6") || pyexists("PyQt5") || pyexists("PyQt4") || pyexists("PySide") || pyexists("PySide2") || pyexists("PySide6")))) # get or set the default GUI; doesn't affect running GUI """ @@ -55,7 +58,7 @@ end function pygui(g::Symbol) global gui if g != gui::Symbol - if !(g in (:wx,:gtk,:gtk3,:tk,:qt,:qt4,:qt5,:qt_pyqt5,:qt_pyqt4,:qt_pyside,:qt_pyside2,:default)) + if !(g in (:wx,:gtk,:gtk3,:tk,:qt,:qt4,:qt5,:qt6,:qt_pyqt4,:qt_pyqt5,:qt_pyqt6,:qt_pyside,:qt_pyside2,:qt_pyside6,:default)) throw(ArgumentError("invalid gui $g")) elseif !pygui_works(g) error("Python GUI toolkit for $g is not installed.") @@ -136,7 +139,7 @@ function fixqtpath(qtconf=joinpath(dirname(pyprogramname),"qt.conf")) return false end -# Qt: (PyQt5, PyQt4, or PySide module) +# Qt: (PyQt6, PyQt5, PyQt4, or PySide module) function qt_eventloop(QtCore::PyObject, sec::Real=50e-3) fixqtpath() instance = QtCore."QCoreApplication"."instance" @@ -157,7 +160,7 @@ qt_eventloop(QtModule::AbstractString, sec::Real=50e-3) = qt_eventloop(pyimport("$QtModule.QtCore"), sec) function qt_eventloop(sec::Real=50e-3) - for QtModule in ("PyQt5", "PyQt4", "PySide", "PySide2") + for QtModule in ("PyQt6", "PyQt5", "PyQt4", "PySide", "PySide2", "PySide6") try return qt_eventloop(QtModule, sec) catch @@ -232,11 +235,15 @@ function pygui_start(gui::Symbol=pygui(), sec::Real=50e-3) elseif gui == :qt_pyqt4 eventloops[gui] = qt_eventloop("PyQt4", sec) elseif gui == :qt_pyqt5 - eventloops[gui] = qt_eventloop("PyQt5", sec) + eventloops[gui] = qt_eventloop("PyQt5", sec) + elseif gui == :qt_pyqt6 + eventloops[gui] = qt_eventloop("PyQt6", sec) elseif gui == :qt_pyside eventloops[gui] = qt_eventloop("PySide", sec) elseif gui == :qt_pyside2 eventloops[gui] = qt_eventloop("PySide2", sec) + elseif gui == :qt_pyside6 + eventloops[gui] = qt_eventloop("PySide6", sec) elseif gui == :qt4 try eventloops[gui] = qt_eventloop("PyQt4", sec) @@ -249,6 +256,12 @@ function pygui_start(gui::Symbol=pygui(), sec::Real=50e-3) catch eventloops[gui] = qt_eventloop("PySide2", sec) end + elseif gui == :qt6 + try + eventloops[gui] = qt_eventloop("PyQt6", sec) + catch + eventloops[gui] = qt_eventloop("PySide6", sec) + end elseif gui == :qt eventloops[gui] = qt_eventloop(sec) else diff --git a/src/io.jl b/src/io.jl index 145b2fea..bee8440f 100644 --- a/src/io.jl +++ b/src/io.jl @@ -11,7 +11,7 @@ function ioraise(e, bt = nothing) if isa(e, MethodError) || isa(e, ErrorException) ccall((@pysym :PyErr_SetString), Cvoid, (PyPtr, Cstring), - (pyexc::Dict)[PyIOError], + pyexc[PyIOError], showerror_string(e, bt)) else pyraise(e, bt) diff --git a/src/numpy.jl b/src/numpy.jl index f3d523aa..1f96e4cb 100644 --- a/src/numpy.jl +++ b/src/numpy.jl @@ -64,8 +64,12 @@ function npyinitialize() numpy = pyimport("numpy") # emit a warning if both Julia and NumPy are linked with MKL (#433) - if LinearAlgebra.BLAS.vendor() === :mkl && - LinearAlgebra.BLAS.BlasInt === Int64 && hasproperty(numpy, "__config__") + julia_mkl = @static if VERSION < v"1.7" + LinearAlgebra.BLAS.vendor() === :mkl + else + any(contains("mkl"), getfield.(LinearAlgebra.BLAS.get_config().loaded_libs, :libname)) + end + if julia_mkl && LinearAlgebra.BLAS.BlasInt === Int64 && hasproperty(numpy, "__config__") config = numpy."__config__" if hasproperty(config, "blas_opt_info") blaslibs = get(config."blas_opt_info", Vector{String}, "libraries", String[]) diff --git a/src/precompile.jl b/src/precompile.jl new file mode 100644 index 00000000..cdd75906 --- /dev/null +++ b/src/precompile.jl @@ -0,0 +1,531 @@ +# Here, we precompile functions that are passed to cfunction by __init__, +# for the reasons described in JuliaLang/julia#12256. + +precompile(pyjlwrap_call, (PyPtr,PyPtr,PyPtr)) +precompile(pyjlwrap_dealloc, (PyPtr,)) +precompile(pyjlwrap_repr, (PyPtr,)) +precompile(pyjlwrap_hash, (PyPtr,)) +precompile(pyjlwrap_hash32, (PyPtr,)) + + +# The following calls were generated by running a PySR example +# (see https://github.com/MilesCranmer/PySR/pull/230), +# and also test/runtests.jl of PyCall.jl v1.94.1, with `--trace-compile=stderr`, +# and with `@testset` and `@test` replaced with identity macros. +# Overly-specific calls were then removed. + +# All calls are sorted in the following list. +precompile(Tuple{FuncWrapper{Tuple{Complex{Int64}}, typeof(sin)}, Complex{Int64}}) +precompile(Tuple{FuncWrapper{Tuple{Int64}, typeof(factorial)}, Int64}) +precompile(Tuple{PyObject, Array{Any, 1}, Vararg{Any}}) +precompile(Tuple{PyObject, Array{Int64, 1}, Vararg{Any}}) +precompile(Tuple{PyObject, Array{String, 1}}) +precompile(Tuple{PyObject, Bool}) +precompile(Tuple{PyObject, Dict{Int64, PyObject}}) +precompile(Tuple{PyObject, Function}) +precompile(Tuple{PyObject, Int64, Vararg{Any}}) +precompile(Tuple{PyObject, Int64, Vararg{Int64}}) +precompile(Tuple{PyObject, Int64}) +precompile(Tuple{PyObject, PyObject, Vararg{Any}}) +precompile(Tuple{PyObject, PyObject, Vararg{PyObject}}) +precompile(Tuple{PyObject, String, Vararg{Any}}) +precompile(Tuple{PyObject, String, Vararg{String}}) +precompile(Tuple{PyObject, UnitRange{Int64}, Vararg{UnitRange{Int64}}}) +precompile(Tuple{PyObject}) +precompile(Tuple{Type{Base.IteratorSize}, PyIterator{PyObject, Base.SizeUnknown}}) +precompile(Tuple{Type{Dict{K, V} where V where K}, Pair{Int64, PyObject}}) +precompile(Tuple{Type{Dict{Module, PyDict{String, PyObject, true}}}}) +precompile(Tuple{Type{Dict{Ptr{PyObject_struct}, Any}}}) +precompile(Tuple{Type{Docs.Binding}, PyObject, Symbol}) +precompile(Tuple{Type{FuncWrapper{Tuple{Complex{Int64}}, typeof(sin)}}, Function, Dict{Symbol, Any}}) +precompile(Tuple{Type{FuncWrapper{Tuple{Int64}, typeof(factorial)}}, Function, Dict{Symbol, Any}}) +precompile(Tuple{Type{IdDict{DataType, Ptr{PyObject_struct}}}}) +precompile(Tuple{Type{Iterators.Zip{Is} where Is<:Tuple}, Tuple{PyIterator{Int64, Base.SizeUnknown}, UnitRange{Int64}}}) +precompile(Tuple{Type{Iterators.Zip{Is} where Is<:Tuple}, Tuple{PyIterator{PyObject, Base.HasLength}, UnitRange{Int64}}}) +precompile(Tuple{Type{Iterators.Zip{Is} where Is<:Tuple}, Tuple{PyObject, UnitRange{Int64}}}) +precompile(Tuple{Type{NamedTuple{(:dtype,), T} where T<:Tuple}, Tuple{PyObject}}) +precompile(Tuple{Type{Pair{A, B} where B where A}, Int64, PyObject}) +precompile(Tuple{Type{Pair{A, B} where B where A}, Symbol, PyObject}) +precompile(Tuple{Type{Ptr{PyObject_struct}}, Ptr{Nothing}}) +precompile(Tuple{Type{Ptr{PyObject_struct}}, Ptr{PyObject_struct}}) +precompile(Tuple{Type{Ptr{PyObject_struct}}, PyObject}) +precompile(Tuple{Type{PyAny}, PyObject}) +precompile(Tuple{Type{PyArray{Bool, 1}}, PyObject, PyArray_Info{Bool, 1}}) +precompile(Tuple{Type{PyArray{Bool, 3}}, PyObject, PyArray_Info{Bool, 3}}) +precompile(Tuple{Type{PyArray{Complex{Float64}, 2}}, PyObject, PyArray_Info{Complex{Float64}, 2}}) +precompile(Tuple{Type{PyArray{Float16, 1}}, PyObject, PyArray_Info{Float16, 1}}) +precompile(Tuple{Type{PyArray{Float16, 2}}, PyObject, PyArray_Info{Float16, 2}}) +precompile(Tuple{Type{PyArray{Float32, 1}}, PyObject, PyArray_Info{Float32, 1}}) +precompile(Tuple{Type{PyArray{Float32, 2}}, PyObject, PyArray_Info{Float32, 2}}) +precompile(Tuple{Type{PyArray{Float64, 1}}, PyObject, PyArray_Info{Float64, 1}}) +precompile(Tuple{Type{PyArray{Float64, 2}}, PyObject, PyArray_Info{Float64, 2}}) +precompile(Tuple{Type{PyArray{Float64, 3}}, PyObject, PyArray_Info{Float64, 3}}) +precompile(Tuple{Type{PyArray{Int16, 1}}, PyObject, PyArray_Info{Int16, 1}}) +precompile(Tuple{Type{PyArray{Int32, 1}}, PyObject, PyArray_Info{Int32, 1}}) +precompile(Tuple{Type{PyArray{Int32, 2}}, PyObject, PyArray_Info{Int32, 2}}) +precompile(Tuple{Type{PyArray{Int64, 0}}, PyObject, PyArray_Info{Int64, 0}}) +precompile(Tuple{Type{PyArray{Int64, 1}}, PyObject, PyArray_Info{Int64, 1}}) +precompile(Tuple{Type{PyArray{Int64, 2}}, PyObject, PyArray_Info{Int64, 2}}) +precompile(Tuple{Type{PyArray{Int64, 3}}, PyObject, PyArray_Info{Int64, 3}}) +precompile(Tuple{Type{PyArray{Int8, 1}}, PyObject, PyArray_Info{Int64, 1}}) +precompile(Tuple{Type{PyArray{Ptr{Nothing}, 0}}, PyObject, PyArray_Info{Ptr{Nothing}, 0}}) +precompile(Tuple{Type{PyArray{Ptr{PyObject_struct}, 1}}, PyObject, PyArray_Info{Ptr{PyObject_struct}, 1}}) +precompile(Tuple{Type{PyArray{Ptr{PyObject_struct}, 2}}, PyObject, PyArray_Info{Ptr{PyObject_struct}, 2}}) +precompile(Tuple{Type{PyArray{T, N} where N where T}, PyObject}) +precompile(Tuple{Type{PyBuffer}, PyObject}) +precompile(Tuple{Type{PyDict{Int64, Int64, true}}, PyObject}) +precompile(Tuple{Type{PyDict{Int64, PyObject, false}}, PyObject}) +precompile(Tuple{Type{PyDict{Int64, String, true}}, PyObject}) +precompile(Tuple{Type{PyDict{K, V, isdict} where isdict where V where K}, Dict{Int64, Int64}}) +precompile(Tuple{Type{PyDict{K, V, isdict} where isdict where V where K}, Dict{Int64, String}}) +precompile(Tuple{Type{PyDict{K, V, isdict} where isdict where V where K}, PyObject}) +precompile(Tuple{Type{PyDict{PyAny, PyAny, true}}, PyObject}) +precompile(Tuple{Type{PyDict{Symbol, PyObject, true}}, PyObject}) +precompile(Tuple{Type{PyIterator{Float64, Base.HasLength}}, PyObject}) +precompile(Tuple{Type{PyIterator{Float64, S} where S}, PyObject}) +precompile(Tuple{Type{PyIterator{Int64, Base.SizeUnknown}}, PyObject}) +precompile(Tuple{Type{PyIterator{Int64, S} where S}, PyObject}) +precompile(Tuple{Type{PyIterator{PyAny, Base.HasLength}}, PyObject}) +precompile(Tuple{Type{PyIterator{PyAny, S} where S}, PyObject}) +precompile(Tuple{Type{PyIterator{PyObject, Base.HasLength}}, PyObject}) +precompile(Tuple{Type{PyIterator{PyObject, Base.SizeUnknown}}, PyObject}) +precompile(Tuple{Type{PyIterator{T, S} where S where T}, PyObject}) +precompile(Tuple{Type{PyMemberDef}, Ptr{Nothing}, Int64, Int64, Int64, Ptr{Nothing}}) +precompile(Tuple{Type{PyObject}, Array{Any, 0}}) +precompile(Tuple{Type{PyObject}, Array{Any, 1}}) +precompile(Tuple{Type{PyObject}, Array{Complex{Float64}, 1}}) +precompile(Tuple{Type{PyObject}, Array{Float64, 3}}) +precompile(Tuple{Type{PyObject}, Array{PyObject, 1}}) +precompile(Tuple{Type{PyObject}, Array{UInt32, 1}}) +precompile(Tuple{Type{PyObject}, Array{UInt8, 1}}) +precompile(Tuple{Type{PyObject}, Base.Generator{UnitRange{Int64}, typeof(identity)}}) +precompile(Tuple{Type{PyObject}, Bool}) +precompile(Tuple{Type{PyObject}, Complex{Int64}}) +precompile(Tuple{Type{PyObject}, Float64}) +precompile(Tuple{Type{PyObject}, Function}) +precompile(Tuple{Type{PyObject}, Int128}) +precompile(Tuple{Type{PyObject}, Int64}) +precompile(Tuple{Type{PyObject}, Module}) +precompile(Tuple{Type{PyObject}, Ptr{Nothing}}) +precompile(Tuple{Type{PyObject}, PyObject}) +precompile(Tuple{Type{PyObject}, String}) +precompile(Tuple{Type{PyObject}, Tuple{Int64}}) +precompile(Tuple{Type{PyObject}, Type}) +precompile(Tuple{Type{PyObject}, UnitRange{Int64}}) +precompile(Tuple{Type{PyTypeObject}}) +precompile(Tuple{Type{Ref{Ptr{PyObject_struct}}}, Int64}) +precompile(Tuple{Type{Ref{PyMethodDef}}}) +precompile(Tuple{Type{Ref{Union{Nothing, Tuple{PyObject, Int64}}}}, Tuple{PyObject, Int64}}) +precompile(Tuple{typeof(:(!=)), Ptr{PyObject_struct}, Ptr{PyObject_struct}}) +precompile(Tuple{typeof(:(!=)), PyObject, Float64}) +precompile(Tuple{typeof(:(&)), Int64, PyObject}) +precompile(Tuple{typeof(:(&)), PyObject, Int64}) +precompile(Tuple{typeof(:(&)), PyObject, PyObject}) +precompile(Tuple{typeof(:(*)), Int64, PyObject}) +precompile(Tuple{typeof(:(*)), PyObject, Int64}) +precompile(Tuple{typeof(:(*)), PyObject, PyObject}) +precompile(Tuple{typeof(:(-)), Int64, PyObject}) +precompile(Tuple{typeof(:(-)), PyObject, Int128}) +precompile(Tuple{typeof(:(-)), PyObject, Int64}) +precompile(Tuple{typeof(:(-)), PyObject, PyObject}) +precompile(Tuple{typeof(:(-)), PyObject}) +precompile(Tuple{typeof(:(/)), Int64, PyObject}) +precompile(Tuple{typeof(:(/)), PyObject, Int64}) +precompile(Tuple{typeof(:(/)), PyObject, PyObject}) +precompile(Tuple{typeof(:(<)), PyObject, Float64}) +precompile(Tuple{typeof(:(<)), PyObject, PyObject}) +precompile(Tuple{typeof(:(<<)), Int64, PyObject}) +precompile(Tuple{typeof(:(<<)), PyObject, Int64}) +precompile(Tuple{typeof(:(<<)), PyObject, PyObject}) +precompile(Tuple{typeof(:(<=)), PyObject, Float64}) +precompile(Tuple{typeof(:(<=)), PyObject, PyObject}) +precompile(Tuple{typeof(:(==)), Array{PyObject, 1}, Array{Int64, 1}}) +precompile(Tuple{typeof(:(==)), Array{PyObject, 2}, Array{Int64, 2}}) +precompile(Tuple{typeof(:(==)), Array{Tuple{PyObject, Int64}, 1}, Array{Tuple{Int64, Int64}, 1}}) +precompile(Tuple{typeof(:(==)), Dict{Int64, Int64}, PyDict{Int64, Int64, true}}) +precompile(Tuple{typeof(:(==)), Dict{Int64, PyObject}, Dict{Int64, PyObject}}) +precompile(Tuple{typeof(:(==)), Ptr{PyObject_struct}, Ptr{PyObject_struct}}) +precompile(Tuple{typeof(:(==)), PyArray{Float64, 2}, Array{Float64, 2}}) +precompile(Tuple{typeof(:(==)), PyDict{Int64, Int64, true}, Dict{Int64, Int64}}) +precompile(Tuple{typeof(:(==)), PyDict{PyAny, PyAny, true}, Dict{Int64, String}}) +precompile(Tuple{typeof(:(==)), PyObject, Float64}) +precompile(Tuple{typeof(:(==)), PyObject, Int64}) +precompile(Tuple{typeof(:(==)), Tuple{PyObject, PyObject, PyObject, PyObject, PyObject}, Tuple{PyObject, PyObject, PyObject, PyObject, PyObject}}) +precompile(Tuple{typeof(:(==)), Tuple{PyObject, PyObject, PyObject}, Tuple{PyObject, PyObject, PyObject}}) +precompile(Tuple{typeof(:(==)), Tuple{PyObject, PyObject}, Tuple{PyObject, PyObject}}) +precompile(Tuple{typeof(:(>)), PyObject, Float64}) +precompile(Tuple{typeof(:(>)), PyObject, PyObject}) +precompile(Tuple{typeof(:(>=)), PyObject, Float64}) +precompile(Tuple{typeof(:(>>)), Int64, PyObject}) +precompile(Tuple{typeof(:(>>)), PyObject, Int64}) +precompile(Tuple{typeof(:(>>)), PyObject, PyObject}) +precompile(Tuple{typeof(:(^)), Int64, PyObject}) +precompile(Tuple{typeof(:(^)), PyObject, Int64}) +precompile(Tuple{typeof(:(^)), PyObject, PyObject}) +precompile(Tuple{typeof(:(|)), Int64, PyObject}) +precompile(Tuple{typeof(:(|)), PyObject, Int64}) +precompile(Tuple{typeof(:(|)), PyObject, PyObject}) +precompile(Tuple{typeof(:(~)), PyObject}) +precompile(Tuple{typeof(Base._append!), Array{PyMemberDef, 1}, Base.HasLength, Tuple{PyMemberDef, PyMemberDef}}) +precompile(Tuple{typeof(Base.cconvert), Type, Base.RefValue{PyMethodDef}}) +precompile(Tuple{typeof(Base.cconvert), Type{Ptr{PyObject_struct}}, Ptr{Nothing}}) +precompile(Tuple{typeof(Base.cconvert), Type{Ptr{PyObject_struct}}, PyObject}) +precompile(Tuple{typeof(Base.indexed_iterate), Array{PyObject, 1}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Array{PyObject, 1}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Pair{Symbol, PyObject}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Pair{Symbol, PyObject}, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{PyObject, Int64}, Int64, Int64}) +precompile(Tuple{typeof(Base.indexed_iterate), Tuple{PyObject, Int64}, Int64}) +precompile(Tuple{typeof(Base.vect), PyObject, Vararg{PyObject}}) +precompile(Tuple{typeof(Base.vect), PyObject}) +precompile(Tuple{typeof(Broadcast.broadcasted), Function, Array{Float64, 1}, PyArray{Float64, 1}}) +precompile(Tuple{typeof(Broadcast.broadcasted), Function, PyArray{Ptr{PyObject_struct}, 1}}) +precompile(Tuple{typeof(Broadcast.broadcasted), Function, PyArray{Ptr{PyObject_struct}, 2}}) +precompile(Tuple{typeof(Broadcast.broadcasted), Function, PyObject, Array{Int64, 1}}) +precompile(Tuple{typeof(Core.Compiler.eltype), Type{Array{PyObject, 1}}}) +precompile(Tuple{typeof(Core.convert), Type{DataType}, Type{Ptr{PyObject_struct}}}) +precompile(Tuple{typeof(Docs.doc), PyObject}) +precompile(Tuple{typeof(Iterators.zip), PyIterator{Int64, Base.SizeUnknown}, Vararg{Any}}) +precompile(Tuple{typeof(Iterators.zip), PyIterator{PyObject, Base.HasLength}, Vararg{Any}}) +precompile(Tuple{typeof(Iterators.zip), PyObject, Vararg{Any}}) +precompile(Tuple{typeof(NoCopyArray), PyObject}) +precompile(Tuple{typeof(PyNULL)}) +precompile(Tuple{typeof(PyReverseDims), Array{Int64, 3}}) +precompile(Tuple{typeof(PyReverseDims), BitArray{3}}) +precompile(Tuple{typeof(Py_Finalize)}) +precompile(Tuple{typeof(Py_GetVersion), Ptr{Nothing}}) +precompile(Tuple{typeof(Py_SetPythonHome), Ptr{Nothing}, VersionNumber, String}) +precompile(Tuple{typeof(__init__)}) +precompile(Tuple{typeof(_insert!), PyObject, Int64, Int64}) +precompile(Tuple{typeof(_pyjlwrap_call), Function, Ptr{PyObject_struct}, Ptr{PyObject_struct}}) +precompile(Tuple{typeof(_pyjlwrap_call), Type, Ptr{PyObject_struct}, Ptr{PyObject_struct}}) +precompile(Tuple{typeof(_pywith), Expr, Nothing, Type, Expr}) +precompile(Tuple{typeof(_pywith), Expr, Symbol, Type, Expr}) +precompile(Tuple{typeof(_set_finalized)}) +precompile(Tuple{typeof(abs), PyObject}) +precompile(Tuple{typeof(append!), PyObject, Array{Int64, 1}}) +precompile(Tuple{typeof(append!), PyObject, PyObject}) +precompile(Tuple{typeof(callsym), Expr}) +precompile(Tuple{typeof(collect), Base.KeySet{Int64, PyDict{Int64, String, true}}}) +precompile(Tuple{typeof(collect), Iterators.Zip{Tuple{PyIterator{Int64, Base.SizeUnknown}, UnitRange{Int64}}}}) +precompile(Tuple{typeof(collect), Iterators.Zip{Tuple{PyIterator{PyObject, Base.HasLength}, UnitRange{Int64}}}}) +precompile(Tuple{typeof(collect), Iterators.Zip{Tuple{PyObject, UnitRange{Int64}}}}) +precompile(Tuple{typeof(collect), PyIterator{Float64, Base.HasLength}}) +precompile(Tuple{typeof(collect), PyIterator{PyAny, Base.HasLength}}) +precompile(Tuple{typeof(collect), PyIterator{PyObject, Base.HasLength}}) +precompile(Tuple{typeof(collect), PyObject}) +precompile(Tuple{typeof(convert), Type{AbstractRange{T} where T}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Bool, N} where N}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Complex{Float64}, N} where N}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Float16, N} where N}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Float32, 1}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Float32, 2}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Float32, N} where N}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Float64, 1}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Float64, 2}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Float64, N} where N}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Function, 1}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Int32, N} where N}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Int64, 1}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Int64, 2}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Int64, N} where N}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{Int8, N} where N}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{PyAny, 1}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{PyObject, 1}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{PyObject, 2}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{PyObject, N} where N}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{T, N} where N where T}, PyObject}) +precompile(Tuple{typeof(convert), Type{Array{UInt8, 1}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Bool}, PyObject}) +precompile(Tuple{typeof(convert), Type{Complex{Float64}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Complex{Int64}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Dates.DateTime}, PyObject}) +precompile(Tuple{typeof(convert), Type{Dates.Date}, PyObject}) +precompile(Tuple{typeof(convert), Type{Dates.Day}, PyObject}) +precompile(Tuple{typeof(convert), Type{Dates.Millisecond}, PyObject}) +precompile(Tuple{typeof(convert), Type{Dates.Second}, PyObject}) +precompile(Tuple{typeof(convert), Type{Dict{Int64, PyObject}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Dict{PyAny, PyAny}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Float32}, PyObject}) +precompile(Tuple{typeof(convert), Type{Float64}, PyObject}) +precompile(Tuple{typeof(convert), Type{Function}, PyObject}) +precompile(Tuple{typeof(convert), Type{Int32}, PyObject}) +precompile(Tuple{typeof(convert), Type{Int64}, PyObject}) +precompile(Tuple{typeof(convert), Type{Int8}, PyObject}) +precompile(Tuple{typeof(convert), Type{Integer}, PyObject}) +precompile(Tuple{typeof(convert), Type{Nothing}, PyObject}) +precompile(Tuple{typeof(convert), Type{Pair{Int64, Int64}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Ptr{Nothing}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Ptr{PyGetSetDef}}, Ptr{Nothing}}) +precompile(Tuple{typeof(convert), Type{Ptr{PyMemberDef}}, Ptr{Nothing}}) +precompile(Tuple{typeof(convert), Type{Ptr{PyMethodDef}}, Ptr{Nothing}}) +precompile(Tuple{typeof(convert), Type{Ptr{PyObject_struct}}, Ptr{Nothing}}) +precompile(Tuple{typeof(convert), Type{Ptr{PyObject_struct}}, Ptr{PyObject_struct}}) +precompile(Tuple{typeof(convert), Type{PyArray{T, N} where N where T}, PyObject}) +precompile(Tuple{typeof(convert), Type{PyObject}, Array{Any, 1}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Array{Float32, 1}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Array{Float32, 2}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Array{Float64, 1}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Array{Float64, 2}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Array{Function, 1}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Array{Int64, 1}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Array{Int64, 2}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Bool}) +precompile(Tuple{typeof(convert), Type{PyObject}, Dict{Function, Dict{K, Int64} where K}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Dict{Function, Int64}}) +precompile(Tuple{typeof(convert), Type{PyObject}, Float32}) +precompile(Tuple{typeof(convert), Type{PyObject}, Float64}) +precompile(Tuple{typeof(convert), Type{PyObject}, Function}) +precompile(Tuple{typeof(convert), Type{PyObject}, Int64}) +precompile(Tuple{typeof(convert), Type{PyObject}, Nothing}) +precompile(Tuple{typeof(convert), Type{PyObject}, PyObject}) +precompile(Tuple{typeof(convert), Type{PyObject}, String}) +precompile(Tuple{typeof(convert), Type{PyObject}, Type}) +precompile(Tuple{typeof(convert), Type{Py_buffer}, Py_buffer}) +precompile(Tuple{typeof(convert), Type{Ref{PyMethodDef}}, Base.RefValue{PyMethodDef}}) +precompile(Tuple{typeof(convert), Type{String}, PyObject}) +precompile(Tuple{typeof(convert), Type{Symbol}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{AbstractRange{T} where T, AbstractRange{T} where T, AbstractRange{T} where T}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Array{Float32, N} where N, Array{Float32, N} where N}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Float64, String}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Int64, Int64, Int64}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Int64, Vararg{Int64}}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Integer, Integer}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Integer, PyAny}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Integer, Tuple{Float64, String}, Bool}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Integer}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Nothing, Nothing, Nothing}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny, AbstractString}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny, Array{T, N} where N where T}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny, Array{UInt8, 1}}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny, Bool}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny, Integer, Integer}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny, Integer}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny, Nothing, Nothing, Nothing}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny, PyAny}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny, String}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{PyAny}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{String, Integer}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{String, String}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{String}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Vararg{Int64}}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{Vararg{PyAny}}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple{}}, PyObject}) +precompile(Tuple{typeof(convert), Type{Tuple}, PyObject}) +precompile(Tuple{typeof(convert), Type{Type}, PyObject}) +precompile(Tuple{typeof(copy!), PyObject, PyObject}) +precompile(Tuple{typeof(copy), PyArray{Float64, 2}}) +precompile(Tuple{typeof(copy), PyDict{Int64, PyObject, false}}) +precompile(Tuple{typeof(copy), PyDict{PyAny, PyAny, true}}) +precompile(Tuple{typeof(current_python)}) +precompile(Tuple{typeof(delete!), PyDict{String, PyObject, true}, Int64}) +precompile(Tuple{typeof(delete!), PyDict{String, PyObject, true}, String}) +precompile(Tuple{typeof(docstring), Function}) +precompile(Tuple{typeof(eltype), PyArray_Info{Float64, 3}}) +precompile(Tuple{typeof(eltype), PyArray_Info{Int16, 1}}) +precompile(Tuple{typeof(eltype), PyArray_Info{Int32, 2}}) +precompile(Tuple{typeof(eltype), PyArray_Info{Ptr{Nothing}, 0}}) +precompile(Tuple{typeof(eltype), PyArray{Int32, 1}}) +precompile(Tuple{typeof(eltype), PyArray{Int32, 2}}) +precompile(Tuple{typeof(eltype), PyArray{Ptr{PyObject_struct}, 1}}) +precompile(Tuple{typeof(eltype), PyArray{Ptr{PyObject_struct}, 2}}) +precompile(Tuple{typeof(eltype), PyDict{Int64, String, true}}) +precompile(Tuple{typeof(empty!), PyObject}) +precompile(Tuple{typeof(empty), Dict{Any, Any}, Type{Symbol}, Type{PyObject}}) +precompile(Tuple{typeof(f_contiguous), Type{Float64}, Tuple{Int64, Int64, Int64}, Tuple{Int64, Int64, Int64}}) +precompile(Tuple{typeof(f_contiguous), Type{Float64}, Tuple{Int64, Int64}, Tuple{Int64, Int64}}) +precompile(Tuple{typeof(f_contiguous), Type{Float64}, Tuple{Int64}, Tuple{Int64}}) +precompile(Tuple{typeof(findsym), Ptr{Nothing}, Symbol, Vararg{Symbol}}) +precompile(Tuple{typeof(float), PyObject}) +precompile(Tuple{typeof(get), PyObject, Int64}) +precompile(Tuple{typeof(get), PyObject, Tuple{Int64, Int64, Int64}}) +precompile(Tuple{typeof(get), PyObject, Tuple{Int64, Int64}}) +precompile(Tuple{typeof(get), PyObject, Type{PyObject}, Int64}) +precompile(Tuple{typeof(get_format_str), PyBuffer}) +precompile(Tuple{typeof(getindex), Base.RefValue{Union{Nothing, Tuple{PyObject, Int64}}}}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 1}, Int64}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 1}, UnitRange{Int64}}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 2}, Base.IteratorsMD.CartesianIndex{2}}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 2}, Int64, Int64, Int64}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 2}, Int64, Int64}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 3}, Base.IteratorsMD.CartesianIndex{4}}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 3}, Base.IteratorsMD.CartesianIndex{5}}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 3}, Int64, Int64, Int64, Vararg{Int64}}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 3}, Int64, Int64, Int64}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 3}, Int64, Int64}) +precompile(Tuple{typeof(getindex), PyArray{Float64, 3}, Int64}) +precompile(Tuple{typeof(getindex), PyArray{Int64, 1}, UnitRange{Int64}}) +precompile(Tuple{typeof(getindex), PyArray{Int64, 2}, UnitRange{Int64}, Int64}) +precompile(Tuple{typeof(getindex), PyArray{Int64, 2}, UnitRange{Int64}, UnitRange{Int64}}) +precompile(Tuple{typeof(getindex), PyArray{Ptr{Nothing}, 0}}) +precompile(Tuple{typeof(getindex), PyDict{Int64, String, true}, Int64}) +precompile(Tuple{typeof(getindex), Type{PyAny}}) +precompile(Tuple{typeof(getindex), Type{PyMemberDef}}) +precompile(Tuple{typeof(getindex), Type{Tuple{PyObject, Type}}}) +precompile(Tuple{typeof(getproperty), PyArray_Info{Int32, 1}, Symbol}) +precompile(Tuple{typeof(getproperty), PyArray_Info{Int32, 2}, Symbol}) +precompile(Tuple{typeof(getproperty), PyArray{Float64, 1}, Symbol}) +precompile(Tuple{typeof(getproperty), PyArray{Float64, 2}, Symbol}) +precompile(Tuple{typeof(getproperty), PyArray{Int32, 1}, Symbol}) +precompile(Tuple{typeof(getproperty), PyArray{Int32, 2}, Symbol}) +precompile(Tuple{typeof(getproperty), PyDict{Int64, String, true}, Symbol}) +precompile(Tuple{typeof(getproperty), PyError, Symbol}) +precompile(Tuple{typeof(getproperty), PyObject, String}) +precompile(Tuple{typeof(hash), PyObject}) +precompile(Tuple{typeof(hashsalt), Function}) +precompile(Tuple{typeof(hasproperty), PyObject, String}) +precompile(Tuple{typeof(hasproperty), PyObject, Symbol}) +precompile(Tuple{typeof(hassym), Ptr{Nothing}, Symbol}) +precompile(Tuple{typeof(include), String}) +precompile(Tuple{typeof(interpolate_pycode), String}) +precompile(Tuple{typeof(is_pyjlwrap), PyObject}) +precompile(Tuple{typeof(isbuftype), PyObject}) +precompile(Tuple{typeof(iscontiguous), PyBuffer}) +precompile(Tuple{typeof(isempty), PyObject}) +precompile(Tuple{typeof(isequal), PyObject, PyObject}) +precompile(Tuple{typeof(isless), PyObject, Float64}) +precompile(Tuple{typeof(isless), PyObject, PyObject}) +precompile(Tuple{typeof(ispynull), PyObject}) +precompile(Tuple{typeof(istuplen), Type, Bool, Int64}) +precompile(Tuple{typeof(iterate), Dict{Symbol, PyObject}, Int64}) +precompile(Tuple{typeof(iterate), Dict{Symbol, PyObject}}) +precompile(Tuple{typeof(jlwrap_iterator), Base.Generator{UnitRange{Int64}, typeof(identity)}}) +precompile(Tuple{typeof(jlwrap_iterator), UnitRange{Int64}}) +precompile(Tuple{typeof(keys), PyDict{Int64, String, true}}) +precompile(Tuple{typeof(keys), PyObject}) +precompile(Tuple{typeof(keys), Type{Int64}, PyDict{Int64, String, true}}) +precompile(Tuple{typeof(length), Array{PyObject, 1}}) +precompile(Tuple{typeof(length), PyBuffer}) +precompile(Tuple{typeof(length), PyIterator{PyObject, Base.HasLength}}) +precompile(Tuple{typeof(length), PyObject}) +precompile(Tuple{typeof(make_fname), String}) +precompile(Tuple{typeof(merge), Dict{Symbol, PyObject}, Dict{Any, Any}, Dict{Any, Any}}) +precompile(Tuple{typeof(merge), Dict{Symbol, PyObject}, Dict{Any, Any}, Dict{Symbol, Int64}}) +precompile(Tuple{typeof(merge), Dict{Symbol, PyObject}, Dict{Symbol, PyObject}, Dict{Any, Any}}) +precompile(Tuple{typeof(ndims), PyBuffer}) +precompile(Tuple{typeof(parse_pydef), Expr}) +precompile(Tuple{typeof(parse_pydef_toplevel), Expr}) +precompile(Tuple{typeof(pickle)}) +precompile(Tuple{typeof(pop!), PyObject}) +precompile(Tuple{typeof(popfirst!), PyObject}) +precompile(Tuple{typeof(prepend!), PyObject, Array{Int64, 1}}) +precompile(Tuple{typeof(prepend!), PyObject, PyObject}) +precompile(Tuple{typeof(propertynames), PyObject}) +precompile(Tuple{typeof(push!), PyObject, Int64}) +precompile(Tuple{typeof(pushfirst!), PyObject, Int64}) +precompile(Tuple{typeof(py2array), Type, Array{Any, 1}, PyObject, Int64, Int64}) +precompile(Tuple{typeof(pyany_toany), Type{Tuple{Int64, PyAny}}}) +precompile(Tuple{typeof(pyany_toany), Type{Tuple{Int64, Tuple{PyAny, Int8}}}}) +precompile(Tuple{typeof(pyany_toany), Type{Tuple{PyAny, Int64, Vararg{PyAny}}}}) +precompile(Tuple{typeof(pyany_toany), Type{Tuple{PyAny, Int8}}}) +precompile(Tuple{typeof(pyany_toany), Type}) +precompile(Tuple{typeof(pybuiltin), String}) +precompile(Tuple{typeof(pybytes), Array{UInt8, 1}}) +precompile(Tuple{typeof(pybytes), String}) +precompile(Tuple{typeof(pycall!), PyObject, PyObject, Type{PyAny}, String, Vararg{Any}}) +precompile(Tuple{typeof(pycall!), PyObject, PyObject, Type{PyObject}, String, Vararg{Any}}) +precompile(Tuple{typeof(pycall!), PyObject, PyObject, Type{Tuple}, String, Vararg{Any}}) +precompile(Tuple{typeof(pycall), PyObject, Type{Bool}, PyObject, Vararg{Any}}) +precompile(Tuple{typeof(pycall), PyObject, Type{Int64}, Int64}) +precompile(Tuple{typeof(pycall), PyObject, Type{PyAny}, Int64}) +precompile(Tuple{typeof(pycall), PyObject, Type{PyAny}, PyObject}) +precompile(Tuple{typeof(pycall), PyObject, Type{PyAny}, String, Vararg{Any}}) +precompile(Tuple{typeof(pycall), PyObject, Type{PyArray{T, N} where N where T}, Array{Int64, 1}}) +precompile(Tuple{typeof(pycall), PyObject, Type{PyArray{T, N} where N where T}, Array{Int64, 2}}) +precompile(Tuple{typeof(pycall), PyObject, Type{PyObject}, Int64}) +precompile(Tuple{typeof(pycall), PyObject, Type{PyObject}, PyObject}) +precompile(Tuple{typeof(pycall), PyObject, Type{PyObject}, String, Vararg{Any}}) +precompile(Tuple{typeof(pycall), PyObject, Type{PyObject}, UnitRange{Int64}}) +precompile(Tuple{typeof(pycall), PyObject, Type{Tuple}, String, Vararg{Any}}) +precompile(Tuple{typeof(pydecref), PyBuffer}) +precompile(Tuple{typeof(pydecref), PyObject}) +precompile(Tuple{typeof(pyerr_clear)}) +precompile(Tuple{typeof(pyerror), String, PyError}) +precompile(Tuple{typeof(pyfunction), Function, Type}) +precompile(Tuple{typeof(pyfunctionret), Function, Nothing, Type}) +precompile(Tuple{typeof(pyfunctionret), Function, Type, Type}) +precompile(Tuple{typeof(pyimport), Symbol}) +precompile(Tuple{typeof(pyimport_conda), String, String}) +precompile(Tuple{typeof(pyimport_e), String}) +precompile(Tuple{typeof(pyincref_), Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pyisinstance), PyObject, Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pyisinstance), PyObject, PyObject}) +precompile(Tuple{typeof(pyjlwrap_call), Ptr{PyObject_struct}, Ptr{PyObject_struct}, Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pyjlwrap_dealloc), Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pyjlwrap_getattr), Ptr{PyObject_struct}, Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pyjlwrap_getiter), Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pyjlwrap_hash), Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pyjlwrap_hash32), Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pyjlwrap_iternext), Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pyjlwrap_new), Array{Float32, 1}}) +precompile(Tuple{typeof(pyjlwrap_new), Array{Float32, 2}}) +precompile(Tuple{typeof(pyjlwrap_new), Array{Float64, 1}}) +precompile(Tuple{typeof(pyjlwrap_new), Array{Float64, 2}}) +precompile(Tuple{typeof(pyjlwrap_new), Array{Int64, 1}}) +precompile(Tuple{typeof(pyjlwrap_new), Array{Int64, 2}}) +precompile(Tuple{typeof(pyjlwrap_new), FuncWrapper{Tuple{Complex{Int64}}, typeof(sin)}}) +precompile(Tuple{typeof(pyjlwrap_new), FuncWrapper{Tuple{Int64}, typeof(factorial)}}) +precompile(Tuple{typeof(pyjlwrap_new), Function}) +precompile(Tuple{typeof(pyjlwrap_new), Nothing}) +precompile(Tuple{typeof(pyjlwrap_new), PyTypeObject, Tuple{Base.Generator{UnitRange{Int64}, typeof(identity)}, Base.RefValue{Union{Nothing, Tuple{Int64, Int64}}}}}) +precompile(Tuple{typeof(pyjlwrap_new), PyTypeObject, Tuple{UnitRange{Int64}, Base.RefValue{Union{Nothing, Tuple{Int64, Int64}}}}}) +precompile(Tuple{typeof(pyjlwrap_new), UnitRange{Int64}}) +precompile(Tuple{typeof(pyjlwrap_repr), Ptr{PyObject_struct}}) +precompile(Tuple{typeof(pynamespace), Module}) +precompile(Tuple{typeof(pyo2ptr), Type}) +precompile(Tuple{typeof(pyocopy), PyArray{Bool, 1}}) +precompile(Tuple{typeof(pyocopy), PyArray{Bool, 3}}) +precompile(Tuple{typeof(pyocopy), PyArray{Complex{Float64}, 2}}) +precompile(Tuple{typeof(pyocopy), PyArray{Float16, 1}}) +precompile(Tuple{typeof(pyocopy), PyArray{Float16, 2}}) +precompile(Tuple{typeof(pyocopy), PyArray{Float32, 1}}) +precompile(Tuple{typeof(pyocopy), PyArray{Float32, 2}}) +precompile(Tuple{typeof(pyocopy), PyArray{Float64, 1}}) +precompile(Tuple{typeof(pyocopy), PyArray{Float64, 2}}) +precompile(Tuple{typeof(pyocopy), PyArray{Int32, 1}}) +precompile(Tuple{typeof(pyocopy), PyArray{Int32, 2}}) +precompile(Tuple{typeof(pyocopy), PyArray{Int64, 1}}) +precompile(Tuple{typeof(pyocopy), PyArray{Int64, 2}}) +precompile(Tuple{typeof(pyocopy), PyArray{Int64, 3}}) +precompile(Tuple{typeof(pyocopy), PyArray{Ptr{PyObject_struct}, 1}}) +precompile(Tuple{typeof(pyocopy), PyArray{Ptr{PyObject_struct}, 2}}) +precompile(Tuple{typeof(pyrepr), PyObject}) +precompile(Tuple{typeof(pyreturn), Bool}) +precompile(Tuple{typeof(pyreturn), Complex{Float64}}) +precompile(Tuple{typeof(pyreturn), Float64}) +precompile(Tuple{typeof(pyreturn), Int64}) +precompile(Tuple{typeof(pyreturn), Module}) +precompile(Tuple{typeof(pyreturn), Nothing}) +precompile(Tuple{typeof(pyreturn), PyObject}) +precompile(Tuple{typeof(pyreturn), Tuple{}}) +precompile(Tuple{typeof(pystr), PyObject}) +precompile(Tuple{typeof(pytype_query), PyObject}) +precompile(Tuple{typeof(pytypeof), PyObject}) +precompile(Tuple{typeof(rem), Int64, PyObject}) +precompile(Tuple{typeof(rem), PyObject, Int64}) +precompile(Tuple{typeof(rem), PyObject, PyObject}) +precompile(Tuple{typeof(set!), PyObject, Int64, Int64}) +precompile(Tuple{typeof(set!), PyObject, Int64, String}) +precompile(Tuple{typeof(set!), PyObject, Tuple{Int64, Int64, Int64}, Int64}) +precompile(Tuple{typeof(set!), PyObject, Tuple{Int64, Int64}, Int64}) +precompile(Tuple{typeof(setdata!), PyArray{Float64, 1}, PyObject}) +precompile(Tuple{typeof(setindex!), Base.RefValue{Union{Nothing, Tuple{PyObject, Int64}}}, Nothing}) +precompile(Tuple{typeof(setindex!), Dict{DataType, String}, String, Type{Ptr{PyObject_struct}}}) +precompile(Tuple{typeof(setindex!), Dict{Symbol, PyObject}, PyObject, Symbol}) +precompile(Tuple{typeof(setproperty!), PyObject, String, Int64}) +precompile(Tuple{typeof(setproperty!), PyObject, Symbol, Int64}) +precompile(Tuple{typeof(size), PyArray{Float64, 2}, Int64}) +precompile(Tuple{typeof(size), PyBuffer, Int64}) +precompile(Tuple{typeof(size), PyBuffer}) +precompile(Tuple{typeof(stride), PyBuffer, Int64}) +precompile(Tuple{typeof(strides), PyBuffer}) +precompile(Tuple{typeof(string), String, PyObject, Vararg{Any}}) +precompile(Tuple{typeof(tuptype), DataType, Bool, Int64}) +precompile(Tuple{typeof(unsafe_convert), Type{Ptr{PyObject_struct}}, Ptr{Nothing}}) +precompile(Tuple{typeof(unsafe_convert), Type{Ptr{PyObject_struct}}, PyObject}) +precompile(Tuple{typeof(unsafe_convert), Type{Ref{Ptr{PyObject_struct}}}, Base.RefValue{Ptr{PyObject_struct}}}) +precompile(Tuple{typeof(unsafe_load), Ptr{Ptr{PyObject_struct}}}) +precompile(Tuple{typeof(weakref_callback), Ptr{PyObject_struct}, Ptr{PyObject_struct}}) +precompile(Tuple{typeof(xor), Int64, PyObject}) +precompile(Tuple{typeof(xor), PyObject, Int64}) +precompile(Tuple{typeof(xor), PyObject, PyObject}) \ No newline at end of file diff --git a/src/pyeval.jl b/src/pyeval.jl index 4eca19d5..a312853f 100644 --- a/src/pyeval.jl +++ b/src/pyeval.jl @@ -232,3 +232,24 @@ macro py_str(code, options...) ret end end + +""" + @pyinclude(filename) + +Execute the Python script in the file `filename` as if +it were in a `py\"\"\" ... \"\"\"` block, e.g. so that +any globals defined in `filename` are available to +subsequent `py"..."` evaluations. + +(Unlike `py"..."`, however, `@pyinclude` does not +interpolate Julia variables into `\$var` expressions — +the `filename` script must be pure Python.) +""" +macro pyinclude(fname) + quote + m = pynamespace($__module__) + fname = $(esc(fname)) + pyeval_(read(fname, String), m, m, Py_file_input, fname) + nothing + end +end diff --git a/src/pyfncall.jl b/src/pyfncall.jl index fc07d8e8..11e81287 100644 --- a/src/pyfncall.jl +++ b/src/pyfncall.jl @@ -99,7 +99,7 @@ macro pycall(ex) end func = ex.args[1].args[1] args, kwargs = ex.args[1].args[2:end], [] - if isexpr(args[1],:parameters) + if !isempty(args) && isexpr(args[1],:parameters) kwargs, args = args[1], args[2:end] end T = ex.args[2] diff --git a/src/pyinit.jl b/src/pyinit.jl index 42a928df..b3371a43 100644 --- a/src/pyinit.jl +++ b/src/pyinit.jl @@ -256,6 +256,15 @@ function __init__() end end + # ensure Jupyter/IJulia flushes I/O streams (issue #912) + if isdefined(Main, :IJulia) && Main.IJulia.inited + Main.IJulia.push_postexecute_hook() do + sys = pyimport("sys") + sys."stdout"."flush"() + sys."stderr"."flush"() + end + end + # Configure finalization steps. # # * In julia/PyCall, `julia` needs to call `Py_Finalize` to diff --git a/src/startup.jl b/src/startup.jl index 1c182c0a..d208040c 100644 --- a/src/startup.jl +++ b/src/startup.jl @@ -73,7 +73,7 @@ else libpy_handle = proc_handle # Now determine the name of the python library that these symbols are from some_address_in_libpython = Libdl.dlsym(libpy_handle, :Py_GetVersion) - some_address_in_main_exe = Libdl.dlsym(proc_handle, Sys.isapple() ? :_mh_execute_header : :main) + some_address_in_main_exe = Libdl.dlsym(proc_handle, Sys.isapple() ? :_mh_execute_header : :_start) dlinfo1 = Ref{Dl_info}() dlinfo2 = Ref{Dl_info}() ccall(:dladdr, Cint, (Ptr{Cvoid}, Ptr{Dl_info}), some_address_in_libpython, diff --git a/test/check_deps_version.jl b/test/check_deps_version.jl index aab41d2d..e2dc339d 100644 --- a/test/check_deps_version.jl +++ b/test/check_deps_version.jl @@ -1,9 +1,16 @@ using Test -const desired_version = VersionNumber(ARGS[1]) +const desired_version_str = ARGS[1] # e.g., "2.7", "3.10.0", "3.x" include("../deps/deps.jl") -@testset "pyversion_build ≈ $desired_version" begin +@testset "pyversion_build ≈ $desired_version_str" begin + v = desired_version_str + while endswith(v, ".x") + v = v[1:end-2] + end + desired_version = VersionNumber(v) @test desired_version.major == pyversion_build.major - @test desired_version.minor == pyversion_build.minor + if desired_version.minor != 0 + @test desired_version.minor == pyversion_build.minor + end if desired_version.patch != 0 @test desired_version.patch == pyversion_build.patch end diff --git a/test/runtests.jl b/test/runtests.jl index 2e826080..1486c480 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,7 @@ using PyCall using PyCall: hasproperty using Test, Dates, Serialization +using REPL # for Docs.doc methods filter(f, itr) = collect(Iterators.filter(f, itr)) filter(f, d::AbstractDict) = Base.filter(f, d) @@ -290,7 +291,7 @@ const PyInt = pyversion < v"3" ? Int : Clonglong end @test convert(BigInt, PyObject(1234)) == 1234 - # hasproperty, getproperty, and propertynames + # hasproperty, getproperty, trygetproperty, and propertynames py""" class A: class B: @@ -302,6 +303,7 @@ const PyInt = pyversion < v"3" ? Int : Clonglong A = py"A" @test hasproperty(A, "B") @test getproperty(A, "B") == py"A.B" + @test PyCall.trygetproperty(A, "C", nothing) === py"None" @test :B in propertynames(A) @static if VERSION >= v"0.7-" @test :D in propertynames(A.B) @@ -391,12 +393,12 @@ const PyInt = pyversion < v"3" ? Int : Clonglong @test !ispynull(pyimport_conda("inspect", "not a conda package")) import Conda if PyCall.conda - # import pyzmq to test PR #294 - let already_installed = "pyzmq" ∈ Conda._installed_packages() - @test !ispynull(pyimport_conda("zmq", "pyzmq")) - @test "pyzmq" ∈ Conda._installed_packages() + # import six to test PR #294 + let already_installed = "six" ∈ Conda._installed_packages() + @test !ispynull(pyimport_conda("six", "six")) + @test "six" ∈ Conda._installed_packages() if !already_installed - Conda.rm("pyzmq") + Conda.rm("six") end end end @@ -529,6 +531,8 @@ const PyInt = pyversion < v"3" ? Int : Clonglong # @pycall macro expands correctly _pycall = GlobalRef(PyCall,:pycall) + @test macroexpand(@__MODULE__, :(@pycall foo()::T)) == :($(_pycall)(foo, T)) + @test macroexpand(@__MODULE__, :(@pycall foo(; kwargs...)::T)) == :($(_pycall)(foo, T; kwargs...)) @test macroexpand(@__MODULE__, :(@pycall foo(bar)::T)) == :($(_pycall)(foo, T, bar)) @test macroexpand(@__MODULE__, :(@pycall foo(bar, args...)::T)) == :($(_pycall)(foo, T, bar, args...)) @test macroexpand(@__MODULE__, :(@pycall foo(bar; kwargs...)::T)) == :($(_pycall)(foo, T, bar; kwargs...)) @@ -617,6 +621,45 @@ const PyInt = pyversion < v"3" ? Int : Clonglong @test_throws ArgumentError float(pybuiltin("type")) end +@testset "deepcopy #757" begin + l = py"[1,2,3]"o + l2 = @test_nowarn deepcopy(l) + @test l == l2 + l2.append(4) + @test l != l2 + @test collect(l2) == [1,2,3,4] + @test collect(l) == [1,2,3] + + obj = py""" + class C757: + def __init__(self, a, b): + self.a = a + self.b = b + """ + obj = py"C757(C757(1,2), C757(3,4))"o + obj2 = @test_nowarn deepcopy(obj) + @test PyPtr(obj) != PyPtr(obj2) # make sure a new Python object is created + @test obj.a.a == obj2.a.a + @test obj.a.b == obj2.a.b + @test obj.b.a == obj2.b.a + @test obj.b.b == obj2.b.b + obj.a = 3 + @test obj.a == 3 + @test obj2.a.a == 1 + @test obj2.a.b == 2 + + struct S;a;b;end + + c = py"C757(1,2)" + obj = S(c, c) + obj2 = @test_nowarn deepcopy(obj) + @test obj.a === obj.b + @test obj2.a === obj2.b + obj.a.a = 4 + @test obj.a.a == 4 + @test obj2.a.a == 1 +end + ###################################################################### #@pydef tests: type declarations need to happen at top level @@ -819,3 +862,37 @@ if lowercase(get(ENV, "JULIA_PKGEVAL", "false")) != "true" include("test_venv.jl") include("test_build.jl") end + +@testset "@pyinclude" begin + mktemp() do path, io + print(io, "foo1 = 1\nbar2 = 2\n") + close(io) + @pyinclude(path) + @test py"foo1" == 1 + @test py"bar2" == 2 + end +end + +@testset "proper exception raised" begin + py""" + class A: + def __getattr__(self, name): + if name == "a": + raise ValueError(name) + else: + raise AttributeError() + + def __setattr__(self, name, value): + if value == 0: + raise ValueError(value) + else: + raise AttributeError() + """ + a = py"A"() + @test_throws PyCall.PyError a.a + @test_throws KeyError a.b + + @test_throws PyCall.PyError a.a = 0 + @test_throws KeyError a.a = 1 +end + diff --git a/test/test_build.jl b/test/test_build.jl index f55102a1..88b7d3ff 100644 --- a/test/test_build.jl +++ b/test/test_build.jl @@ -4,11 +4,11 @@ include(joinpath(dirname(@__FILE__), "..", "deps", "depsutils.jl")) include(joinpath(dirname(@__FILE__), "..", "deps", "buildutils.jl")) using Test +using PyCall: python @testset "find_libpython" begin - for python in ["python", "python2", "python3"] - # TODO: In Windows, word size should also be checked. - Sys.iswindows() && break + # TODO: In Windows, word size should also be checked. + if !Sys.iswindows() if Sys.which(python) === nothing @info "$python not available; skipping test" else @@ -37,7 +37,7 @@ using Test # Test the case `dlopen` failed to open the library. let err, msg @test try - find_libpython("python"; _dlopen = (_...) -> error("dummy")) + find_libpython(python; _dlopen = (_...) -> error("dummy")) false catch err err isa ErrorException diff --git a/test/test_venv.jl b/test/test_venv.jl index 01255462..3d24ceda 100644 --- a/test/test_venv.jl +++ b/test/test_venv.jl @@ -1,5 +1,16 @@ using PyCall, Test +"""Gets temp directory, possibly with user-set environment variable""" +function _mktempdir(f::Function, parent=nothing; kwargs...) + if parent === nothing && haskey(ENV, "_TMP_DIR") + return mktempdir(f, ENV["_TMP_DIR"]; kwargs...) + end + if parent === nothing + parent = tempdir() + end + return mktempdir(f, parent; kwargs...) +end + function test_venv_has_python(path) newpython = PyCall.python_cmd(venv=path).exec[1] @@ -35,7 +46,7 @@ function test_venv_activation(path) # Marking the test broken in Windows. It seems that # venv copies .dll on Windows and libpython check in # PyCall.__init__ detects that. - @test_broken begin + @test begin output = read(jlcmd, String) sys_executable, exec_prefix, mod_file = split(output, "\n") newpython == sys_executable @@ -57,7 +68,7 @@ end elseif Sys.which(pyname) === nothing @info "No $pyname command. Skipping the test..." else - mktempdir() do tmppath + _mktempdir() do tmppath if PyCall.pyversion.major == 2 path = joinpath(tmppath, "kind") else @@ -108,7 +119,7 @@ end elseif !success(PyCall.python_cmd(`-c "import venv"`, python=python)) @info "Skip venv test since venv package is missing." else - mktempdir() do tmppath + _mktempdir() do tmppath if PyCall.pyversion.major == 2 path = joinpath(tmppath, "kind") else