Skip to content

Commit b01c97b

Browse files
committed
Make Index.setdefault atomic using Cache.add
1 parent 434c128 commit b01c97b

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

‎diskcache/persistent.py‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ def __getitem__(self, key):
728728
KeyError: 'c'
729729
730730
:param key: key for item
731+
:return: value for item in index with given key
731732
:raises KeyError: if key is not found
732733
733734
"""
@@ -799,6 +800,39 @@ def __delitem__(self, key):
799800
return
800801

801802

803+
defsetdefault(self, key, default=None):
804+
"""Set and get value for `key` in index using `default`.
805+
806+
If `key` is not in index then set corresponding value to `default`. If
807+
`key` is in index then ignore `default` and return existing value.
808+
809+
>>> index = Index('/tmp/diskcache/index')
810+
>>> index.clear()
811+
>>> index.setdefault('a', 0)
812+
0
813+
>>> index.setdefault('a', 1)
814+
0
815+
816+
:param key: key for item
817+
:param default: value if key is missing (default None)
818+
:return: value for item in index with given key
819+
820+
"""
821+
_cache=self._cache
822+
823+
whileTrue:
824+
try:
825+
returnself[key]
826+
exceptKeyError:
827+
whileTrue:
828+
try:
829+
_cache.add(key, default)
830+
exceptTimeout:
831+
continue
832+
else:
833+
break
834+
835+
802836
defpop(self, key, default=ENOVAL):
803837
"""Remove corresponding item for `key` from index and return value.
804838

‎diskcache/stampede.py‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ class StampedeBarrier(object):
2121
2222
Example:
2323
24-
>>> stampede_barrier = StampedeBarrier('/tmp/user_data', expire=3)
25-
>>> @stampede_barrier
24+
```python
25+
stampede_barrier = StampedeBarrier('/tmp/user_data', expire=3)
26+
27+
@stampede_barrier
2628
def load_user_info(user_id):
2729
return database.lookup_user_info_by_id(user_id)
30+
```
2831
2932
"""
3033
# pylint: disable=too-few-public-methods

‎tests/test_index.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,25 @@ def test_popitem_timeout(index):
170170
assertvalue== (0, 1)
171171

172172

173+
@setup_index
174+
deftest_setdefault(index):
175+
assertindex.setdefault('a', 0) ==0
176+
assertindex.setdefault('a', 1) ==0
177+
178+
179+
@setup_index
180+
deftest_setdefault_timeout(index):
181+
cache=mock.MagicMock()
182+
cache.__getitem__=mock.Mock()
183+
cache.__getitem__.side_effect= [KeyError, 0]
184+
cache.add=mock.Mock()
185+
cache.add.side_effect= [dc.Timeout, 0]
186+
187+
withmock.patch.object(index, '_cache', cache):
188+
value=index.setdefault('a', 0)
189+
assertvalue==0
190+
191+
173192
@setup_index
174193
deftest_iter(index):
175194
letters='abcde'

0 commit comments

Comments
(0)