From ebecd1747c382a57ad8e47d0e32112cdbd454b40 Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@collabora.com>
Date: Thu, 13 Mar 2025 10:53:42 +0000
Subject: [PATCH] bindings: Use Py_TPFLAGS_MANAGED_WEAKREF if available

This was an attempt to fix dbus-python#55 (it didn't work) but still
seems worth having.

Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 dbus_bindings/conn-internal.h |  2 ++
 dbus_bindings/conn.c          | 14 +++++++++++++-
 dbus_bindings/server.c        | 16 +++++++++++++++-
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/dbus_bindings/conn-internal.h b/dbus_bindings/conn-internal.h
index d333d271..ae47816e 100644
--- a/dbus_bindings/conn-internal.h
+++ b/dbus_bindings/conn-internal.h
@@ -42,8 +42,10 @@ typedef struct {
      */
     PyObject *object_paths;
 
+#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
     /* Weak-references list to make Connections weakly referenceable */
     PyObject *weaklist;
+#endif
 
     dbus_bool_t has_mainloop;
 } Connection;
diff --git a/dbus_bindings/conn.c b/dbus_bindings/conn.c
index 4aa0865e..54efc49b 100644
--- a/dbus_bindings/conn.c
+++ b/dbus_bindings/conn.c
@@ -238,7 +238,9 @@ DBusPyConnection_NewConsumingDBusConnection(PyTypeObject *cls,
     self->has_mainloop = (mainloop != Py_None);
     self->conn = NULL;
     self->filters = PyList_New(0);
+#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
     self->weaklist = NULL;
+#endif
     if (!self->filters) goto err;
     self->object_paths = PyDict_New();
     if (!self->object_paths) goto err;
@@ -392,7 +394,10 @@ static void Connection_tp_dealloc(Connection *self)
     /* avoid clobbering any pending exception */
     PyErr_Fetch(&et, &ev, &etb);
 
-    if (self->weaklist) {
+#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
+    if (self->weaklist)
+#endif
+    {
         PyObject_ClearWeakRefs((PyObject *)self);
     }
 
@@ -455,12 +460,19 @@ PyTypeObject DBusPyConnection_Type = {
     0,                      /*tp_getattro*/
     0,                      /*tp_setattro*/
     0,                      /*tp_as_buffer*/
+#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
+    Py_TPFLAGS_MANAGED_WEAKREF |
+#endif
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
     Connection_tp_doc,      /*tp_doc*/
     0,                      /*tp_traverse*/
     0,                      /*tp_clear*/
     0,                      /*tp_richcompare*/
+#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
+    0,                      /*tp_weaklistoffset*/
+#else
     offsetof(Connection, weaklist),   /*tp_weaklistoffset*/
+#endif
     0,                      /*tp_iter*/
     0,                      /*tp_iternext*/
     DBusPyConnection_tp_methods,  /*tp_methods*/
diff --git a/dbus_bindings/server.c b/dbus_bindings/server.c
index 3591eac4..d250a1db 100644
--- a/dbus_bindings/server.c
+++ b/dbus_bindings/server.c
@@ -38,8 +38,10 @@ typedef struct {
     /* The Connection subtype for which this Server is a factory */
     PyObject *conn_class;
 
+#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
     /* Weak-references list to make server weakly referenceable */
     PyObject *weaklist;
+#endif
 
     PyObject *mainloop;
 } Server;
@@ -423,7 +425,9 @@ Server_tp_new(PyTypeObject *cls, PyObject *args, PyObject *kwargs)
         return NULL;
     }
 
+#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
     ((Server *)self)->weaklist = NULL;
+#endif
     TRACE(self);
 
     return self;
@@ -438,7 +442,10 @@ static void Server_tp_dealloc(Server *self)
     /* avoid clobbering any pending exception */
     PyErr_Fetch(&et, &ev, &etb);
 
-    if (self->weaklist) {
+#if !DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
+    if (self->weaklist)
+#endif
+    {
         PyObject_ClearWeakRefs((PyObject *)self);
     }
 
@@ -570,12 +577,19 @@ PyTypeObject DBusPyServer_Type = {
     0,                      /*tp_getattro*/
     0,                      /*tp_setattro*/
     0,                      /*tp_as_buffer*/
+#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
+    Py_TPFLAGS_MANAGED_WEAKREF |
+#endif
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
     Server_tp_doc,          /*tp_doc*/
     0,                      /*tp_traverse*/
     0,                      /*tp_clear*/
     0,                      /*tp_richcompare*/
+#if DBUSPY_PY_VERSION_AT_LEAST(3, 12, 0, 0)
+    0,                      /*tp_weaklistoffset*/
+#else
     offsetof(Server, weaklist),   /*tp_weaklistoffset*/
+#endif
     0,                      /*tp_iter*/
     0,                      /*tp_iternext*/
     DBusPyServer_tp_methods,/*tp_methods*/
-- 
GitLab