@@ -74,45 +74,72 @@ typedef _object PyObject;
7474 */
7575class JPPyObject
7676{
77- /* * Create a new reference to a Python object.
78- *
79- * @param obj is the python object.
80- */
77+ /* *
78+ * Creates a new reference to a Python object.
79+ *
80+ * This constructor takes ownership of the provided Python object reference.
81+ * If the object is not null, the reference count is incremented to ensure
82+ * the object remains valid for the lifetime of the `JPPyObject` instance.
83+ *
84+ * @param obj A pointer to the Python object (`PyObject*`). May be null.
85+ */
8186 explicit JPPyObject (PyObject* obj);
8287
8388public:
84-
8589 /* *
86- * This policy is used if we need to hold a reference to an existing
87- * object for some duration. The object may be null.
90+ * Creates a strong reference to an existing Python object for a limited duration.
91+ *
92+ * This policy is used when the caller needs to temporarily manage an existing
93+ * Python object. It can be applied to both existing references and "borrowed"
94+ * references returned by Python methods.
95+ *
96+ * If the object is not null, its reference count is incremented upon creation
97+ * and decremented when the `JPPyObject` instance is destroyed.
8898 *
89- * Increment reference count if not null, and decrement when done.
99+ * @param obj A pointer to the Python object (`PyObject*`). Must not be null.
100+ * @return A `JPPyObject` instance managing the provided reference.
101+ * @throws std::runtime_error if the object is null.
90102 */
91103 static JPPyObject use (PyObject* obj);
92104
93105 /* *
94- * This policy is used when we are given a new reference that we must
95- * destroy. This will steal a reference.
106+ * Unconditionally takes ownership of a new Python object reference.
96107 *
97- * claim reference, and decremented when done. Clears errors if NULL.
108+ * This policy is used when the caller is responsible for managing a new
109+ * Python object reference and transfers ownership to the `JPPyObject` instance.
110+ * If the object is null, any existing Python errors are cleared. The caller
111+ * must ensure the reference is valid before using this method.
112+ *
113+ * @param obj A pointer to the Python object (`PyObject*`). May be null.
114+ * @return A `JPPyObject` instance managing the provided reference.
98115 */
99116 static JPPyObject accept (PyObject* obj);
100117
101118 /* *
102- * This policy is used when we are given a new reference that we must
103- * destroy. This will steal a reference.
119+ * Takes ownership of a new Python object reference, ensuring it is not null.
120+ *
121+ * This policy is used when the caller is responsible for managing a new
122+ * Python object reference and transfers ownership to the `JPPyObject` instance.
123+ * If the object is null, an exception is thrown.
104124 *
105- * Assert not null, claim reference, and decremented when done.
106- * Will throw an exception in the object is null.
125+ * @param obj A pointer to the Python object (`PyObject*`). Must not be null.
126+ * @return A `JPPyObject` instance managing the provided reference.
127+ * @throws std::runtime_error if the object is null.
107128 */
108129 static JPPyObject claim (PyObject* obj);
109130
110131 /* *
111- * This policy is used when we are capturing an object returned from a python
112- * call that we are responsible for. This will steal a reference.
132+ * Captures and takes ownership of a Python object returned from a Python call.
133+ *
134+ * This policy is used when the caller is responsible for managing a Python
135+ * object returned from a Python call. Ownership of the reference is transferred
136+ * to the `JPPyObject` instance. Before claiming the reference, this method
137+ * first checks for Python errors and then ensures the object is not null.
138+ * If an error occurs or the object is null, an exception is thrown.
113139 *
114- * Check for errors, assert not null, then claim.
115- * Will throw an exception an error occurs.
140+ * @param obj A pointer to the Python object (`PyObject*`). Must not be null.
141+ * @return A `JPPyObject` instance managing the provided reference.
142+ * @throws std::runtime_error if the object is null or if a Python error occurs.
116143 */
117144 static JPPyObject call (PyObject* obj);
118145
@@ -127,13 +154,23 @@ class JPPyObject
127154 JPPyObject& operator =(const JPPyObject& o);
128155
129156 /* *
130- * Keep an object by creating a reference.
157+ * Transfers ownership of the Python object reference.
131158 *
132- * This should only appear in the return statement in the cpython module.
133- * The reference must not be null. Keep invalidates this handle from any
134- * further use as you were supposed to have called return .
159+ * This method is used to transfer control of an existing reference, such as:
160+ * - Returning a reference from a function.
161+ * - Passing a reference to a Python method that steals ownership of the reference .
135162 *
136- * @return the pointer to the Python object.
163+ * Important Notes:
164+ * - The reference must not be null. If the reference is null, this method will raise
165+ * a SystemError exception.
166+ * - Calling `keep()` invalidates this handle, meaning the `JPPyObject` instance
167+ * should no longer be used after calling this method.
168+ * - This method does NOT increment the reference counter. Instead, it transfers
169+ * ownership of the existing reference to the caller. The caller is responsible
170+ * for managing the reference lifecycle (e.g., calling `Py_DECREF` when appropriate).
171+ *
172+ * @return A pointer to the Python object (`PyObject*`).
173+ * @throws PyExc_SystemError if the reference is null.
137174 */
138175 PyObject* keep ();
139176
@@ -153,6 +190,15 @@ class JPPyObject
153190 return m_PyObject;
154191 }
155192
193+ /* * Determine if this python reference is valid.
194+ *
195+ * @returns true if is a valid reference.
196+ */
197+ bool isValid () const
198+ {
199+ return m_PyObject != nullptr ;
200+ }
201+
156202 /* * Determine if this python reference is null.
157203 *
158204 * @returns true if null.
0 commit comments