Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1253c3e

Browse filesBrowse files
authored
bpo-40504: Allow weakrefs to lru_cache objects (GH-19938)
1 parent c21c512 commit 1253c3e
Copy full SHA for 1253c3e

File tree

Expand file treeCollapse file tree

3 files changed

+38
-1
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+38
-1
lines changed

‎Lib/test/test_functools.py

Copy file name to clipboardExpand all lines: Lib/test/test_functools.py
+31Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import unittest
1515
import unittest.mock
1616
import os
17+
import weakref
18+
import gc
1719
from weakref import proxy
1820
import contextlib
1921

@@ -1938,6 +1940,35 @@ def f():
19381940
return 1
19391941
self.assertEqual(f.cache_parameters(), {'maxsize': 1000, "typed": True})
19401942

1943+
def test_lru_cache_weakrefable(self):
1944+
@self.module.lru_cache
1945+
def test_function(x):
1946+
return x
1947+
1948+
class A:
1949+
@self.module.lru_cache
1950+
def test_method(self, x):
1951+
return (self, x)
1952+
1953+
@staticmethod
1954+
@self.module.lru_cache
1955+
def test_staticmethod(x):
1956+
return (self, x)
1957+
1958+
refs = [weakref.ref(test_function),
1959+
weakref.ref(A.test_method),
1960+
weakref.ref(A.test_staticmethod)]
1961+
1962+
for ref in refs:
1963+
self.assertIsNotNone(ref())
1964+
1965+
del A
1966+
del test_function
1967+
gc.collect()
1968+
1969+
for ref in refs:
1970+
self.assertIsNone(ref())
1971+
19411972

19421973
@py_functools.lru_cache()
19431974
def py_cached_func(x, y):
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:func:`functools.lru_cache` objects can now be the targets of weakrefs.

‎Modules/_functoolsmodule.c

Copy file name to clipboardExpand all lines: Modules/_functoolsmodule.c
+6-1Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ typedef struct lru_cache_object {
783783
Py_ssize_t misses;
784784
PyObject *cache_info_type;
785785
PyObject *dict;
786+
PyObject *weakreflist;
786787
} lru_cache_object;
787788

788789
static PyTypeObject lru_cache_type;
@@ -1196,6 +1197,7 @@ lru_cache_new(PyTypeObject *type, PyObject *args, PyObject *kw)
11961197
Py_INCREF(cache_info_type);
11971198
obj->cache_info_type = cache_info_type;
11981199
obj->dict = NULL;
1200+
obj->weakreflist = NULL;
11991201
return (PyObject *)obj;
12001202
}
12011203

@@ -1227,6 +1229,8 @@ lru_cache_dealloc(lru_cache_object *obj)
12271229
lru_list_elem *list;
12281230
/* bpo-31095: UnTrack is needed before calling any callbacks */
12291231
PyObject_GC_UnTrack(obj);
1232+
if (obj->weakreflist != NULL)
1233+
PyObject_ClearWeakRefs((PyObject*)obj);
12301234

12311235
list = lru_cache_unlink_list(obj);
12321236
Py_XDECREF(obj->cache);
@@ -1384,7 +1388,8 @@ static PyTypeObject lru_cache_type = {
13841388
(traverseproc)lru_cache_tp_traverse,/* tp_traverse */
13851389
(inquiry)lru_cache_tp_clear, /* tp_clear */
13861390
0, /* tp_richcompare */
1387-
0, /* tp_weaklistoffset */
1391+
offsetof(lru_cache_object, weakreflist),
1392+
/* tp_weaklistoffset */
13881393
0, /* tp_iter */
13891394
0, /* tp_iternext */
13901395
lru_cache_methods, /* tp_methods */

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.