Skip to content

Commit

Permalink
Added add for all backends
Browse files Browse the repository at this point in the history
  • Loading branch information
argaen committed Oct 9, 2016
1 parent aacbe8f commit e0e9a38
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 12 deletions.
12 changes: 6 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ Current supported backends are:

This libraries aims for simplicity over specialization. It provides a common interface for all caches which allows to store any python object. The operations supported by all backends are:

- `add`
- `get`
- `set`
- `multi_get`
- `multi_set`
- `delete`
- ``add``
- ``get``
- ``set``
- ``multi_get``
- ``multi_set``
- ``delete``


Usage
Expand Down
5 changes: 3 additions & 2 deletions aiocache/backends/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ class BaseCache(metaclass=abc.ABCMeta):
def get_serializer(self):
return DefaultSerializer()

async def add(self, key, value):
raise NotImplementedError
@abc.abstractmethod
async def add(self, key, value, ttl=None):
pass

@abc.abstractmethod
async def get(self, key, default=None):
Expand Down
29 changes: 27 additions & 2 deletions aiocache/backends/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async def set(self, key, value, ttl=None, dumps_fn=None):
:param value: obj
:param ttl: int the expiration time in seconds
:param dumps_fn: callable alternative to use as dumps function
:returns:
:returns: True
"""
dumps = dumps_fn or self.serializer.dumps
SimpleMemoryCache._cache[self._build_key(key)] = dumps(value)
Expand All @@ -62,14 +62,39 @@ async def multi_set(self, pairs, dumps_fn=None):
:param pairs: list of two element iterables. First is key and second is value
:param dumps_fn: callable alternative to use as dumps function
:returns:
:returns: True
"""
dumps = dumps_fn or self.serializer.dumps

for key, value in pairs:
SimpleMemoryCache._cache[self._build_key(key)] = dumps(value)
return True

async def add(self, key, value, ttl=None, dumps_fn=None):
"""
Stores the value in the given key with ttl if specified. Raises an error if the
key already exists.
:param key: str
:param value: obj
:param ttl: int the expiration time in seconds
:param dumps_fn: callable alternative to use as dumps function
:returns: True if key is inserted
:raises: Value error if key already exists
"""
dumps = dumps_fn or self.serializer.dumps

key = self._build_key(key)
if key in SimpleMemoryCache._cache:
raise ValueError(
"Key {} already exists, use .set to update the value".format(key))

SimpleMemoryCache._cache[self._build_key(key)] = dumps(value)
if ttl:
loop = asyncio.get_event_loop()
loop.call_later(ttl, self._delete, key)
return True

async def delete(self, key):
"""
Deletes the given key.
Expand Down
26 changes: 24 additions & 2 deletions aiocache/backends/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ async def set(self, key, value, ttl=None, dumps_fn=None):
:param value: obj
:param ttl: int the expiration time in seconds
:param dumps_fn: callable alternative to use as dumps function
:returns:
:returns: True
"""
dumps = dumps_fn or self.serializer.dumps
ttl = ttl or 0
Expand All @@ -72,7 +72,7 @@ async def multi_set(self, pairs, dumps_fn=None):
:param pairs: list of two element iterables. First is key and second is value
:param dumps: callable alternative to use as dumps function
:returns:
:returns: True
"""
dumps = dumps_fn or self.serializer.dumps

Expand All @@ -82,6 +82,28 @@ async def multi_set(self, pairs, dumps_fn=None):
(self._build_key(key), dumps(value)) for key, value in pairs))
return await redis.mset(*serialized_pairs)

async def add(self, key, value, ttl=None, dumps_fn=None):
"""
Stores the value in the given key with ttl if specified. Raises an error if the
key already exists.
:param key: str
:param value: obj
:param ttl: int the expiration time in seconds
:param dumps_fn: callable alternative to use as dumps function
:returns: True if key is inserted
:raises: Value error if key already exists
"""
dumps = dumps_fn or self.serializer.dumps
ttl = ttl or 0

key = self._build_key(key)
with await self._connect() as redis:
if await redis.exists(key):
raise ValueError(
"Key {} already exists, use .set to update the value".format(key))
return await redis.set(key, dumps(value), expire=ttl)

async def delete(self, key):
"""
Deletes the given key.
Expand Down
10 changes: 10 additions & 0 deletions tests/test_base_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,13 @@ async def test_get_set_alt_serializer_class(self, cache):
cache.serializer = my_serializer
await cache.set(pytest.KEY, my_obj)
assert await cache.get(pytest.KEY) == my_serializer.loads(my_serializer.dumps(my_obj))

@pytest.mark.asyncio
async def test_add_missing(self, cache):
assert await cache.add(pytest.KEY, "value") is True

@pytest.mark.asyncio
async def test_add_existing(self, cache):
await cache.set(pytest.KEY, "value") is True
with pytest.raises(ValueError):
await cache.add(pytest.KEY, "value")

0 comments on commit e0e9a38

Please sign in to comment.