[Python-checkins] cpython (merge 3.6 -> default): Issue #27275: Fixed implementation of pop() and popitem() methods in

serhiy.storchaka python-checkins at python.org
Tue Oct 25 08:38:53 EDT 2016


https://hg.python.org/cpython/rev/19e199038704
changeset: 104717:19e199038704
parent: 104714:4a3892f49e1a
parent: 104716:2def8a24c299
user: Serhiy Storchaka <storchaka at gmail.com>
date: Tue Oct 25 15:38:28 2016 +0300
summary:
 Issue #27275: Fixed implementation of pop() and popitem() methods in
subclasses of accelerated OrderedDict.
files:
 Lib/test/test_ordered_dict.py | 59 +++++++++++++++++++++++
 Misc/NEWS | 3 +
 Objects/odictobject.c | 29 ++--------
 3 files changed, 69 insertions(+), 22 deletions(-)
diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py
--- a/Lib/test/test_ordered_dict.py
+++ b/Lib/test/test_ordered_dict.py
@@ -775,5 +775,64 @@
 self.assertRaises(KeyError, d.popitem)
 
 
+class SimpleLRUCache:
+
+ def __init__(self, size):
+ super().__init__()
+ self.size = size
+
+ def __getitem__(self, item):
+ value = super().__getitem__(item)
+ self.move_to_end(item)
+ return value
+
+ def __setitem__(self, key, value):
+ while key not in self and len(self) >= self.size:
+ self.popitem(last=False)
+ super().__setitem__(key, value)
+ self.move_to_end(key)
+
+
+class SimpleLRUCacheTests:
+
+ def test_add_after_full(self):
+ c = self.type2test(2)
+ c['t1'] = 1
+ c['t2'] = 2
+ c['t3'] = 3
+ self.assertEqual(list(c), ['t2', 't3'])
+
+ def test_popitem(self):
+ c = self.type2test(3)
+ for i in range(1, 4):
+ c[i] = i
+ self.assertEqual(c.popitem(last=False), (1, 1))
+ self.assertEqual(c.popitem(last=True), (3, 3))
+
+ def test_change_order_on_get(self):
+ c = self.type2test(3)
+ for i in range(1, 4):
+ c[i] = i
+ self.assertEqual(list(c), list(range(1, 4)))
+ self.assertEqual(c[2], 2)
+ self.assertEqual(list(c), [1, 3, 2])
+
+
+class PySimpleLRUCacheTests(SimpleLRUCacheTests, unittest.TestCase):
+
+ class type2test(SimpleLRUCache, py_coll.OrderedDict):
+ pass
+
+
+ at unittest.skipUnless(c_coll, 'requires the C version of the collections module')
+class CSimpleLRUCacheTests(SimpleLRUCacheTests, unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ class type2test(SimpleLRUCache, c_coll.OrderedDict):
+ pass
+ cls.type2test = type2test
+
+
 if __name__ == "__main__":
 unittest.main()
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -97,6 +97,9 @@
 Library
 -------
 
+- Issue #27275: Fixed implementation of pop() and popitem() methods in
+ subclasses of accelerated OrderedDict.
+
 - Issue #28255: calendar.TextCalendar.prweek() no longer prints a space after
 a weeks's calendar. calendar.TextCalendar.pryear() no longer prints redundant
 newline after a year's calendar. Based on patch by Xiang Zhang.
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -1102,28 +1102,13 @@
 }
 
 /* Now delete the value from the dict. */
- if (PyODict_CheckExact(od)) {
- if (node != NULL) {
- value = _PyDict_GetItem_KnownHash(od, key, hash); /* borrowed */
- if (value != NULL) {
- Py_INCREF(value);
- if (_PyDict_DelItem_KnownHash(od, key, hash) < 0) {
- Py_DECREF(value);
- return NULL;
- }
- }
- }
- }
- else {
- int exists = PySequence_Contains(od, key);
- if (exists < 0)
- return NULL;
- if (exists) {
- value = PyObject_GetItem(od, key);
- if (value != NULL) {
- if (PyObject_DelItem(od, key) == -1) {
- Py_CLEAR(value);
- }
+ if (node != NULL) {
+ value = _PyDict_GetItem_KnownHash(od, key, hash); /* borrowed */
+ if (value != NULL) {
+ Py_INCREF(value);
+ if (_PyDict_DelItem_KnownHash(od, key, hash) < 0) {
+ Py_DECREF(value);
+ return NULL;
 }
 }
 }
-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /