Skip to content

Commit

Permalink
expirable dict
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowone committed Jun 11, 2018
1 parent 35670d7 commit 3abf171
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 7 deletions.
52 changes: 50 additions & 2 deletions ring/func_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
factories.
"""
from typing import Any, Optional, List
import functools
import time
import re
import hashlib
Expand Down Expand Up @@ -174,7 +175,7 @@ def touch_many(self, keys, expire=Ellipsis):
self.touch_many_values(keys, expire)


class DictStorage(fbase.CommonMixinStorage, fbase.StorageMixin):
class ExpirableDictStorage(fbase.CommonMixinStorage, fbase.StorageMixin):

now = time.time

Expand Down Expand Up @@ -218,6 +219,28 @@ def touch_value(self, key, expire):
self.backend[key] = expired_time, value


class PersistentDictStorage(fbase.CommonMixinStorage, fbase.StorageMixin):

def get_value(self, key):
try:
value = self.backend[key]
except KeyError:
raise fbase.NotFound
return value

def set_value(self, key, value, expire):
self.backend[key] = value

def delete_value(self, key):
try:
del self.backend[key]
except KeyError:
pass

def has_value(self, key):
return key in self.backend


class MemcacheStorage(
fbase.CommonMixinStorage, fbase.StorageMixin, BulkStorageMixin):

Expand Down Expand Up @@ -282,6 +305,22 @@ def set_many_values(self, keys, values, expire):


class DiskStorage(fbase.CommonMixinStorage, fbase.StorageMixin):

def get_value(self, key):
value = self.backend.get(key)
if value is None:
raise fbase.NotFound
return value

def set_value(self, key, value, expire):
self.backend.set(key, value, expire)

def delete_value(self, key):
self.backend.delete(key)


class ShelveStorage(fbase.CommonMixinStorage, fbase.StorageMixin):

def get_value(self, key):
value = self.backend.get(key)
if value is None:
Expand All @@ -298,7 +337,7 @@ def delete_value(self, key):
def dict(
obj, key_prefix=None, expire=None, coder=None, ignorable_keys=None,
default_action='get_or_update', coder_registry=None,
user_interface=CacheUserInterface, storage_class=DictStorage):
user_interface=CacheUserInterface, storage_class=Ellipsis):
"""Basic Python :class:`dict` based cache.
This backend is not designed for real products, but useful by
Expand All @@ -321,6 +360,12 @@ def dict(
:see: :func:`ring.aiodict` for :mod:`asyncio` version.
"""
if storage_class is Ellipsis:
if expire is None:
storage_class = PersistentDictStorage
else:
storage_class = ExpirableDictStorage

return fbase.factory(
obj, key_prefix=key_prefix, on_manufactured=None,
user_interface=user_interface, storage_class=storage_class,
Expand All @@ -329,6 +374,9 @@ def dict(
ignorable_keys=ignorable_keys)


shelve = functools.partial(dict, expire=None)


def memcache(
client, key_prefix=None, expire=0, coder=None, ignorable_keys=None,
default_action='get_or_update', coder_registry=None,
Expand Down
4 changes: 2 additions & 2 deletions tests/_test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def f(a):
assert f('10') == '10'
raw_value = storage.get(f.key('10')) # raw value
value = f.decode(raw_value)
assert f.get('10') == value[1]
assert f.get('10') == value


def test_coder_method():
Expand Down Expand Up @@ -190,4 +190,4 @@ def data(self):

raw_value = storage.get(u1.data.key())
value = u1.data.decode(raw_value)
assert u1.data.get() == value[1]
assert u1.data.get() == value
2 changes: 1 addition & 1 deletion tests/test_action_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def data(self):
assert updated_data == data

key = u1.data.run('key')
direct_data = cache[key][1]
direct_data = cache[key]
assert data == direct_data

with pytest.raises(TypeError):
Expand Down
3 changes: 2 additions & 1 deletion tests/test_func_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ def f():

assert f.get() is None
assert f() == 0
f.touch()
with pytest.raises(AttributeError):
f.touch()


def test_func_dict_expire():
Expand Down
2 changes: 1 addition & 1 deletion tests/test_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def child(self, n):

# do you want to access to cache directly?
key = u1.data.key()
assert u1.data() == cache[key][1] # whenever you want!
assert u1.data() == cache[key] # whenever you want!

u1._data['name'] = 'User renamed'
assert u1.data() == {'user_id': 42, 'name': 'User 1'} # still cached
Expand Down

0 comments on commit 3abf171

Please sign in to comment.