Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
* Comparisons like `==`, `<` and `isless` between `Py`s now return `Bool` instead of `Py`.
* Removed comparisons between `Py` and `Number` (like `Py(3) < 5`).
* Removed arithmetic between `Py` and `Number` (like `Py(2) * 10`).
* Removed unsafe API: `getptr`, `pycopy!`, `pyisnull`, `pynew`, `PyNULL`, `unsafe_pynext`.
A `Py` is now always a valid, fixed, non-NULL Python object in the documented API.
* Python errors no longer automatically set `sys.last_traceback` etc. when displayed from Julia.
* Removed `CONFIG.auto_sys_last_traceback`.
* Changes to `PythonCall.GC` (now more like `Base.GC`):
Expand Down
5 changes: 0 additions & 5 deletions docs/src/pythoncall-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,7 @@ The functions here are not exported. They are mostly unsafe in the sense that yo
crash Julia by using them incorrectly.

```@docs
PythonCall.pynew
PythonCall.pyisnull
PythonCall.pycopy!
PythonCall.getptr
PythonCall.pydel!
PythonCall.unsafe_pynext
```

## NumpyDates
Expand Down
35 changes: 35 additions & 0 deletions docs/src/v1-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,41 @@ between Python and Julia is explicit.
* Instead of `Py(5) * 6` use `Py(5) * Py(6)` or `pymul(Py(5), 6)`.
* Instead of `np.array([1,2,3]) < 3` use `pylt(np.array([1,2,3]), 3)`.

The unsafe API has been removed: `getptr`, `pycopy!`, `pyisnull`, `pynew`, `PyNULL`,
`unsafe_pynext`. This means that a `Py` is immutable and non-NULL in the documented API
for PythonCall (mutability and NULLs are internal implementation details). These functions
were primarily used in packages to have global `Py` objects with this pattern:

```
module Foo
using PythonCall

const np = PythonCall.pynew()

function __init__()
PythonCall.pycopy!(np, pyimport("numpy"))
end
end
```

We have recommended this alternate, safe pattern for a while now:

```
module Foo
using PythonCall

const np = Ref{Py}()

function __init__()
np[] = pyimport("numpy")
end
end
```

* Instead of `PythonCall.pynew()` use `Ref{Py}()`.
* Instead of `PythonCall.pycopy!(x, y)` use `x[] = y`.
* Instead of `PythonCall.unsafe_pynext(x)` (and check for `pyisnull`) use `pynext(x, nothing)` (and check for `nothing`).

When a Python error is displayed in Julia, PythonCall no longer sets `sys.last_traceback`
and friends. This means that the Python post-mortem debugger `pdb.pm()` will no longer
work.
Expand Down
5 changes: 0 additions & 5 deletions src/API/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ function python_library_path end
function python_version end

# Core
function getptr end
function ispy end
function pyabs end
function pyadd end
Expand All @@ -21,7 +20,6 @@ function pycollist end
function pycompile end
function pycomplex end
function pycontains end
function pycopy! end
function pydate end
function pydatetime end
function pydel! end
Expand Down Expand Up @@ -62,7 +60,6 @@ function pyipow end
function pyirshift end
function pyis end
function pyisinstance end
function pyisnull end
function pyissubclass end
function pyisub end
function pyiter end
Expand All @@ -78,7 +75,6 @@ function pymod end
function pymul end
function pyne end
function pyneg end
function pynew end
function pynext end
function pynot end
function pyor end
Expand All @@ -102,7 +98,6 @@ function pytuple end
function pytype end
function pywith end
function pyxor end
function unsafe_pynext end

# Convert
function pyconvert end
Expand Down
6 changes: 0 additions & 6 deletions src/API/publics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,7 @@ if Base.VERSION ≥ v"1.11"

# Core
CONFIG,
getptr,
pycopy!,
pydel!,
pyisnull,
pynew,
PyNULL,
unsafe_pynext,

# Compat
event_loop_off,
Expand Down
7 changes: 1 addition & 6 deletions src/Core/Core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import ..PythonCall:
@pyconst,
@pyeval,
@pyexec,
getptr,
ispy,
Py,
pyabs,
Expand All @@ -53,7 +52,6 @@ import ..PythonCall:
pycomplex,
pycontains,
pyconvert,
pycopy!,
pydate,
pydatetime,
pydel!,
Expand Down Expand Up @@ -95,7 +93,6 @@ import ..PythonCall:
pyirshift,
pyis,
pyisinstance,
pyisnull,
pyissubclass,
pyisub,
pyiter,
Expand All @@ -111,7 +108,6 @@ import ..PythonCall:
pymul,
pyne,
pyneg,
pynew,
pynext,
pynot,
pyor,
Expand All @@ -134,8 +130,7 @@ import ..PythonCall:
pytuple,
pytype,
pywith,
pyxor,
unsafe_pynext
pyxor

export
_base_datetime,
Expand Down
2 changes: 1 addition & 1 deletion src/PythonCall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ include("JlWrap/JlWrap.jl")
include("Compat/Compat.jl")

# non-exported API
using .Core: PyNULL, CONFIG
using .Core: CONFIG

# not API but used in tests
for k in [
Expand Down
24 changes: 12 additions & 12 deletions test/Core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import Markdown
@testset "pyis" begin
x = pylist()
y = PythonCall.pynew(x)
y = PythonCall.Core.pynew(x)
z = pylist()
@test pyis(x, x)
@test pyis(x, y)
Expand Down Expand Up @@ -218,7 +218,7 @@
@test Base.Docs.getdoc(Py(nothing)) isa Markdown.MD
@test Base.Docs.getdoc(Py(12)) isa Markdown.MD
@test Base.Docs.getdoc(pybuiltins.int) isa Markdown.MD
@test Base.Docs.getdoc(PythonCall.PyNULL) === nothing
@test Base.Docs.getdoc(PythonCall.Core.PyNULL) === nothing
end
@testset "comparisons" begin
@testset "Py vs Py" begin
Expand Down Expand Up @@ -255,14 +255,14 @@ end
@test_throws PyException pyiter(pybuiltins.True)
# unsafe_pynext
it = pyiter(pyrange(2))
x = PythonCall.unsafe_pynext(it)
@test !PythonCall.pyisnull(x)
x = PythonCall.Core.unsafe_pynext(it)
@test !PythonCall.Core.pyisnull(x)
@test pyeq(Bool, x, 0)
x = PythonCall.unsafe_pynext(it)
@test !PythonCall.pyisnull(x)
x = PythonCall.Core.unsafe_pynext(it)
@test !PythonCall.Core.pyisnull(x)
@test pyeq(Bool, x, 1)
x = PythonCall.unsafe_pynext(it)
@test PythonCall.pyisnull(x)
x = PythonCall.Core.unsafe_pynext(it)
@test PythonCall.Core.pyisnull(x)
# pynext
it = pyiter(pyrange(2))
x = pynext(it)
Expand Down Expand Up @@ -825,18 +825,18 @@ end
@test showable(MIME("text/plain"), Py(nothing))
@test showable(MIME("text/plain"), Py(12))
# https://github.com/JuliaPy/PythonCall.jl/issues/522
@test showable(MIME("text/plain"), PythonCall.pynew())
@test !showable(MIME("text/html"), PythonCall.pynew())
@test showable(MIME("text/plain"), PythonCall.Core.pynew())
@test !showable(MIME("text/html"), PythonCall.Core.pynew())
end
@testset "show" begin
@test sprint(show, MIME("text/plain"), Py(nothing)) == "Python: None"
@test sprint(show, MIME("text/plain"), Py(12)) == "Python: 12"
# https://github.com/JuliaPy/PythonCall.jl/issues/522
@test sprint(show, MIME("text/plain"), PythonCall.pynew()) == "Python: NULL"
@test sprint(show, MIME("text/plain"), PythonCall.Core.pynew()) == "Python: NULL"
# test compact printing
@test sprint(show, MIME("text/plain"), Py(String('A':'Z')), context=(:compact=>true, :displaysize=>(50, 20))) == "Py: 'ABCDE ... WXYZ'"
@test sprint(show, MIME("text/plain"), Py(String('A':'Z')), context=(:compact=>true, :limit=>false, :displaysize=>(50, 20))) == "Py: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"
@test_throws MethodError sprint(show, MIME("text/html"), PythonCall.pynew())
@test_throws MethodError sprint(show, MIME("text/html"), PythonCall.Core.pynew())
end
end

Expand Down
Loading