[Python-checkins] cpython: Issue #22116: C functions and methods (of the 'builtin_function_or_method'

antoine.pitrou python-checkins at python.org
Thu Aug 7 01:34:50 CEST 2014


http://hg.python.org/cpython/rev/87f940e85cb0
changeset:   92027:87f940e85cb0
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Wed Aug 06 19:31:40 2014 -0400
summary:
  Issue #22116: C functions and methods (of the 'builtin_function_or_method' type) can now be weakref'ed.  Patch by Wei Wu.

files:
  Include/methodobject.h    |   1 +
  Lib/test/test_sys.py      |   2 +-
  Lib/test/test_weakref.py  |  12 ++++++++++++
  Misc/ACKS                 |   1 +
  Misc/NEWS                 |   3 +++
  Modules/_testcapimodule.c |  16 ++++++++++++++++
  Objects/methodobject.c    |   6 +++++-
  7 files changed, 39 insertions(+), 2 deletions(-)


diff --git a/Include/methodobject.h b/Include/methodobject.h
--- a/Include/methodobject.h
+++ b/Include/methodobject.h
@@ -77,6 +77,7 @@
     PyMethodDef *m_ml; /* Description of the C function to call */
     PyObject    *m_self; /* Passed as 'self' arg to the C func, can be NULL */
     PyObject    *m_module; /* The __module__ attribute, can be anything */
+    PyObject    *m_weakreflist; /* List of weak references */
 } PyCFunctionObject;
 #endif
 
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -784,7 +784,7 @@
         # buffer
         # XXX
         # builtin_function_or_method
-        check(len, size('3P')) # XXX check layout
+        check(len, size('4P')) # XXX check layout
         # bytearray
         samples = [b'', b'u'*100000]
         for sample in samples:
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -92,6 +92,18 @@
         self.check_basic_callback(create_function)
         self.check_basic_callback(create_bound_method)
 
+    @support.cpython_only
+    def test_cfunction(self):
+        import _testcapi
+        create_cfunction = _testcapi.create_cfunction
+        f = create_cfunction()
+        wr = weakref.ref(f)
+        self.assertIs(wr(), f)
+        del f
+        self.assertIsNone(wr())
+        self.check_basic_ref(create_cfunction)
+        self.check_basic_callback(create_cfunction)
+
     def test_multiple_callbacks(self):
         o = C()
         ref1 = weakref.ref(o, self.callback)
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1484,6 +1484,7 @@
 Darren Worrall
 Thomas Wouters
 Daniel Wozniak
+Wei Wu
 Heiko Wundram
 Doug Wyatt
 Robert Xiao
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #22116: C functions and methods (of the 'builtin_function_or_method'
+  type) can now be weakref'ed.  Patch by Wei Wu.
+
 - Issue #22077: Improve index error messages for bytearrays, bytes, lists,
   and tuples by adding 'or slices'. Added ', not <typename' for bytearrays.
   Original patch by Claudiu Popa.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -2653,6 +2653,21 @@
     return obj;
 }
 
+static PyMethodDef ml;
+
+static PyObject *
+create_cfunction(PyObject *self, PyObject *args)
+{
+    return PyCFunction_NewEx(&ml, self, NULL);
+}
+
+static PyMethodDef ml = {
+    "create_cfunction",
+    create_cfunction,
+    METH_NOARGS,
+    NULL
+};
+
 static PyObject *
 _test_incref(PyObject *ob)
 {
@@ -3186,6 +3201,7 @@
     {"pytime_object_to_timeval", test_pytime_object_to_timeval,  METH_VARARGS},
     {"pytime_object_to_timespec", test_pytime_object_to_timespec,  METH_VARARGS},
     {"with_tp_del",             with_tp_del,                     METH_VARARGS},
+    {"create_cfunction",        create_cfunction,                METH_NOARGS},
     {"test_pymem_alloc0",
      (PyCFunction)test_pymem_alloc0, METH_NOARGS},
     {"test_pymem_setrawallocators",
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -37,6 +37,7 @@
         if (op == NULL)
             return NULL;
     }
+    op->m_weakreflist = NULL;
     op->m_ml = ml;
     Py_XINCREF(self);
     op->m_self = self;
@@ -147,6 +148,9 @@
 meth_dealloc(PyCFunctionObject *m)
 {
     _PyObject_GC_UNTRACK(m);
+    if (m->m_weakreflist != NULL) {
+        PyObject_ClearWeakRefs((PyObject*) m);
+    }
     Py_XDECREF(m->m_self);
     Py_XDECREF(m->m_module);
     if (numfree < PyCFunction_MAXFREELIST) {
@@ -352,7 +356,7 @@
     (traverseproc)meth_traverse,                /* tp_traverse */
     0,                                          /* tp_clear */
     meth_richcompare,                           /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
+    offsetof(PyCFunctionObject, m_weakreflist), /* tp_weaklistoffset */
     0,                                          /* tp_iter */
     0,                                          /* tp_iternext */
     meth_methods,                               /* tp_methods */

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list