From c075a1974b0dce9801cb645c77faa8af612b3db5 Mon Sep 17 00:00:00 2001
From: Victor Stinner <vstinner@python.org>
Date: Mon, 26 Jun 2023 12:10:53 +0200
Subject: gh-105927: Deprecate PyWeakref_GetObject() function (#106006)

Deprecate PyWeakref_GetObject() and PyWeakref_GET_OBJECT() functions.
---
 Doc/c-api/weakref.rst                                          |  6 ++++++
 Doc/whatsnew/3.13.rst                                          | 10 +++++++++-
 Include/cpython/weakrefobject.h                                |  3 ++-
 Include/weakrefobject.h                                        |  2 +-
 .../next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst  |  3 +++
 Modules/_testcapimodule.c                                      |  6 ++++++
 Objects/weakrefobject.c                                        |  7 ++++++-
 7 files changed, 33 insertions(+), 4 deletions(-)
 create mode 100644 Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst

diff --git a/Doc/c-api/weakref.rst b/Doc/c-api/weakref.rst
index 44f4dce..04781f7 100644
--- a/Doc/c-api/weakref.rst
+++ b/Doc/c-api/weakref.rst
@@ -74,11 +74,17 @@ as much as it can.
       except when it cannot be destroyed before the last usage of the borrowed
       reference.
 
+   .. deprecated-removed:: 3.13 3.15
+      Use :c:func:`PyWeakref_GetRef` instead.
+
 
 .. c:function:: PyObject* PyWeakref_GET_OBJECT(PyObject *ref)
 
    Similar to :c:func:`PyWeakref_GetObject`, but does no error checking.
 
+   .. deprecated-removed:: 3.13 3.15
+      Use :c:func:`PyWeakref_GetRef` instead.
+
 
 .. c:function:: void PyObject_ClearWeakRefs(PyObject *object)
 
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index ee8c198..b6d13a8 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -470,6 +470,14 @@ Deprecated
   Scheduled for removal in Python 3.15.
   (Contributed by Victor Stinner in :gh:`105396`.)
 
+* Deprecate the :c:func:`PyWeakref_GetObject` and
+  :c:func:`PyWeakref_GET_OBJECT` functions, which return a :term:`borrowed
+  reference`: use the new :c:func:`PyWeakref_GetRef` function instead, it
+  returns a :term:`strong reference`. The `pythoncapi-compat project
+  <https://github.com/python/pythoncapi-compat/>`__ can be used to get
+  :c:func:`PyWeakref_GetRef` on Python 3.12 and older.
+  (Contributed by Victor Stinner in :gh:`105927`.)
+
 Removed
 -------
 
@@ -565,7 +573,7 @@ Removed
 * Remove the old private, undocumented and untested ``_PyGC_FINALIZED()`` macro
   which was kept for backward compatibility with Python 3.8 and older: use
   :c:func:`PyObject_GC_IsFinalized()` instead. The `pythoncapi-compat project
-  <https://github.com/python/pythoncapi-compat/>`_ can be used to get this
+  <https://github.com/python/pythoncapi-compat/>`__ can be used to get this
   function on Python 3.8 and older.
   (Contributed by Victor Stinner in :gh:`105268`.)
 
diff --git a/Include/cpython/weakrefobject.h b/Include/cpython/weakrefobject.h
index 6bf1655..1559e2d 100644
--- a/Include/cpython/weakrefobject.h
+++ b/Include/cpython/weakrefobject.h
@@ -32,7 +32,8 @@ struct _PyWeakReference {
     vectorcallfunc vectorcall;
 };
 
-static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj) {
+Py_DEPRECATED(3.13) static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj)
+{
     PyWeakReference *ref;
     PyObject *obj;
     assert(PyWeakref_Check(ref_obj));
diff --git a/Include/weakrefobject.h b/Include/weakrefobject.h
index 2c69f9e..727ba69 100644
--- a/Include/weakrefobject.h
+++ b/Include/weakrefobject.h
@@ -27,7 +27,7 @@ PyAPI_FUNC(PyObject *) PyWeakref_NewRef(PyObject *ob,
                                         PyObject *callback);
 PyAPI_FUNC(PyObject *) PyWeakref_NewProxy(PyObject *ob,
                                           PyObject *callback);
-PyAPI_FUNC(PyObject *) PyWeakref_GetObject(PyObject *ref);
+Py_DEPRECATED(3.13) PyAPI_FUNC(PyObject *) PyWeakref_GetObject(PyObject *ref);
 PyAPI_FUNC(int) PyWeakref_GetRef(PyObject *ref, PyObject **pobj);
 
 
diff --git a/Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst b/Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst
new file mode 100644
index 0000000..57982dc
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2023-06-22-00-25-55.gh-issue-105927.GRxZtI.rst	
@@ -0,0 +1,3 @@
+Deprecate the :c:func:`PyWeakref_GetObject` and
+:c:func:`PyWeakref_GET_OBJECT` functions: use the new
+:c:func:`PyWeakref_GetRef` function instead. Patch by Victor Stinner.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index d847539..dc8acec 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3375,6 +3375,10 @@ error:
 static PyObject *
 test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
 {
+    // Ignore PyWeakref_GetObject() deprecation, we test it on purpose
+    _Py_COMP_DIAG_PUSH
+    _Py_COMP_DIAG_IGNORE_DEPR_DECLS
+
     // Create a new heap type, create an instance of this type, and delete the
     // type. This object supports weak references.
     PyObject *new_type = PyObject_CallFunction((PyObject*)&PyType_Type,
@@ -3463,6 +3467,8 @@ test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
     Py_DECREF(weakref);
 
     Py_RETURN_NONE;
+
+    _Py_COMP_DIAG_POP
 }
 
 
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index c54f663..f3f6c86 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -923,7 +923,12 @@ PyWeakref_GetObject(PyObject *ref)
         PyErr_BadInternalCall();
         return NULL;
     }
-    return PyWeakref_GET_OBJECT(ref);
+    PyObject *obj = _PyWeakref_GET_REF(ref);
+    if (obj == NULL) {
+        return Py_None;
+    }
+    Py_DECREF(obj);
+    return obj;  // borrowed reference
 }
 
 /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
-- 
cgit v0.12