Skip to content

Commit b8a52f0

Browse files
committed
Adds array and object commands
1 parent e94aef6 commit b8a52f0

File tree

2 files changed

+160
-4
lines changed

2 files changed

+160
-4
lines changed

rejson/client.py

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ def float_or_long(n):
2020
else:
2121
return long(n)
2222

23+
def long_or_none(r):
24+
"Return a long or None from a Redis reply"
25+
if r:
26+
return long(r)
27+
return r
28+
2329
def json_or_none(r):
2430
"Return a deserialized JSON object or None"
2531
if r:
@@ -53,8 +59,15 @@ class Client(StrictRedis):
5359
'JSON.SET': lambda r: r and nativestr(r) == 'OK',
5460
'JSON.NUMINCRBY': float_or_long,
5561
'JSON.NUMMULTBY': float_or_long,
56-
'JSON.STRAPPEND': long,
57-
'JSON.STRLEN': long,
62+
'JSON.STRAPPEND': long_or_none,
63+
'JSON.STRLEN': long_or_none,
64+
'JSON.ARRAPPEND': long_or_none,
65+
'JSON.ARRINDEX': long_or_none,
66+
'JSON.ARRINSERT': long_or_none,
67+
'JSON.ARRLEN': long_or_none,
68+
'JSON.ARRPOP': json_or_none,
69+
'JSON.ARRTRIM': long_or_none,
70+
'JSON.OBJLEN': long_or_none,
5871
}
5972

6073
def __init__(self, **kwargs):
@@ -150,12 +163,78 @@ def JSONNumMultBy(self, name, path, number):
150163

151164
def JSONStrAppend(self, name, string, path=Path.rootPath()):
152165
"""
153-
Appends to the string JSON value under ``path`` at key ``name`` the provided ``string``
166+
Appends to the string JSON value under ``path`` at key ``name`` the
167+
provided ``string``
154168
"""
155169
return self.execute_command('JSON.STRAPPEND', name, str_path(path), json.dumps(string))
156170

157171
def JSONStrLen(self, name, path=Path.rootPath()):
158172
"""
159-
Returns the length of the string JSON value under ``path`` at key ``name``
173+
Returns the length of the string JSON value under ``path`` at key
174+
``name``
160175
"""
161176
return self.execute_command('JSON.STRLEN', name, str_path(path))
177+
178+
def JSONArrAppend(self, name, path=Path.rootPath(), *args):
179+
"""
180+
Appends the objects ``args`` to the array under the ``path` in key
181+
``name``
182+
"""
183+
pieces = [name, str_path(path)]
184+
for o in args:
185+
pieces.append(json.dumps(o))
186+
return self.execute_command('JSON.ARRAPPEND', *pieces)
187+
188+
def JSONArrIndex(self, name, path, scalar, start=0, stop=-1):
189+
"""
190+
Returns the index of ``scalar`` in the JSON array under ``path`` at key
191+
``name``. The search can be limited using the optional inclusive
192+
``start`` and exclusive ``stop`` indices.
193+
"""
194+
return self.execute_command('JSON.ARRINDEX', name, str_path(path), json.dumps(scalar), start, stop)
195+
196+
def JSONArrInsert(self, name, path, index, *args):
197+
"""
198+
Inserts the objects ``args`` to the array at index ``index`` under the
199+
``path` in key ``name``
200+
"""
201+
pieces = [name, str_path(path), index]
202+
for o in args:
203+
pieces.append(json.dumps(o))
204+
return self.execute_command('JSON.ARRINSERT', *pieces)
205+
206+
def JSONArrLen(self, name, path=Path.rootPath()):
207+
"""
208+
Returns the length of the array JSON value under ``path`` at key
209+
``name``
210+
"""
211+
return self.execute_command('JSON.ARRLEN', name, str_path(path))
212+
213+
def JSONArrPop(self, name, path=Path.rootPath(), index=-1):
214+
"""
215+
Pops the element at ``index`` in the array JSON value under ``path`` at
216+
key ``name``
217+
"""
218+
return self.execute_command('JSON.ARRPOP', name, str_path(path), index)
219+
220+
def JSONArrTrim(self, name, path, start, stop):
221+
"""
222+
Trim the array JSON value under ``path`` at key ``name`` to the
223+
inclusive range given by ``start`` and ``stop``
224+
"""
225+
return self.execute_command('JSON.ARRTRIM', name, str_path(path), start, stop)
226+
227+
def JSONObjKeys(self, name, path=Path.rootPath()):
228+
"""
229+
Returns the key names in the dictionary JSON value under ``path`` at key
230+
``name``
231+
"""
232+
return self.execute_command('JSON.OBJKEYS', name, str_path(path))
233+
234+
def JSONObjLen(self, name, path=Path.rootPath()):
235+
"""
236+
Returns the length of the dictionary JSON value under ``path`` at key
237+
``name``
238+
"""
239+
return self.execute_command('JSON.OBJLEN', name, str_path(path))
240+

test/test.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,83 @@ def testStrLenShouldSucceed(self):
7272
rj.JSONStrAppend('str', 'bar', Path.rootPath())
7373
self.assertEqual(6, rj.JSONStrLen('str', Path.rootPath()))
7474

75+
def testArrAppendShouldSucceed(self):
76+
"Test JSONSArrAppend"
77+
rj = Client()
78+
rj.flushdb()
79+
80+
rj.JSONSet('arr', Path.rootPath(), [1])
81+
self.assertEqual(2, rj.JSONArrAppend('arr', Path.rootPath(), 2))
82+
83+
def testArrIndexShouldSucceed(self):
84+
"Test JSONSArrIndex"
85+
rj = Client()
86+
rj.flushdb()
87+
88+
rj.JSONSet('arr', Path.rootPath(), [0, 1, 2, 3, 4])
89+
self.assertEqual(1, rj.JSONArrIndex('arr', Path.rootPath(), 1))
90+
self.assertEqual(-1, rj.JSONArrIndex('arr', Path.rootPath(), 1, 2))
91+
92+
def testArrInsertShouldSucceed(self):
93+
"Test JSONSArrInsert"
94+
rj = Client()
95+
rj.flushdb()
96+
97+
rj.JSONSet('arr', Path.rootPath(), [0, 4])
98+
self.assertEqual(5, rj.JSONArrInsert('arr', Path.rootPath(), 1, *[1, 2, 3,]))
99+
self.assertListEqual([0, 1, 2, 3, 4], rj.JSONGet('arr'))
100+
101+
def testArrLenShouldSucceed(self):
102+
"Test JSONSArrLen"
103+
rj = Client()
104+
rj.flushdb()
105+
106+
rj.JSONSet('arr', Path.rootPath(), [0, 1, 2, 3, 4])
107+
self.assertEqual(5, rj.JSONArrLen('arr', Path.rootPath()))
108+
109+
def testArrPopShouldSucceed(self):
110+
"Test JSONSArrPop"
111+
rj = Client()
112+
rj.flushdb()
113+
114+
rj.JSONSet('arr', Path.rootPath(), [0, 1, 2, 3, 4])
115+
self.assertEqual(4, rj.JSONArrPop('arr', Path.rootPath(), 4))
116+
self.assertEqual(3, rj.JSONArrPop('arr', Path.rootPath(), -1))
117+
self.assertEqual(2, rj.JSONArrPop('arr', Path.rootPath()))
118+
self.assertEqual(0, rj.JSONArrPop('arr', Path.rootPath(), 0))
119+
self.assertListEqual([1], rj.JSONGet('arr'))
120+
121+
def testArrTrimShouldSucceed(self):
122+
"Test JSONSArrPop"
123+
rj = Client()
124+
rj.flushdb()
125+
126+
rj.JSONSet('arr', Path.rootPath(), [0, 1, 2, 3, 4])
127+
self.assertEqual(3, rj.JSONArrTrim('arr', Path.rootPath(), 1, 3))
128+
self.assertListEqual([1, 2, 3], rj.JSONGet('arr'))
129+
130+
def testObjKeysShouldSucceed(self):
131+
"Test JSONSObjKeys"
132+
rj = Client()
133+
rj.flushdb()
134+
135+
obj = { 'foo': 'bar', 'baz': 'qaz' }
136+
rj.JSONSet('obj', Path.rootPath(), obj)
137+
keys = rj.JSONObjKeys('obj', Path.rootPath())
138+
keys.sort()
139+
exp = [k for k in obj.iterkeys()]
140+
exp.sort()
141+
self.assertListEqual(exp, keys)
142+
143+
def testObjLenShouldSucceed(self):
144+
"Test JSONSObjLen"
145+
rj = Client()
146+
rj.flushdb()
147+
148+
obj = { 'foo': 'bar', 'baz': 'qaz' }
149+
rj.JSONSet('obj', Path.rootPath(), obj)
150+
self.assertEqual(len(obj), rj.JSONObjLen('obj', Path.rootPath()))
151+
75152
def testUsageExampleShouldSucceed(self):
76153
"Test the usage example"
77154

0 commit comments

Comments
 (0)