]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #14373: C implementation of functools.lru_cache() now can be used with
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 8 Jun 2015 08:19:24 +0000 (11:19 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 8 Jun 2015 08:19:24 +0000 (11:19 +0300)
methods.

Lib/test/test_functools.py
Misc/NEWS
Modules/_functoolsmodule.c

index 632b2d3740975c6b88f95e82abffef59f6528205..569bdcf701cc1212731da5719ce9dbdda203a890 100644 (file)
@@ -1203,6 +1203,37 @@ class TestLRU:
             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
 
index 03b8631a4a26c50ea062e64bbad461f56889bce8..16098167bb27409738104fc34c427c1c9fd0b720 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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
 
index 99b50b0e9d3df876e16bb0597f55b3adf48acd52..95b5b13fbecad311d74fddf2deb3dd7be92f4e25 100644 (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 */