From 8a98fb45ef39d09e11c1270e9120a32df2578d50 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 9 Apr 2021 18:37:32 -0400 Subject: [PATCH 01/47] bump 1.92.3 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 013e8c97..0561b43d 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.92.3" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From f83a11f5aaf26f5036817c45f6d0de505ba30832 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 23 Oct 2021 17:18:05 -0700 Subject: [PATCH 02/47] Revive CI (#930) * Don't test Python 2.7 on macOS * Install libpython2.7 for `find_libpython` * Use 1.7-rc1 instead of nightly in AOT test --- .github/workflows/aot.yml | 8 +++++++- .github/workflows/conda.yml | 3 +++ .github/workflows/system.yml | 17 ++++++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aot.yml b/.github/workflows/aot.yml index ea23d765..b1ce838a 100644 --- a/.github/workflows/aot.yml +++ b/.github/workflows/aot.yml @@ -17,7 +17,10 @@ jobs: - ubuntu-latest architecture: [x64] python-version: ['3.8'] - julia-version: ['1.5', 'nightly'] + julia-version: + - '1.5' + - '~1.7.0-rc1' + # - '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..e16eb193 100644 --- a/.github/workflows/conda.yml +++ b/.github/workflows/conda.yml @@ -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..8caae1a1 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yml @@ -18,13 +18,15 @@ jobs: - macos-latest - windows-latest architecture: [x64] - python-version: ['2.7', '3.8'] + python-version: ['3.8'] julia-version: ['1.0', '1.5', 'nightly'] include: + # 32 bit Windows: - os: windows-latest architecture: x86 python-version: '3.8' julia-version: '1.5' + # Sweep julia-version only on Ubuntu: - os: ubuntu-latest architecture: x64 python-version: '3.7' @@ -37,6 +39,16 @@ jobs: architecture: x64 python-version: '3.8' julia-version: '1.3' + # 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: '2.7' + julia-version: '1.5' + - os: windows-latest + architecture: x64 + python-version: '2.7' + julia-version: '1.5' fail-fast: false name: Test Julia ${{ matrix.julia-version }} @@ -56,6 +68,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: From 1e4a97f22dd8f2ba35b5efa045a3cc70247b347a Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 23 Oct 2021 18:00:10 -0700 Subject: [PATCH 03/47] Update Julia and Python versions in CI (#932) --- .github/workflows/aot.yml | 4 ++-- .github/workflows/conda.yml | 4 ++-- .github/workflows/system.yml | 27 +++++++++++++++------------ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/.github/workflows/aot.yml b/.github/workflows/aot.yml index b1ce838a..c7bb3c7d 100644 --- a/.github/workflows/aot.yml +++ b/.github/workflows/aot.yml @@ -16,9 +16,9 @@ jobs: os: - ubuntu-latest architecture: [x64] - python-version: ['3.8'] + python-version: ['3.10'] julia-version: - - '1.5' + - '1' - '~1.7.0-rc1' # - 'nightly' # TODO: reenable fail-fast: false diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml index e16eb193..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: "" diff --git a/.github/workflows/system.yml b/.github/workflows/system.yml index 8caae1a1..58db4847 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yml @@ -18,37 +18,40 @@ jobs: - macos-latest - windows-latest architecture: [x64] - python-version: ['3.8'] - julia-version: ['1.0', '1.5', 'nightly'] + python-version: ['3.10'] + julia-version: + - '1.0' + - '1' + - 'nightly' include: # 32 bit Windows: - os: windows-latest architecture: x86 - python-version: '3.8' + python-version: '3.9' # 3.10 not available yet? julia-version: '1.5' - # Sweep julia-version only on Ubuntu: + # Sweep python-version and julia-version only on Ubuntu: - os: ubuntu-latest architecture: x64 - python-version: '3.7' - julia-version: '1.5' + python-version: '3.9' + julia-version: '1' - os: ubuntu-latest architecture: x64 - python-version: '3.8' - julia-version: '1.4' + python-version: '3.10' + julia-version: '1.5' - os: ubuntu-latest architecture: x64 - python-version: '3.8' - julia-version: '1.3' + python-version: '3.10' + 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: '2.7' - julia-version: '1.5' + julia-version: '1' - os: windows-latest architecture: x64 python-version: '2.7' - julia-version: '1.5' + julia-version: '1' fail-fast: false name: Test Julia ${{ matrix.julia-version }} From c7b069afcbf63a3c1d39b636c32c7bca6c1ffd37 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 23 Oct 2021 18:27:27 -0700 Subject: [PATCH 04/47] Simplify Python version selection for latest stable (#933) --- .github/workflows/aot.yml | 2 +- .github/workflows/system.yml | 8 ++++---- test/check_deps_version.jl | 13 ++++++++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.github/workflows/aot.yml b/.github/workflows/aot.yml index c7bb3c7d..8fc32fa2 100644 --- a/.github/workflows/aot.yml +++ b/.github/workflows/aot.yml @@ -16,7 +16,7 @@ jobs: os: - ubuntu-latest architecture: [x64] - python-version: ['3.10'] + python-version: ['3.x'] julia-version: - '1' - '~1.7.0-rc1' diff --git a/.github/workflows/system.yml b/.github/workflows/system.yml index 58db4847..360ee9d0 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yml @@ -18,7 +18,7 @@ jobs: - macos-latest - windows-latest architecture: [x64] - python-version: ['3.10'] + python-version: ['3.x'] julia-version: - '1.0' - '1' @@ -27,7 +27,7 @@ jobs: # 32 bit Windows: - os: windows-latest architecture: x86 - python-version: '3.9' # 3.10 not available yet? + python-version: '3.x' julia-version: '1.5' # Sweep python-version and julia-version only on Ubuntu: - os: ubuntu-latest @@ -36,11 +36,11 @@ jobs: julia-version: '1' - os: ubuntu-latest architecture: x64 - python-version: '3.10' + python-version: '3.x' julia-version: '1.5' - os: ubuntu-latest architecture: x64 - python-version: '3.10' + 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: 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 From 4be534b9175e490d84c23a226ad51bf84b0fe267 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sat, 23 Oct 2021 20:40:20 -0500 Subject: [PATCH 05/47] Dict->IdDict in exception types (#927) * Dict->IdDict in exception types Dicts use extensive specialization and this adds latency. IdDicts don't and are the go-to associative container for type-keys. * Rely on `const` to solve inference problems The `::Dict`, being an abstract annotation, wouldn't have been all that much help anyway. --- src/exception.jl | 4 ++-- src/io.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/exception.jl b/src/exception.jl index 7df89269..362719ed 100644 --- a/src/exception.jl +++ b/src/exception.jl @@ -140,7 +140,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 +213,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/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) From 45faa625a94be820f66f44397a76db641b883d5f Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Sun, 24 Oct 2021 03:48:07 +0200 Subject: [PATCH 06/47] typo fix in README.md (#871) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 53ba1866..6fac51be 100644 --- a/README.md +++ b/README.md @@ -298,7 +298,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 From 1743b59258c5d1ef248914b918d050cfb565edce Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sat, 23 Oct 2021 21:52:31 -0400 Subject: [PATCH 07/47] rm arch checks in build script (#906) --- deps/build.jl | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/deps/build.jl b/deps/build.jl index f27c7441..4dd63826 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,19 +64,14 @@ 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) From b845ffbb086baab1bc6066dfa96ec58c1a1fca9d Mon Sep 17 00:00:00 2001 From: vijay Date: Sun, 24 Oct 2021 04:06:58 +0200 Subject: [PATCH 08/47] Fixed typo in fail message for pyimport. (#926) --- src/PyCall.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index 615f1171..42713b9f 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -512,7 +512,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 From cf807f40d47c1147c8a3ee0bef35b40924e502f2 Mon Sep 17 00:00:00 2001 From: miheer vaidya Date: Sat, 23 Oct 2021 20:11:03 -0600 Subject: [PATCH 09/47] Update pkg api to install master version (#914) --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6fac51be..cda1ecf3 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 From 77d144a839f522fb593a7ae48a3f1cfdea319566 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 23 Oct 2021 19:41:58 -0700 Subject: [PATCH 10/47] Update TagBot (#934) --- .github/workflows/TagBot.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 From a399d2dd8e206f13ab2681d48bac6d5d9d728d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1ll=20Haraldsson?= Date: Sun, 24 Oct 2021 02:46:00 +0000 Subject: [PATCH 11/47] Interpolation caveat and typo (#848) --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cda1ecf3..c6c17bea 100644 --- a/README.md +++ b/README.md @@ -364,7 +364,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 @@ -392,7 +393,7 @@ and also by providing more type information to the Julia compiler. * `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. From f77394b7e3ad9ed6b1b82ab4c4cf854ff9e1603e Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 23 Oct 2021 20:01:47 -0700 Subject: [PATCH 12/47] Bump to 1.92.4 (#935) --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 0561b43d..df12e278 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.3" +version = "1.92.4" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 4e5c12cfc597a0e911d42fe661aabd4f1cd74a5f Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 23 Oct 2021 21:13:20 -0700 Subject: [PATCH 13/47] Use latest stable Julia when testing Windows x86 (#936) It looks like #932 forgot to change this. --- .github/workflows/system.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/system.yml b/.github/workflows/system.yml index 360ee9d0..2d6fb420 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yml @@ -28,7 +28,7 @@ jobs: - os: windows-latest architecture: x86 python-version: '3.x' - julia-version: '1.5' + julia-version: '1' # Sweep python-version and julia-version only on Ubuntu: - os: ubuntu-latest architecture: x64 From 5bea9e13e2eb77a78762f64d83ff24f8f43b9362 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 24 Oct 2021 19:21:07 -0700 Subject: [PATCH 14/47] Workaround missing main symbol in Python >= 3.9 (#937) --- src/startup.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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, From 3c66d9ea6d6c2166e11dece15b12335c24648e59 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sun, 24 Oct 2021 19:33:06 -0700 Subject: [PATCH 15/47] Bump to 1.92.5 (#938) --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index df12e278..f2a099e0 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.4" +version = "1.92.5" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 429f2515ec7d34027c32ee1a057b301e4966f403 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Mon, 20 Dec 2021 15:56:52 -0500 Subject: [PATCH 16/47] slight simplification --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c6c17bea..3554b4b4 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,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 From e3e3008ee1b3e449c6382293f58a1f85384beea6 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 21 Dec 2021 08:31:58 -0500 Subject: [PATCH 17/47] add pyinclude macro (#948) --- Project.toml | 2 +- README.md | 7 +++++++ src/PyCall.jl | 2 +- src/pyeval.jl | 21 +++++++++++++++++++++ test/runtests.jl | 10 ++++++++++ 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index f2a099e0..3dea4f2e 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.5" +version = "1.93.0" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" diff --git a/README.md b/README.md index 3554b4b4..d05ee329 100644 --- a/README.md +++ b/README.md @@ -165,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"..."`. @@ -390,6 +392,11 @@ 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"` diff --git a/src/PyCall.jl b/src/PyCall.jl index 42713b9f..c09cc204 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, 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/test/runtests.jl b/test/runtests.jl index 2e826080..4594cc40 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -819,3 +819,13 @@ 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 From c77c20a6e2e9e6a940d49e7f5869beebb9015ddb Mon Sep 17 00:00:00 2001 From: Reno <25192197+singularitti@users.noreply.github.com> Date: Thu, 27 Jan 2022 13:47:17 -0500 Subject: [PATCH 18/47] Remove extra ` in README.md (#962) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d05ee329..fe66f71b 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ this after installing the package, run: ```julia Pkg.add(PackageSpec(name="PyCall", rev="master")) -Pkg.build("PyCall")` +Pkg.build("PyCall") ``` By default on Mac and Windows systems, `Pkg.add("PyCall")` From f0e02f30806e7b794fcd2c4785ecae880b0e7404 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 2 Mar 2022 22:32:02 -0800 Subject: [PATCH 19/47] Fix CI versions (#970) --- .github/workflows/aot.yml | 2 +- .github/workflows/system.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aot.yml b/.github/workflows/aot.yml index 8fc32fa2..e227a659 100644 --- a/.github/workflows/aot.yml +++ b/.github/workflows/aot.yml @@ -19,7 +19,7 @@ jobs: python-version: ['3.x'] julia-version: - '1' - - '~1.7.0-rc1' + - '1.6' # - 'nightly' # TODO: reenable fail-fast: false env: diff --git a/.github/workflows/system.yml b/.github/workflows/system.yml index 2d6fb420..f61f59fc 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yml @@ -48,7 +48,7 @@ jobs: architecture: x64 python-version: '2.7' julia-version: '1' - - os: windows-latest + - os: windows-2019 architecture: x64 python-version: '2.7' julia-version: '1' From 85a11cd3a7aea8d5e8aed5c6f2e3e56b83fcde86 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Thu, 3 Mar 2022 06:52:09 +0000 Subject: [PATCH 20/47] Avoid deprecated BLAS.vendor() in MKL conflict check (#950) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch as suggested by Carsten Bauer in #922. GitHub: Fixes #922. Co-authored-by: Mosè Giordano --- src/numpy.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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[]) From 6b18f387e54b6d5a31b1dd6e65a26c45471c2356 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 2 Mar 2022 23:23:42 -0800 Subject: [PATCH 21/47] Bump to 1.93.1 (#971) --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 3dea4f2e..8eebe6ad 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.93.0" +version = "1.93.1" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 2728e20162db3c90198e2828c40e675924c73528 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 8 Apr 2022 18:00:08 -0400 Subject: [PATCH 22/47] flush Python I/O in IJulia (#982) --- src/pyinit.jl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pyinit.jl b/src/pyinit.jl index 42a928df..26945c88 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) && 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 From b27bd5a9ecabec4a30ba6062c3754768746e3adb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1ll=20Haraldsson?= Date: Tue, 19 Apr 2022 22:45:52 +0000 Subject: [PATCH 23/47] Python 3.10 is latest (#986) I noticed Python 3.6 is EOLed, and was thinking you may not want say you support it (I didn't locate it), nor test it(?) to not waste resources (nor 2.7?). Maybe default to latest version, for Conda/Windows downloads, so people can profit from latest featuers? I'm not sure, but it seems 2.7 is still tested... --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fe66f71b..9300647c 100644 --- a/README.md +++ b/README.md @@ -53,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 From d5d3d07a91b2670b14e7d194c004aea235266477 Mon Sep 17 00:00:00 2001 From: James Hu Date: Sat, 20 Aug 2022 06:47:45 -0700 Subject: [PATCH 24/47] Add PyQt6 and PySide6 support to pygui (#1002) --- src/gui.jl | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) 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 From ddb54a83b272fa63b9aacacddbac799e9cd869a3 Mon Sep 17 00:00:00 2001 From: Alexander Plavin Date: Mon, 22 Aug 2022 15:34:01 +0300 Subject: [PATCH 25/47] fix getproperty exceptions (#997) * raise proper exception in getproperty * Update src/PyCall.jl * Update src/PyCall.jl * whoops * also fix setproperty * Update src/PyCall.jl * Update src/PyCall.jl * Update src/PyCall.jl * Update src/PyCall.jl Co-authored-by: Steven G. Johnson --- src/PyCall.jl | 22 +++++++++++++++------- test/runtests.jl | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index c09cc204..7f0317ec 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -298,7 +298,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 @@ -327,15 +333,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} diff --git a/test/runtests.jl b/test/runtests.jl index 4594cc40..e16b31ae 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -829,3 +829,26 @@ end @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 From 94a77bf8d0af8de1cbed32447051908b02b4d360 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Mon, 22 Aug 2022 08:34:53 -0400 Subject: [PATCH 26/47] tag 1.94 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 8eebe6ad..84293fc0 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.93.1" +version = "1.94.0" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 56b3ffafcc4d9a4aaa097cebb0fb98f208e51def Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Mon, 22 Aug 2022 11:21:00 -0400 Subject: [PATCH 27/47] whoops --- src/pyinit.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pyinit.jl b/src/pyinit.jl index 26945c88..b3371a43 100644 --- a/src/pyinit.jl +++ b/src/pyinit.jl @@ -257,7 +257,7 @@ function __init__() end # ensure Jupyter/IJulia flushes I/O streams (issue #912) - if isdefined(Main, :IJulia) && IJulia.inited + if isdefined(Main, :IJulia) && Main.IJulia.inited Main.IJulia.push_postexecute_hook() do sys = pyimport("sys") sys."stdout"."flush"() From 9f22684ab26231b1fba66d998e1fc25887f67ed5 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Mon, 22 Aug 2022 11:22:28 -0400 Subject: [PATCH 28/47] tag bugfix --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 84293fc0..74aca7a5 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.94.0" +version = "1.94.1" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 38b1061d3e54cebea53b74ec0668d9cfaeecaf1c Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Sat, 3 Dec 2022 20:14:36 -0500 Subject: [PATCH 29/47] Fix unittests on Windows (#1016) * Attempt to fix temp dirs on windows * Fix call to `_mktempdir` in venv test * Change to normal `@test` --- .github/workflows/system.yml | 6 ++++++ test/test_venv.jl | 17 ++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/workflows/system.yml b/.github/workflows/system.yml index f61f59fc..ec3fc7f5 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yml @@ -85,6 +85,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/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 From ddfd3ea13084d2b632ea08233c8b8c130464f015 Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Thu, 5 Jan 2023 11:16:45 -0500 Subject: [PATCH 30/47] Expand precompilation (#1015) * Create expanded precompilation * Expand conversions for precompile * Precompile more types * Add calls from running `runtests.jl` * Remove overly-specific precompile statements * `Core.TypeofVarargs` requires newer Julia * Require Julia >= 1.4 * Remove Julia 1.0 test --- .github/workflows/system.yml | 1 - Project.toml | 2 +- src/PyCall.jl | 12 +- src/precompile.jl | 531 +++++++++++++++++++++++++++++++++++ 4 files changed, 534 insertions(+), 12 deletions(-) create mode 100644 src/precompile.jl diff --git a/.github/workflows/system.yml b/.github/workflows/system.yml index ec3fc7f5..fefb6b4a 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yml @@ -20,7 +20,6 @@ jobs: architecture: [x64] python-version: ['3.x'] julia-version: - - '1.0' - '1' - 'nightly' include: diff --git a/Project.toml b/Project.toml index 74aca7a5..edd786b7 100644 --- a/Project.toml +++ b/Project.toml @@ -16,7 +16,7 @@ VersionParsing = "81def892-9a0e-5fdd-b105-ffc91e053289" Conda = "1.0" MacroTools = "0.4, 0.5" VersionParsing = "1.0" -julia = "0.7, 1.0" +julia = "1.4" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/src/PyCall.jl b/src/PyCall.jl index 7f0317ec..ad3d754c 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -980,16 +980,8 @@ 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. -precompile(pyjlwrap_call, (PyPtr,PyPtr,PyPtr)) -precompile(pyjlwrap_dealloc, (PyPtr,)) -precompile(pyjlwrap_repr, (PyPtr,)) -precompile(pyjlwrap_hash, (PyPtr,)) -precompile(pyjlwrap_hash32, (PyPtr,)) - -# TODO: precompilation of the io.jl functions +include("precompile.jl") +######################################################################### end # module PyCall 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 From cedc1cc910a613b075b03508b4c7cff3f321ae5b Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 5 Jan 2023 11:18:23 -0500 Subject: [PATCH 31/47] tag 1.94.2 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index edd786b7..e058d226 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.94.1" +version = "1.94.2" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 9bd09080cee34b356c80238d6fb87eb356917a4b Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 5 Jan 2023 17:29:54 -0500 Subject: [PATCH 32/47] tag 1.95.0 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index e058d226..b2f641f3 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.94.2" +version = "1.95.0" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From d1764a6c8df2f9614ed042814a4deb9019b33eb1 Mon Sep 17 00:00:00 2001 From: Luke Decker Date: Mon, 9 Jan 2023 12:09:33 -0600 Subject: [PATCH 33/47] unit test for trygetproperty (#1007) --- test/runtests.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index e16b31ae..5cc1b5ce 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -290,7 +290,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 +302,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) From 3b0a0f4e095cdd882c2c730464f1e6660718fd62 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Mon, 9 Jan 2023 13:12:13 -0500 Subject: [PATCH 34/47] type-stable PyError constructor (#1022) * fix test_build to use PyCall's python * type-stable PyError constructor --- src/PyCall.jl | 8 ++++---- src/exception.jl | 26 +++++++++++++++++--------- test/test_build.jl | 8 ++++---- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index ad3d754c..0c155fef 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -299,7 +299,7 @@ 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) if p == C_NULL && pyerr_occurred() - e = pyerror("PyObject_GetAttrString") + e = PyError("PyObject_GetAttrString") if PyPtr(e.T) != @pyglobalobjptr(:PyExc_AttributeError) throw(e) end @@ -336,7 +336,7 @@ function _setproperty!(o::PyObject, s::Union{Symbol,AbstractString}, 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") + e = PyError("PyObject_SetAttrString") if PyPtr(e.T) != @pyglobalobjptr(:PyExc_AttributeError) throw(e) end @@ -507,7 +507,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 = """ @@ -553,7 +553,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 diff --git a/src/exception.jl b/src/exception.jl index 362719ed..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") 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 From e3794994c7ae90feffe1e0e5d7d5e2d6007ccc03 Mon Sep 17 00:00:00 2001 From: szcf-weiya Date: Mon, 9 Jan 2023 16:52:50 -0500 Subject: [PATCH 35/47] fix BoundsError of args[1] when args is empty (#1014) * fix BoundsError of args[1] when args is empty if `args` on L101 is empty, then `args[1]` in `isexpr()` would throw `BoundsError: attempt to access 0-element Vector{Any} at index [1]` * add unit tests for empty arguments * Update src/pyfncall.jl * Update src/pyfncall.jl Co-authored-by: Steven G. Johnson --- src/pyfncall.jl | 2 +- test/runtests.jl | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) 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/test/runtests.jl b/test/runtests.jl index 5cc1b5ce..2e5c915a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -530,6 +530,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...)) From bcaba00d1e2c412b2f61d33343ef5a9ab1b9258a Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Mon, 9 Jan 2023 16:53:29 -0500 Subject: [PATCH 36/47] tag 1.95.1 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index b2f641f3..54ae595e 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.95.0" +version = "1.95.1" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From b5da159a55dfca2ffda7d4f52aef6972b95b0844 Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Fri, 16 Jun 2023 16:31:33 -0400 Subject: [PATCH 37/47] Urgent: add option to disable numpy install / prevent corruption of conda-forge environments (#1040) * Option to disable numpy install * Bump version with numpy install fix * Use `satisfied_skip_solve` in `Conda.add` --- Project.toml | 4 ++-- deps/build.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 54ae595e..f2462d16 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.95.1" +version = "1.95.2" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" @@ -13,7 +13,7 @@ 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 = "1.4" diff --git a/deps/build.jl b/deps/build.jl index 4dd63826..52b970c8 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -76,7 +76,7 @@ try # make sure deps.jl file is removed on error 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) From c12d6d7da4116d8231c57e349a469567f14f362c Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Wed, 21 Jun 2023 18:01:37 +0200 Subject: [PATCH 38/47] disable deepcopy on PyObject #757 (#1039) * disable deepcopy on PyObject #757 * Update src/PyCall.jl Co-authored-by: Steven G. Johnson * fix deepcopy and add tests * add another deepcopy test * v1.95.2 * Update Project.toml * Update test/runtests.jl --------- Co-authored-by: Steven G. Johnson --- Project.toml | 2 +- src/PyCall.jl | 10 ++++++++++ test/runtests.jl | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index f2462d16..133a026d 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.95.2" +version = "1.96.0" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" diff --git a/src/PyCall.jl b/src/PyCall.jl index 0c155fef..182abb13 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -979,6 +979,16 @@ include("serialize.jl") include("pyinit.jl") +const _deepcopy = PyNULL() + +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 + ######################################################################### include("precompile.jl") diff --git a/test/runtests.jl b/test/runtests.jl index 2e5c915a..b718ee23 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -620,6 +620,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 = 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 = 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 = 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 @@ -855,3 +894,4 @@ end @test_throws PyCall.PyError a.a = 0 @test_throws KeyError a.a = 1 end + From 0b300006b8e814f07bcb4821fe8b988879b675ca Mon Sep 17 00:00:00 2001 From: Alexander Seiler Date: Wed, 28 Jun 2023 02:47:41 +0200 Subject: [PATCH 39/47] Fix typo (#1032) Signed-off-by: Alexander Seiler --- deps/find_libpython.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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: From 2a9f07725b1bce8c07ac5437d66701dd9579a221 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 28 Jun 2023 02:48:10 +0200 Subject: [PATCH 40/47] fix depwarn (#1042) * fix depwarn * bump version --- Project.toml | 2 +- src/PyCall.jl | 2 +- test/runtests.jl | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index 133a026d..413c2820 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.96.0" +version = "1.96.1" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" diff --git a/src/PyCall.jl b/src/PyCall.jl index 182abb13..f1987a29 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -983,7 +983,7 @@ const _deepcopy = PyNULL() function Base.deepcopy_internal(obj::PyObject, stackdict::Base.IdDict) haskey(stackdict, obj) && return stackdict[obj] - ispynull(_deepcopy) && copy!(_deepcopy, pyimport("copy")["deepcopy"]) + ispynull(_deepcopy) && copy!(_deepcopy, pyimport("copy")."deepcopy") ret = pycall(_deepcopy, PyObject, obj) stackdict[obj] = ret ret diff --git a/test/runtests.jl b/test/runtests.jl index b718ee23..96dc4fa3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -622,7 +622,7 @@ end @testset "deepcopy #757" begin l = py"[1,2,3]"o - l2 = deepcopy(l) + l2 = @test_nowarn deepcopy(l) @test l == l2 l2.append(4) @test l != l2 @@ -636,7 +636,7 @@ end self.b = b """ obj = py"C757(C757(1,2), C757(3,4))"o - obj2 = deepcopy(obj) + 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 @@ -651,7 +651,7 @@ end c = py"C757(1,2)" obj = S(c, c) - obj2 = deepcopy(obj) + obj2 = @test_nowarn deepcopy(obj) @test obj.a === obj.b @test obj2.a === obj2.b obj.a.a = 4 From 04c477858b84c1a2dfcf450d0250f3527b56035b Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 30 Oct 2023 17:06:43 -0400 Subject: [PATCH 41/47] A few fixes for julia master (#1059) * Fix breakage due to JuliaLang/julia#51319 `cconvert` does not return an array anymore and cannot be used with `reinterpret`. Fix to use the underlying `transcode` function directly, which is also consistent with the `Cstring` version. * Fix doc test --- Project.toml | 3 ++- deps/depsutils.jl | 6 ++++-- test/runtests.jl | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index 413c2820..565f73fb 100644 --- a/Project.toml +++ b/Project.toml @@ -20,6 +20,7 @@ julia = "1.4" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [targets] -test = ["Test"] +test = ["Test", "REPL"] 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/test/runtests.jl b/test/runtests.jl index 96dc4fa3..bc124a52 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) From 69f915709c977a38c05261ab2c2aa8c6e2768ebe Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Wed, 8 Nov 2023 02:18:45 +0100 Subject: [PATCH 42/47] new release (#1062) --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 565f73fb..e4d85067 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.96.1" +version = "1.96.2" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 3df5c48cdbb0c21b748bc12dbfd4e8fdd8e7ca30 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 8 Nov 2023 11:11:32 -0500 Subject: [PATCH 43/47] version stdlibs (#1063) * version stdlibs, which requires Julia 1.6 * try with Julia 1.4 * use "six" not "pyzmq" to test pyimport_conda * whoops --- Project.toml | 5 +++++ test/runtests.jl | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index e4d85067..3939e35d 100644 --- a/Project.toml +++ b/Project.toml @@ -16,7 +16,12 @@ VersionParsing = "81def892-9a0e-5fdd-b105-ffc91e053289" Conda = "1.9" MacroTools = "0.4, 0.5" VersionParsing = "1.0" + julia = "1.4" +Dates = "1.4" +Libdl = "1.4" +LinearAlgebra = "1.4" +Serialization = "1.4" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/test/runtests.jl b/test/runtests.jl index bc124a52..1486c480 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -393,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 From 9decc34d4f3f3aa5fa1af746b7c05be611b28d37 Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Tue, 5 Dec 2023 21:39:41 -0500 Subject: [PATCH 44/47] Fix the stdlib compat entries (#1065) --- Project.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Project.toml b/Project.toml index 3939e35d..a376f77d 100644 --- a/Project.toml +++ b/Project.toml @@ -18,10 +18,10 @@ MacroTools = "0.4, 0.5" VersionParsing = "1.0" julia = "1.4" -Dates = "1.4" -Libdl = "1.4" -LinearAlgebra = "1.4" -Serialization = "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" From d407513e667d259881fe04667fd74a8bb098253d Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 5 Dec 2023 21:43:19 -0500 Subject: [PATCH 45/47] bump to 1.96.3 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index a376f77d..b3cef1f2 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.96.2" +version = "1.96.3" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 790e62f8bfaeb17209ece53cc353b49b10b0e06f Mon Sep 17 00:00:00 2001 From: Miles Cranmer Date: Sat, 16 Dec 2023 08:02:58 -0600 Subject: [PATCH 46/47] Rename `distutils.sysconfig` to `sysconfig` (#1068) * Rename `distutils.sysconfig` to `sysconfig` - Required for Python 3.12 as distutils is removed. * Fallback to `distutils.sysconfig` --- deps/buildutils.jl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 From e54c4ee3962f423a4c77fbc8afc20f5fb66296c3 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Sat, 16 Dec 2023 09:03:58 -0500 Subject: [PATCH 47/47] bump to 1.96.4 (#1070) --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index b3cef1f2..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.96.3" +version = "1.96.4" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"