Skip to content

Commit

Permalink
bpo-40504: Allow weakrefs to lru_cache objects (pythonGH-19938)
Browse files Browse the repository at this point in the history
  • Loading branch information
sweeneyde authored May 5, 2020
1 parent c21c512 commit 1253c3e
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 1 deletion.
31 changes: 31 additions & 0 deletions Lib/test/test_functools.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import unittest
import unittest.mock
import os
import weakref
import gc
from weakref import proxy
import contextlib

Expand Down Expand Up @@ -1938,6 +1940,35 @@ def f():
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):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:func:`functools.lru_cache` objects can now be the targets of weakrefs.
7 changes: 6 additions & 1 deletion Modules/_functoolsmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,7 @@ typedef struct lru_cache_object {
Py_ssize_t misses;
PyObject *cache_info_type;
PyObject *dict;
PyObject *weakreflist;
} lru_cache_object;

static PyTypeObject lru_cache_type;
Expand Down Expand Up @@ -1196,6 +1197,7 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
Py_INCREF(cache_info_type);
obj->cache_info_type = cache_info_type;
obj->dict = NULL;
obj->weakreflist = NULL;
return (PyObject *)obj;
}

Expand Down Expand Up @@ -1227,6 +1229,8 @@ lru_cache_dealloc(lru_cache_object *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);
Expand Down Expand Up @@ -1384,7 +1388,8 @@ static PyTypeObject lru_cache_type = {
(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 */
Expand Down

0 comments on commit 1253c3e

Please sign in to comment.