Skip to content

Commit e94aef6

Browse files
committed
String and number commands
1 parent 3e0b6dd commit e94aef6

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed

rejson/client.py

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ def str_path(p):
1313
else:
1414
return p
1515

16+
def float_or_long(n):
17+
"Return a number from a Redis reply"
18+
if isinstance(n, str):
19+
return float(n)
20+
else:
21+
return long(n)
22+
23+
def json_or_none(r):
24+
"Return a deserialized JSON object or None"
25+
if r:
26+
return json.loads(r)
27+
return r
28+
1629
def bulk_of_jsons(b):
1730
"Replace serialized JSON values with objects in a bulk array response (list)"
1831
for index, item in enumerate(b):
@@ -34,17 +47,19 @@ class Client(StrictRedis):
3447
}
3548

3649
MODULE_CALLBACKS = {
37-
'JSON.DEL': lambda r: int(r),
38-
'JSON.GET': lambda r: json.loads(r),
50+
'JSON.DEL': long,
51+
'JSON.GET': json_or_none,
3952
'JSON.MGET': bulk_of_jsons,
4053
'JSON.SET': lambda r: r and nativestr(r) == 'OK',
54+
'JSON.NUMINCRBY': float_or_long,
55+
'JSON.NUMMULTBY': float_or_long,
56+
'JSON.STRAPPEND': long,
57+
'JSON.STRLEN': long,
4158
}
4259

4360
def __init__(self, **kwargs):
4461
super(Client, self).__init__(**kwargs)
45-
4662
self.__checkPrerequirements()
47-
4863
# Inject the callbacks for the module's commands
4964
self.response_callbacks.update(self.MODULE_CALLBACKS)
5065

@@ -103,7 +118,6 @@ def JSONSet(self, name, path, obj, nx=False, xx=False):
103118
``xx`` if set to True, set ``value`` only if it exists
104119
"""
105120
pieces = [name, str_path(path), json.dumps(obj)]
106-
107121
# Handle existential modifiers
108122
if nx and xx:
109123
raise Exception('nx and xx are mutually exclusive: use one, the '
@@ -112,11 +126,36 @@ def JSONSet(self, name, path, obj, nx=False, xx=False):
112126
pieces.append('NX')
113127
elif xx:
114128
pieces.append('XX')
115-
116129
return self.execute_command('JSON.SET', *pieces)
117130

118131
def JSONType(self, name, path=Path.rootPath()):
119132
"""
120133
Gets the type of the JSON value under ``path`` from key ``name``
121134
"""
122135
return self.execute_command('JSON.TYPE', name, str_path(path))
136+
137+
def JSONNumIncrBy(self, name, path, number):
138+
"""
139+
Increments the numeric (integer or floating point) JSON value under
140+
``path`` at key ``name`` by the provided ``number``
141+
"""
142+
return self.execute_command('JSON.NUMINCRBY', name, str_path(path), json.dumps(number))
143+
144+
def JSONNumMultBy(self, name, path, number):
145+
"""
146+
Multiplies the numeric (integer or floating point) JSON value under
147+
``path`` at key ``name`` with the provided ``number``
148+
"""
149+
return self.execute_command('JSON.NUMMULTBY', name, str_path(path), json.dumps(number))
150+
151+
def JSONStrAppend(self, name, string, path=Path.rootPath()):
152+
"""
153+
Appends to the string JSON value under ``path`` at key ``name`` the provided ``string``
154+
"""
155+
return self.execute_command('JSON.STRAPPEND', name, str_path(path), json.dumps(string))
156+
157+
def JSONStrLen(self, name, path=Path.rootPath()):
158+
"""
159+
Returns the length of the string JSON value under ``path`` at key ``name``
160+
"""
161+
return self.execute_command('JSON.STRLEN', name, str_path(path))

test/test.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,45 @@ def testTypeShouldSucceed(self):
3333
rj.JSONSet('1', Path.rootPath(), 1)
3434
self.assertEqual('integer', rj.JSONType('1'))
3535

36+
def testNumIncrByShouldSucceed(self):
37+
"Test JSONNumIncrBy"
38+
rj = Client()
39+
rj.flushdb()
40+
41+
rj.JSONSet('num', Path.rootPath(), 1)
42+
self.assertEqual(2, rj.JSONNumIncrBy('num', Path.rootPath(), 1))
43+
self.assertEqual(2.5, rj.JSONNumIncrBy('num', Path.rootPath(), 0.5))
44+
self.assertEqual(1.25, rj.JSONNumIncrBy('num', Path.rootPath(), -1.25))
45+
46+
def testNumMultByShouldSucceed(self):
47+
"Test JSONNumIncrBy"
48+
rj = Client()
49+
rj.flushdb()
50+
51+
rj.JSONSet('num', Path.rootPath(), 1)
52+
self.assertEqual(2, rj.JSONNumMultBy('num', Path.rootPath(), 2))
53+
self.assertEqual(5, rj.JSONNumMultBy('num', Path.rootPath(), 2.5))
54+
self.assertEqual(2.5, rj.JSONNumMultBy('num', Path.rootPath(), 0.5))
55+
56+
def testStrAppendShouldSucceed(self):
57+
"Test JSONStrAppend"
58+
rj = Client()
59+
rj.flushdb()
60+
61+
rj.JSONSet('str', Path.rootPath(), 'foo')
62+
self.assertEqual(6, rj.JSONStrAppend('str', 'bar', Path.rootPath()))
63+
self.assertEqual('foobar', rj.JSONGet('str', Path.rootPath()))
64+
65+
def testStrLenShouldSucceed(self):
66+
"Test JSONStrLen"
67+
rj = Client()
68+
rj.flushdb()
69+
70+
rj.JSONSet('str', Path.rootPath(), 'foo')
71+
self.assertEqual(3, rj.JSONStrLen('str', Path.rootPath()))
72+
rj.JSONStrAppend('str', 'bar', Path.rootPath())
73+
self.assertEqual(6, rj.JSONStrLen('str', Path.rootPath()))
74+
3675
def testUsageExampleShouldSucceed(self):
3776
"Test the usage example"
3877

0 commit comments

Comments
 (0)