# HG changeset patch # User Laurent Wouters # Date 1524662965 -7200 # Node ID cbbcfa69a0e74110447d590ed42524dc2d3665ec # Parent d507cbe169ab48346cba732fb0f1ec688cf4a64d [utils] Fixes compatiblity of QueryCache with expected dict interface QueryCache is expected to mimick the interface of the dict built-in. The current __iter__ implementation breaks this expectation by iterating over key, value pairs instead of only the keys. This changeset fixes this issue by changing the __iter__ implementation to iterate over the keys in the cache and providing an implementation of the items method with a contract identical to the dict build-in (return a copy of the key- value pairs within the dictionary as a list). diff -r d507cbe169ab -r cbbcfa69a0e7 cubicweb/test/unittest_utils.py --- a/cubicweb/test/unittest_utils.py Tue Apr 24 15:21:18 2018 +0200 +++ b/cubicweb/test/unittest_utils.py Wed Apr 25 15:29:25 2018 +0200 @@ -154,8 +154,28 @@ v = c.get(x, -1) self.assertEqual(v, -1) + def test_iterkeys(self): + """ + Tests the iterating on keys in the cache + """ + c = QueryCache(ceiling=20) + # set 10 values + for x in range(10): + c[x] = x + # arrange for the first 5 to be permanent + for x in range(5): + for r in range(QueryCache._maxlevel + 2): + v = c[x] + self.assertEqual(v, x) + self.assertEqual(c._usage_report(), + {'transientcount': 0, + 'itemcount': 10, + 'permanentcount': 5}) + keys = sorted(c) + for x in range(10): + self.assertEquals(x, keys[x]) - def test_iterator(self): + def test_items(self): """ Tests the iterating on key-value couples in the cache """ @@ -172,7 +192,7 @@ {'transientcount': 0, 'itemcount': 10, 'permanentcount': 5}) - content = sorted(c) + content = sorted(c.items()) for x in range(10): self.assertEquals(x, content[x][0]) self.assertEquals(x, content[x][1]) diff -r d507cbe169ab -r cbbcfa69a0e7 cubicweb/utils.py --- a/cubicweb/utils.py Tue Apr 24 15:21:18 2018 +0200 +++ b/cubicweb/utils.py Wed Apr 25 15:29:25 2018 +0200 @@ -627,6 +627,12 @@ with self._lock: return len(self._data) + def items(self): + """Get an iterator over the dictionary's items: (key, value) pairs""" + with self._lock: + for k, v in self._data.items(): + yield k, v + def get(self, k, default=None): """Get the value associated to the specified key @@ -641,8 +647,8 @@ def __iter__(self): with self._lock: - for k, v in self._data.items(): - yield k, v + for k in iter(self._data): + yield k def __getitem__(self, k): with self._lock: