import unittest
import unittest.mock
import os
+import weakref
+import gc
from weakref import proxy
import contextlib
return 1
self.assertEqual(f.cache_parameters(), {'maxsize': 1000, "typed": True})
+ def test_lru_cache_weakrefable(self):
+ @self.module.lru_cache
+ def test_function(x):
+ return x
+
+ class A:
+ @self.module.lru_cache
+ def test_method(self, x):
+ return (self, x)
+
+ @staticmethod
+ @self.module.lru_cache
+ def test_staticmethod(x):
+ return (self, x)
+
+ refs = [weakref.ref(test_function),
+ weakref.ref(A.test_method),
+ weakref.ref(A.test_staticmethod)]
+
+ for ref in refs:
+ self.assertIsNotNone(ref())
+
+ del A
+ del test_function
+ gc.collect()
+
+ for ref in refs:
+ self.assertIsNone(ref())
+
@py_functools.lru_cache()
def py_cached_func(x, y):
Py_ssize_t misses;
PyObject *cache_info_type;
PyObject *dict;
+ PyObject *weakreflist;
} lru_cache_object;
static PyTypeObject lru_cache_type;
Py_INCREF(cache_info_type);
obj->cache_info_type = cache_info_type;
obj->dict = NULL;
+ obj->weakreflist = NULL;
return (PyObject *)obj;
}
lru_list_elem *list;
/* bpo-31095: UnTrack is needed before calling any callbacks */
PyObject_GC_UnTrack(obj);
+ if (obj->weakreflist != NULL)
+ PyObject_ClearWeakRefs((PyObject*)obj);
list = lru_cache_unlink_list(obj);
Py_XDECREF(obj->cache);
(traverseproc)lru_cache_tp_traverse,/* tp_traverse */
(inquiry)lru_cache_tp_clear, /* tp_clear */
0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
+ offsetof(lru_cache_object, weakreflist),
+ /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
lru_cache_methods, /* tp_methods */