summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2010-03-31 21:32:15 +0000
committerAntoine Pitrou <solipsis@pitrou.net>2010-03-31 21:32:15 +0000
commita57df2cf1d627840dff505e8487fbd5f42414c7b (patch)
tree87d099bca7fc01072ad6911e9ffa79707b982704
parent26cc99da2a350f3093c9d7055794daef2034e2a4 (diff)
downloadcpython-git-a57df2cf1d627840dff505e8487fbd5f42414c7b.tar.gz
Issue #8268: Old-style classes (not just instances) now support weak
references.
-rw-r--r--Include/classobject.h1
-rw-r--r--Lib/test/test_sys.py2
-rw-r--r--Lib/test/test_weakref.py20
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/classobject.c5
5 files changed, 29 insertions, 2 deletions
diff --git a/Include/classobject.h b/Include/classobject.h
index 118dd09647..bc03e0d027 100644
--- a/Include/classobject.h
+++ b/Include/classobject.h
@@ -18,6 +18,7 @@ typedef struct {
PyObject *cl_getattr;
PyObject *cl_setattr;
PyObject *cl_delattr;
+ PyObject *cl_weakreflist; /* List of weak references */
} PyClassObject;
typedef struct {
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index d106fe7a7a..17208753be 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -544,7 +544,7 @@ class SizeofTest(unittest.TestCase):
class class_oldstyle():
def method():
pass
- check(class_oldstyle, size(h + '6P'))
+ check(class_oldstyle, size(h + '7P'))
# instance (old-style class)
check(class_oldstyle(), size(h + '3P'))
# instancemethod (old-style class)
diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py
index 536a987fe4..bc2982fadb 100644
--- a/Lib/test/test_weakref.py
+++ b/Lib/test/test_weakref.py
@@ -685,6 +685,26 @@ class ReferencesTestCase(TestBase):
# No exception should be raised here
gc.collect()
+ def test_classes(self):
+ # Check that both old-style classes and new-style classes
+ # are weakrefable.
+ class A(object):
+ pass
+ class B:
+ pass
+ l = []
+ weakref.ref(int)
+ a = weakref.ref(A, l.append)
+ A = None
+ gc.collect()
+ self.assertEqual(a(), None)
+ self.assertEqual(l, [a])
+ b = weakref.ref(B, l.append)
+ B = None
+ gc.collect()
+ self.assertEqual(b(), None)
+ self.assertEqual(l, [a, b])
+
class SubclassableWeakrefTestCase(TestBase):
diff --git a/Misc/NEWS b/Misc/NEWS
index 09d07f2c3b..80f1d2e2e0 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.7 beta 1?
Core and Builtins
-----------------
+- Issue #8268: Old-style classes (not just instances) now support weak
+ references.
+
- Issue #8211: Save/restore CFLAGS around AC_PROG_CC in configure.in, compiler
optimizations are disabled when --with-pydebug is used.
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 3f51c0fc55..032d354ef0 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -123,6 +123,7 @@ alloc_error:
op->cl_dict = dict;
Py_XINCREF(name);
op->cl_name = name;
+ op->cl_weakreflist = NULL;
op->cl_getattr = class_lookup(op, getattrstr, &dummy);
op->cl_setattr = class_lookup(op, setattrstr, &dummy);
@@ -188,6 +189,8 @@ static void
class_dealloc(PyClassObject *op)
{
_PyObject_GC_UNTRACK(op);
+ if (op->cl_weakreflist != NULL)
+ PyObject_ClearWeakRefs((PyObject *) op);
Py_DECREF(op->cl_bases);
Py_DECREF(op->cl_dict);
Py_XDECREF(op->cl_name);
@@ -454,7 +457,7 @@ PyTypeObject PyClass_Type = {
(traverseproc)class_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
+ offsetof(PyClassObject, cl_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */