From: Claude Code <noreply@anthropic.com>
Date: $(date -R)
Subject: [PATCH] Fix sip4 compatibility with Python 3.11+

diff --git a/siplib/descriptors.c b/siplib/descriptors.c
index e6008167..79e09bf5 100644
--- siplib/descriptors.c
+++ siplib/descriptors.c
@@ -111,6 +111,12 @@ PyTypeObject sipMethodDescr_Type = {
 #if PY_VERSION_HEX >= 0x03080000
     0,                      /* tp_vectorcall */
 #endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_versions_used */
+#endif
 };
 
 
@@ -323,6 +329,12 @@ PyTypeObject sipVariableDescr_Type = {
 #if PY_VERSION_HEX >= 0x03080000
     0,                      /* tp_vectorcall */
 #endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_versions_used */
+#endif
 };
 
 
diff --git a/siplib/qtlib.c b/siplib/qtlib.c
index e166529f..eb7877f7 100644
--- siplib/qtlib.c
+++ siplib/qtlib.c
@@ -133,10 +133,27 @@ PyObject *sip_api_invoke_slot_ex(const sipSlot *slot, PyObject *sigargs,
     }
     else if (slot -> weakSlot == NULL)
         sref = NULL;
+#if PY_VERSION_HEX >= 0x030d0000
+    else
+    {
+        /* PyWeakref_GetRef returns 1 if alive, 0 if dead, -1 on error */
+        int rc = PyWeakref_GetRef(slot->weakSlot, &sref);
+        if (rc < 0)
+            return NULL;  /* Error */
+        if (rc == 0)
+        {
+            /* Referent is dead, treat as Py_None */
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+        /* rc == 1: sref now holds a strong reference */
+    }
+#else
     else if ((sref = PyWeakref_GetObject(slot -> weakSlot)) == NULL)
         return NULL;
     else
         Py_INCREF(sref);
+#endif
 
     if (sref == Py_None)
     {
diff --git a/siplib/siplib.c b/siplib/siplib.c
index db52b68b..2bb7795a 100644
--- siplib/siplib.c
+++ siplib/siplib.c
@@ -124,6 +124,12 @@ static PyTypeObject sipWrapperType_Type = {
 #if PY_VERSION_HEX >= 0x03080000
     0,                      /* tp_vectorcall */
 #endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_versions_used */
+#endif
 };
 
 
@@ -202,6 +208,9 @@ static sipWrapperType sipWrapper_Type = {
             0,              /* am_await */
             0,              /* am_aiter */
             0,              /* am_anext */
+#if PY_VERSION_HEX >= 0x030d0000
+            0,              /* am_send */
+#endif
         },
 #endif
         {
@@ -300,6 +309,9 @@ static sipWrapperType sipWrapper_Type = {
 #if PY_VERSION_HEX >= 0x03090000
         0,                  /* ht_module */
 #endif
+#if PY_VERSION_HEX >= 0x030d0000
+        0,                  /* _ht_tpname */
+#endif
 #if !defined(STACKLESS)
     },
 #endif
@@ -828,6 +840,12 @@ static PyTypeObject sipEnumType_Type = {
 #if PY_VERSION_HEX >= 0x03080000
     0,                      /* tp_vectorcall */
 #endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_versions_used */
+#endif
 };
 
 
@@ -11587,6 +11605,9 @@ sipWrapperType sipSimpleWrapper_Type = {
             0,              /* am_await */
             0,              /* am_aiter */
             0,              /* am_anext */
+#if PY_VERSION_HEX >= 0x030d0000
+            0,              /* am_send */
+#endif
         },
 #endif
         {
@@ -11685,6 +11706,9 @@ sipWrapperType sipSimpleWrapper_Type = {
 #if PY_VERSION_HEX >= 0x03090000
         0,                  /* ht_module */
 #endif
+#if PY_VERSION_HEX >= 0x030d0000
+        0,                  /* _ht_tpname */
+#endif
 #if !defined(STACKLESS)
     },
 #endif
@@ -13747,7 +13771,15 @@ static struct _frame *sip_api_get_frame(int depth)
 
     while (frame != NULL && depth > 0)
     {
+#if PY_VERSION_HEX >= 0x030b0000
+        /* Python 3.11+: PyEval_GetFrame and PyFrame_GetBack return strong refs */
+        struct _frame *back = PyFrame_GetBack(frame);
+        Py_XDECREF(frame);
+        frame = back;
+#else
+        /* Python 3.10 and earlier: frame structure is accessible */
         frame = frame->f_back;
+#endif
         --depth;
     }
 
diff --git a/siplib/voidptr.c b/siplib/voidptr.c
index 7c288bf6..ea067598 100644
--- siplib/voidptr.c
+++ siplib/voidptr.c
@@ -805,6 +805,12 @@ PyTypeObject sipVoidPtr_Type = {
 #if PY_VERSION_HEX >= 0x03080000
     0,                      /* tp_vectorcall */
 #endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_watched */
+#endif
+#if PY_VERSION_HEX >= 0x030d0000
+    0,                      /* tp_versions_used */
+#endif
 };
 
 
