11incref (x:: C.PyPtr ) = (C. Py_IncRef (x); x)
22decref (x:: C.PyPtr ) = (C. Py_DecRef (x); x)
33
4+ """
5+ ispy(x)
6+
7+ True if `x` is a Python object.
8+
9+ This includes `Py` and Python wrapper types such as `PyList`.
10+ """
411ispy (x) = false
5- ispynull (x) = getptr (x) == C. PyNULL
12+ export ispy
13+
14+ """
15+ pyisnull(x)
16+
17+ True if the Python object `x` is NULL.
18+ """
19+ pyisnull (x) = getptr (x) == C. PyNULL
20+
21+ """
22+ getptr(x)
23+
24+ Get the underlying pointer from the Python object `x`.
25+ """
626getptr (x) = getptr (getpy (x):: Py )
7- export ispy, ispynull
827
928"""
1029 Py(x)
@@ -33,6 +52,17 @@ setptr!(x::Py, ptr::C.PyPtr) = (setfield!(x, :ptr, ptr); x)
3352
3453const PYNULL_CACHE = Py[]
3554
55+ """
56+ pynew([ptr])
57+
58+ A new `Py` representing the Python object at `ptr` (NULL by default).
59+
60+ If `ptr` is given and non-NULL, this function steals a reference to the Python object it
61+ points at, i.e. the new `Py` object owns a reference.
62+
63+ Note that NULL Python objects are not safe in the sense that most API functions will probably
64+ crash your Julia session if you pass a NULL argument.
65+ """
3666pynew () =
3767 if isempty (PYNULL_CACHE)
3868 Py (Val (:new ), C. PyNULL)
@@ -44,9 +74,37 @@ const PyNULL = pynew()
4474
4575pynew (ptr:: C.PyPtr ) = setptr! (pynew (), ptr)
4676
47- # assumes dst is NULL
77+ """
78+ pycopy!(dst::Py, src)
79+
80+ Copy the Python object `src` into `dst`, so that they both represent the same object.
81+
82+ This function exists to support module-level constant Python objects. It is illegal to call
83+ most PythonCall API functions at the top level of a module (i.e. before `__init__()` has run)
84+ so you cannot do `const x = pything()` at the top level. Instead do `const x = pynew()` at
85+ the top level then `pycopy!(x, pything())` inside `__init__()`.
86+
87+ Assumes `dst` is NULL, otherwise a memory leak will occur.
88+ """
4889pycopy! (dst, src) = setptr! (dst, incref (getptr (src)))
4990
91+ """
92+ pydel!(x::Py)
93+
94+ Delete the Python object `x`.
95+
96+ DANGER! Use this function ONLY IF the Julia object `x` could have been garbage-collected
97+ anyway, i.e. was about to become unreachable. This means you MUST KNOW that no other part of
98+ the program has the Julia object `x`.
99+
100+ This decrements the reference count, sets the pointer to NULL and appends `x` to a cache
101+ of unused objects (`PYNULL_CACHE`).
102+
103+ This is an optimization to avoid excessive allocation and deallocation in Julia, which can
104+ be a significant source of slow-down in code which uses a lot of Python objects. It allows
105+ `pynew()` to pop an item from `PYNULL_CACHE` instead of allocating one, and avoids calling
106+ the relatively slow finalizer on `x`.
107+ """
50108function pydel! (x:: Py )
51109 ptr = getptr (x)
52110 if ptr != C. PyNULL
@@ -61,8 +119,6 @@ function pystolen!(x::Py)
61119 nothing
62120end
63121
64- export pynull, pynew, pydel!, pystolen!
65-
66122macro autopy (args... )
67123 vs = args[1 : end - 1 ]
68124 ts = [Symbol (v, " _" ) for v in vs]
@@ -94,7 +150,7 @@ Py(x::Time) = pytime(x)
94150Py (x:: DateTime ) = pydatetime (x)
95151Py (x) = ispy (x) ? Py (getpy (x)) : pyjl (x)
96152
97- Base. string (x:: Py ) = ispynull (x) ? " <py NULL>" : pystr (String, x)
153+ Base. string (x:: Py ) = pyisnull (x) ? " <py NULL>" : pystr (String, x)
98154Base. print (io:: IO , x:: Py ) = print (io, string (x))
99155
100156function Base. repr (x:: Py )
124180
125181function Base. show (io:: IO , mime:: MIME"text/plain" , o:: Py )
126182 hasprefix = get (io, :typeinfo , Any) != Py
127- if ispynull (o)
183+ if pyisnull (o)
128184 if hasprefix
129185 printstyled (io, " Python NULL" , bold= true )
130186 else
@@ -261,7 +317,7 @@ Base.IteratorSize(::Type{Py}) = Base.SizeUnknown()
261317
262318function Base. iterate (x:: Py , it:: Py = pyiter (x))
263319 v = unsafe_pynext (it)
264- if ispynull (v)
320+ if pyisnull (v)
265321 pydel! (it)
266322 nothing
267323 else
0 commit comments