From c2877c80530646a5f3e4b679c9bcf347a1acf362 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sun, 11 Jan 2026 20:48:06 -0500 Subject: [PATCH] Replace deprecated PyWeakref_GetObject with PyWeakref_GetRef (closes #191) PyWeakref_GetObject was deprecated in Python 3.13 and will be removed in 3.15. The new PyWeakref_GetRef API returns a strong reference directly and uses integer return codes for error handling. Co-Authored-By: Claude Opus 4.5 --- src/PythonObjectCache.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/PythonObjectCache.cpp b/src/PythonObjectCache.cpp index b280eb2..4d3e453 100644 --- a/src/PythonObjectCache.cpp +++ b/src/PythonObjectCache.cpp @@ -36,15 +36,17 @@ void PythonObjectCache::registerObject(uint64_t serial, PyObject* weakref) { PyObject* PythonObjectCache::lookup(uint64_t serial) { if (serial == 0) return nullptr; - - // No mutex needed for read - GIL protects PyWeakref_GetObject + + // No mutex needed for read - GIL protects PyWeakref_GetRef auto it = cache.find(serial); if (it != cache.end()) { - PyObject* obj = PyWeakref_GetObject(it->second); - if (obj && obj != Py_None) { - Py_INCREF(obj); + PyObject* obj = nullptr; + int result = PyWeakref_GetRef(it->second, &obj); + if (result == 1 && obj) { + // obj is already a strong reference from PyWeakref_GetRef return obj; } + // result == 0: dead reference, result == -1: error } return nullptr; } @@ -62,14 +64,18 @@ void PythonObjectCache::remove(uint64_t serial) { void PythonObjectCache::cleanup() { std::lock_guard lock(serial_mutex); - + auto it = cache.begin(); while (it != cache.end()) { - PyObject* obj = PyWeakref_GetObject(it->second); - if (!obj || obj == Py_None) { + PyObject* obj = nullptr; + int result = PyWeakref_GetRef(it->second, &obj); + if (result <= 0) { + // Dead reference or error - remove from cache Py_DECREF(it->second); it = cache.erase(it); } else { + // Still alive - release the strong reference we obtained + Py_DECREF(obj); ++it; } }