summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiekun <2014bduck@gmail.com>2021-08-08 17:36:17 +0800
committerGitHub <noreply@github.com>2021-08-08 12:36:17 +0300
commit2789f08dfb7192f112aa0fc8cec6738dfb1b3a08 (patch)
treef509de1ebba257f1292b4f457bcb87639ccc2d51
parent8c4fc802ed03cbebeb15686755e792bc179750e7 (diff)
downloadredis-py-2789f08dfb7192f112aa0fc8cec6738dfb1b3a08.tar.gz
Added GET argument to SET command (#1412)
-rwxr-xr-xredis/client.py32
-rw-r--r--tests/test_commands.py8
2 files changed, 37 insertions, 3 deletions
diff --git a/redis/client.py b/redis/client.py
index 5d1cd2c..3c3ab7f 100755
--- a/redis/client.py
+++ b/redis/client.py
@@ -555,6 +555,20 @@ def parse_module_result(response):
return True
+def parse_set_result(response, **options):
+ """
+ Handle SET result since GET argument is available since Redis 6.2.
+ Parsing SET result into:
+ - BOOL
+ - String when GET argument is used
+ """
+ if options.get('get'):
+ # Redis will return a getCommand result.
+ # See `setGenericCommand` in t_string.c
+ return response
+ return response and str_if_bytes(response) == 'OK'
+
+
class Redis:
"""
Implementation of the Redis protocol.
@@ -683,7 +697,7 @@ class Redis:
'SENTINEL SENTINELS': parse_sentinel_slaves_and_sentinels,
'SENTINEL SET': bool_ok,
'SENTINEL SLAVES': parse_sentinel_slaves_and_sentinels,
- 'SET': lambda r: r and str_if_bytes(r) == 'OK',
+ 'SET': parse_set_result,
'SLOWLOG GET': parse_slowlog_get,
'SLOWLOG LEN': int,
'SLOWLOG RESET': bool_ok,
@@ -1804,6 +1818,9 @@ class Redis:
"""
Sets the value at key ``name`` to ``value``
and returns the old value at key ``name`` atomically.
+
+ As per Redis 6.2, GETSET is considered deprecated.
+ Please use SET with GET parameter in new code.
"""
return self.execute_command('GETSET', name, value)
@@ -1964,7 +1981,7 @@ class Redis:
return self.execute_command('RESTORE', *params)
def set(self, name, value,
- ex=None, px=None, nx=False, xx=False, keepttl=False):
+ ex=None, px=None, nx=False, xx=False, keepttl=False, get=False):
"""
Set the value at key ``name`` to ``value``
@@ -1980,8 +1997,13 @@ class Redis:
``keepttl`` if True, retain the time to live associated with the key.
(Available since Redis 6.0)
+
+ ``get`` if True, set the value at key ``name`` to ``value`` and return
+ the old value stored at key, or None when key did not exist.
+ (Available since Redis 6.2)
"""
pieces = [name, value]
+ options = {}
if ex is not None:
pieces.append('EX')
if isinstance(ex, datetime.timedelta):
@@ -2001,7 +2023,11 @@ class Redis:
if keepttl:
pieces.append('KEEPTTL')
- return self.execute_command('SET', *pieces)
+ if get:
+ pieces.append('GET')
+ options["get"] = True
+
+ return self.execute_command('SET', *pieces, **options)
def __setitem__(self, name, value):
self.set(name, value)
diff --git a/tests/test_commands.py b/tests/test_commands.py
index 60e667d..76322d7 100644
--- a/tests/test_commands.py
+++ b/tests/test_commands.py
@@ -1006,6 +1006,14 @@ class TestRedisCommands:
assert r.get('a') == b'2'
assert 0 < r.ttl('a') <= 10
+ @skip_if_server_version_lt('6.2.0')
+ def test_set_get(self, r):
+ assert r.set('a', 'True', get=True) is None
+ assert r.set('a', 'True', get=True) == b'True'
+ assert r.set('a', 'foo') is True
+ assert r.set('a', 'bar', get=True) == b'foo'
+ assert r.get('a') == b'bar'
+
def test_setex(self, r):
assert r.setex('a', 60, '1')
assert r['a'] == b'1'