Issue #14373: C implementation of functools.lru_cache() now can be used with

methods.
This commit is contained in:
Serhiy Storchaka 2015-06-08 11:19:24 +03:00
parent 77cb197aaa
commit e7070f09bc
3 changed files with 45 additions and 1 deletions

View file

@ -1203,6 +1203,37 @@ def test_early_detection_of_bad_call(self):
def f():
pass
def test_lru_method(self):
class X(int):
f_cnt = 0
@self.module.lru_cache(2)
def f(self, x):
self.f_cnt += 1
return x*10+self
a = X(5)
b = X(5)
c = X(7)
self.assertEqual(X.f.cache_info(), (0, 0, 2, 0))
for x in 1, 2, 2, 3, 1, 1, 1, 2, 3, 3:
self.assertEqual(a.f(x), x*10 + 5)
self.assertEqual((a.f_cnt, b.f_cnt, c.f_cnt), (6, 0, 0))
self.assertEqual(X.f.cache_info(), (4, 6, 2, 2))
for x in 1, 2, 1, 1, 1, 1, 3, 2, 2, 2:
self.assertEqual(b.f(x), x*10 + 5)
self.assertEqual((a.f_cnt, b.f_cnt, c.f_cnt), (6, 4, 0))
self.assertEqual(X.f.cache_info(), (10, 10, 2, 2))
for x in 2, 1, 1, 1, 1, 2, 1, 3, 2, 1:
self.assertEqual(c.f(x), x*10 + 7)
self.assertEqual((a.f_cnt, b.f_cnt, c.f_cnt), (6, 4, 5))
self.assertEqual(X.f.cache_info(), (15, 15, 2, 2))
self.assertEqual(a.f.cache_info(), X.f.cache_info())
self.assertEqual(b.f.cache_info(), X.f.cache_info())
self.assertEqual(c.f.cache_info(), X.f.cache_info())
class TestLRUC(TestLRU, unittest.TestCase):
module = c_functools

View file

@ -15,6 +15,9 @@ Core and Builtins
Library
-------
- Issue #14373: C implementation of functools.lru_cache() now can be used with
methods.
- Issue #8232: webbrowser support incomplete on Windows. Patch by Brandon
Milam

View file

@ -1003,6 +1003,16 @@ lru_cache_call(lru_cache_object *self, PyObject *args, PyObject *kwds)
return self->wrapper(self, args, kwds);
}
static PyObject *
lru_cache_descr_get(PyObject *self, PyObject *obj, PyObject *type)
{
if (obj == Py_None || obj == NULL) {
Py_INCREF(self);
return self;
}
return PyMethod_New(self, obj);
}
static PyObject *
lru_cache_cache_info(lru_cache_object *self, PyObject *unused)
{
@ -1115,7 +1125,7 @@ static PyTypeObject lru_cache_type = {
lru_cache_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
lru_cache_descr_get, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(lru_cache_object, dict), /* tp_dictoffset */
0, /* tp_init */