]> granicus.if.org Git - python/commitdiff
Issue #22116: C functions and methods (of the 'builtin_function_or_method' type)...
authorAntoine Pitrou <solipsis@pitrou.net>
Wed, 6 Aug 2014 23:31:40 +0000 (19:31 -0400)
committerAntoine Pitrou <solipsis@pitrou.net>
Wed, 6 Aug 2014 23:31:40 +0000 (19:31 -0400)
Include/methodobject.h
Lib/test/test_sys.py
Lib/test/test_weakref.py
Misc/ACKS
Misc/NEWS
Modules/_testcapimodule.c
Objects/methodobject.c

index 3cc2ea9308f5e6703c8dedf34c98b319c88d204a..0236228617e4a24f0f37eacb81573651585d6920 100644 (file)
@@ -77,6 +77,7 @@ typedef struct {
     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
 
index 854e7865e88c3c378339fa1e751414890c0b1af7..c50b20b9fb3924229229bc3ef822be20496335ad 100644 (file)
@@ -784,7 +784,7 @@ class SizeofTest(unittest.TestCase):
         # 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:
index adb923f2a38a090a221c0b72e018764e68993f46..747627319b1489df06bcac64a3952dabcfe2feed 100644 (file)
@@ -92,6 +92,18 @@ class ReferencesTestCase(TestBase):
         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)
index 09b68d181a3225a020f50a2495c102376c735691..60d6f7fd5f9425d824fd25f0624da039c5e86b65 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1484,6 +1484,7 @@ Gordon Worley
 Darren Worrall
 Thomas Wouters
 Daniel Wozniak
+Wei Wu
 Heiko Wundram
 Doug Wyatt
 Robert Xiao
index 877384f1797f9c0ba58968dbd373995865282f40..4a3ebd56e5bdf45e6bf8e0dfdb96608b8869e18f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: TBA
 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.
index ebbf88f71a48ab1c076b11cf2b7af68704fc0b17..9f20abb20865a8c09a94677fc96ce84d7dc550ae 100644 (file)
@@ -2653,6 +2653,21 @@ with_tp_del(PyObject *self, PyObject *args)
     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 @@ static PyMethodDef TestMethods[] = {
     {"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",
index f2616d4ef0eb4e618b3053a6bab87345753e018d..686baf9ece76310dbad6abe544f3df10e40771cb 100644 (file)
@@ -37,6 +37,7 @@ PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
         if (op == NULL)
             return NULL;
     }
+    op->m_weakreflist = NULL;
     op->m_ml = ml;
     Py_XINCREF(self);
     op->m_self = self;
@@ -147,6 +148,9 @@ static void
 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 @@ PyTypeObject PyCFunction_Type = {
     (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 */