diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -7,6 +7,8 @@ import sys import types import unittest +import weakref + class TypesTests(unittest.TestCase): @@ -1169,6 +1171,13 @@ self.assertEqual(ns, ns_roundtrip, pname) + def test_weakref(self): + original = types.SimpleNamespace() + weakns = weakref.ref(original) + ns = weakns() + + self.assertIs(ns, original) + def test_main(): run_unittest(TypesTests, MappingProxyTests, ClassCreationTests, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -254,6 +254,8 @@ - Issue #15022: Add pickle and comparison support to types.SimpleNamespace. +- Issue #15004: Add weakref support to types.SimpleNamespace. + Library ------- diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c --- a/Objects/namespaceobject.c +++ b/Objects/namespaceobject.c @@ -7,6 +7,7 @@ typedef struct { PyObject_HEAD PyObject *ns_dict; + PyObject *ns_weakreflist; } _PyNamespaceObject; @@ -33,6 +34,9 @@ return NULL; } } + + ((_PyNamespaceObject *)self)->ns_weakreflist = NULL; + return self; } @@ -59,6 +63,9 @@ static void namespace_dealloc(_PyNamespaceObject *ns) { + if (ns->ns_weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *)ns); + PyObject_GC_UnTrack(ns); Py_CLEAR(ns->ns_dict); Py_TYPE(ns)->tp_free((PyObject *)ns); @@ -227,7 +234,7 @@ (traverseproc)namespace_traverse, /* tp_traverse */ (inquiry)namespace_clear, /* tp_clear */ namespace_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(_PyNamespaceObject, ns_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ namespace_methods, /* tp_methods */