Skip to content

Commit 30be3a3

Browse files
authored
Add type hints for JSON commands (#1921)
* add type hints for json commands * Change json.clear test multi to be up to date with redisjson (#1922) * fix json clear test * fix json clear test * Add support for BZMPOP (#1851) * add bzmpop * add comment * fix pr comment * fix linters * fix pr comments * add client no-evict (#1856) * Add support for ZINTERCARD (#1857) * add zintercard * fix pr comment * linters * Add support for EVAL_RO (#1862) * add sort_ro * mark test as onlynon cluster * delete mark test as onlynoncluster * add eval_ro * fix linters * delete sort_ro * fix pr comment * add type hints * add type hints * linters * Add support for EVALSHA_RO (#1863) * add evalsha-ro * fix pr comment * add type hints * add type hints * Fix naming conventions (#1872) * fix naming convention * fix worng changes * fix naming convention in rootPath
1 parent ba3134c commit 30be3a3

File tree

3 files changed

+89
-27
lines changed

3 files changed

+89
-27
lines changed

docs/examples/search_json_examples.ipynb

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@
5959
" \"city\": \"Tel Aviv\"\n",
6060
" }\n",
6161
"}\n",
62-
"r.json().set(\"user:1\", Path.rootPath(), user1)\n",
63-
"r.json().set(\"user:2\", Path.rootPath(), user2)\n",
64-
"r.json().set(\"user:3\", Path.rootPath(), user3)\n",
62+
"r.json().set(\"user:1\", Path.root_path(), user1)\n",
63+
"r.json().set(\"user:2\", Path.root_path(), user2)\n",
64+
"r.json().set(\"user:3\", Path.root_path(), user3)\n",
6565
"\n",
6666
"schema = (TextField(\"$.user.name\", as_name=\"name\"),TagField(\"$.user.city\", as_name=\"city\"), NumericField(\"$.user.age\", as_name=\"age\"))\n",
6767
"r.ft().create_index(schema, definition=IndexDefinition(prefix=[\"user:\"], index_type=IndexType.JSON))"

redis/commands/json/_util.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from typing import Any, Dict, List, Union
2+
3+
JsonType = Union[str, int, float, bool, None, Dict[str, Any], List[Any]]

redis/commands/json/commands.py

+83-24
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
import os
22
from json import JSONDecodeError, loads
3+
from typing import Dict, List, Optional, Union
34

45
from deprecated import deprecated
56

67
from redis.exceptions import DataError
78

9+
from ._util import JsonType
810
from .decoders import decode_dict_keys
911
from .path import Path
1012

1113

1214
class JSONCommands:
1315
"""json commands."""
1416

15-
def arrappend(self, name, path=Path.root_path(), *args):
17+
def arrappend(
18+
self, name: str, path: Optional[str] = Path.root_path(), *args: List[JsonType]
19+
) -> List[Union[int, None]]:
1620
"""Append the objects ``args`` to the array under the
1721
``path` in key ``name``.
1822
@@ -23,7 +27,14 @@ def arrappend(self, name, path=Path.root_path(), *args):
2327
pieces.append(self._encode(o))
2428
return self.execute_command("JSON.ARRAPPEND", *pieces)
2529

26-
def arrindex(self, name, path, scalar, start=0, stop=-1):
30+
def arrindex(
31+
self,
32+
name: str,
33+
path: str,
34+
scalar: int,
35+
start: Optional[int] = 0,
36+
stop: Optional[int] = -1,
37+
) -> List[Union[int, None]]:
2738
"""
2839
Return the index of ``scalar`` in the JSON array under ``path`` at key
2940
``name``.
@@ -37,7 +48,9 @@ def arrindex(self, name, path, scalar, start=0, stop=-1):
3748
"JSON.ARRINDEX", name, str(path), self._encode(scalar), start, stop
3849
)
3950

40-
def arrinsert(self, name, path, index, *args):
51+
def arrinsert(
52+
self, name: str, path: str, index: int, *args: List[JsonType]
53+
) -> List[Union[int, None]]:
4154
"""Insert the objects ``args`` to the array at index ``index``
4255
under the ``path` in key ``name``.
4356
@@ -48,61 +61,73 @@ def arrinsert(self, name, path, index, *args):
4861
pieces.append(self._encode(o))
4962
return self.execute_command("JSON.ARRINSERT", *pieces)
5063

51-
def arrlen(self, name, path=Path.root_path()):
64+
def arrlen(
65+
self, name: str, path: Optional[str] = Path.root_path()
66+
) -> List[Union[int, None]]:
5267
"""Return the length of the array JSON value under ``path``
5368
at key``name``.
5469
5570
For more information: https://oss.redis.com/redisjson/commands/#jsonarrlen
5671
""" # noqa
5772
return self.execute_command("JSON.ARRLEN", name, str(path))
5873

59-
def arrpop(self, name, path=Path.root_path(), index=-1):
74+
def arrpop(
75+
self,
76+
name: str,
77+
path: Optional[str] = Path.root_path(),
78+
index: Optional[int] = -1,
79+
) -> List[Union[str, None]]:
80+
6081
"""Pop the element at ``index`` in the array JSON value under
6182
``path`` at key ``name``.
6283
6384
For more information: https://oss.redis.com/redisjson/commands/#jsonarrpop
6485
""" # noqa
6586
return self.execute_command("JSON.ARRPOP", name, str(path), index)
6687

67-
def arrtrim(self, name, path, start, stop):
88+
def arrtrim(
89+
self, name: str, path: str, start: int, stop: int
90+
) -> List[Union[int, None]]:
6891
"""Trim the array JSON value under ``path`` at key ``name`` to the
6992
inclusive range given by ``start`` and ``stop``.
7093
7194
For more information: https://oss.redis.com/redisjson/commands/#jsonarrtrim
7295
""" # noqa
7396
return self.execute_command("JSON.ARRTRIM", name, str(path), start, stop)
7497

75-
def type(self, name, path=Path.root_path()):
98+
def type(self, name: str, path: Optional[str] = Path.root_path()) -> List[str]:
7699
"""Get the type of the JSON value under ``path`` from key ``name``.
77100
78101
For more information: https://oss.redis.com/redisjson/commands/#jsontype
79102
""" # noqa
80103
return self.execute_command("JSON.TYPE", name, str(path))
81104

82-
def resp(self, name, path=Path.root_path()):
105+
def resp(self, name: str, path: Optional[str] = Path.root_path()) -> List:
83106
"""Return the JSON value under ``path`` at key ``name``.
84107
85108
For more information: https://oss.redis.com/redisjson/commands/#jsonresp
86109
""" # noqa
87110
return self.execute_command("JSON.RESP", name, str(path))
88111

89-
def objkeys(self, name, path=Path.root_path()):
112+
def objkeys(
113+
self, name: str, path: Optional[str] = Path.root_path()
114+
) -> List[Union[List[str], None]]:
90115
"""Return the key names in the dictionary JSON value under ``path`` at
91116
key ``name``.
92117
93118
For more information: https://oss.redis.com/redisjson/commands/#jsonobjkeys
94119
""" # noqa
95120
return self.execute_command("JSON.OBJKEYS", name, str(path))
96121

97-
def objlen(self, name, path=Path.root_path()):
122+
def objlen(self, name: str, path: Optional[str] = Path.root_path()) -> int:
98123
"""Return the length of the dictionary JSON value under ``path`` at key
99124
``name``.
100125
101126
For more information: https://oss.redis.com/redisjson/commands/#jsonobjlen
102127
""" # noqa
103128
return self.execute_command("JSON.OBJLEN", name, str(path))
104129

105-
def numincrby(self, name, path, number):
130+
def numincrby(self, name: str, path: str, number: int) -> str:
106131
"""Increment the numeric (integer or floating point) JSON value under
107132
``path`` at key ``name`` by the provided ``number``.
108133
@@ -113,7 +138,7 @@ def numincrby(self, name, path, number):
113138
)
114139

115140
@deprecated(version="4.0.0", reason="deprecated since redisjson 1.0.0")
116-
def nummultby(self, name, path, number):
141+
def nummultby(self, name: str, path: str, number: int) -> str:
117142
"""Multiply the numeric (integer or floating point) JSON value under
118143
``path`` at key ``name`` with the provided ``number``.
119144
@@ -123,7 +148,7 @@ def nummultby(self, name, path, number):
123148
"JSON.NUMMULTBY", name, str(path), self._encode(number)
124149
)
125150

126-
def clear(self, name, path=Path.root_path()):
151+
def clear(self, name: str, path: Optional[str] = Path.root_path()) -> int:
127152
"""
128153
Empty arrays and objects (to have zero slots/keys without deleting the
129154
array/object).
@@ -135,7 +160,7 @@ def clear(self, name, path=Path.root_path()):
135160
""" # noqa
136161
return self.execute_command("JSON.CLEAR", name, str(path))
137162

138-
def delete(self, key, path=Path.root_path()):
163+
def delete(self, key: str, path: Optional[str] = Path.root_path()) -> int:
139164
"""Delete the JSON value stored at key ``key`` under ``path``.
140165
141166
For more information: https://oss.redis.com/redisjson/commands/#jsondel
@@ -145,7 +170,9 @@ def delete(self, key, path=Path.root_path()):
145170
# forget is an alias for delete
146171
forget = delete
147172

148-
def get(self, name, *args, no_escape=False):
173+
def get(
174+
self, name: str, *args, no_escape: Optional[bool] = False
175+
) -> List[JsonType]:
149176
"""
150177
Get the object stored as a JSON value at key ``name``.
151178
@@ -173,7 +200,7 @@ def get(self, name, *args, no_escape=False):
173200
except TypeError:
174201
return None
175202

176-
def mget(self, keys, path):
203+
def mget(self, keys: List[str], path: str) -> List[JsonType]:
177204
"""
178205
Get the objects stored as a JSON values under ``path``. ``keys``
179206
is a list of one or more keys.
@@ -185,7 +212,15 @@ def mget(self, keys, path):
185212
pieces.append(str(path))
186213
return self.execute_command("JSON.MGET", *pieces)
187214

188-
def set(self, name, path, obj, nx=False, xx=False, decode_keys=False):
215+
def set(
216+
self,
217+
name: str,
218+
path: str,
219+
obj: JsonType,
220+
nx: Optional[bool] = False,
221+
xx: Optional[bool] = False,
222+
decode_keys: Optional[bool] = False,
223+
) -> Optional[str]:
189224
"""
190225
Set the JSON value at key ``name`` under the ``path`` to ``obj``.
191226
@@ -216,7 +251,15 @@ def set(self, name, path, obj, nx=False, xx=False, decode_keys=False):
216251
pieces.append("XX")
217252
return self.execute_command("JSON.SET", *pieces)
218253

219-
def set_file(self, name, path, file_name, nx=False, xx=False, decode_keys=False):
254+
def set_file(
255+
self,
256+
name: str,
257+
path: str,
258+
file_name: str,
259+
nx: Optional[bool] = False,
260+
xx: Optional[bool] = False,
261+
decode_keys: Optional[bool] = False,
262+
) -> Optional[str]:
220263
"""
221264
Set the JSON value at key ``name`` under the ``path`` to the content
222265
of the json file ``file_name``.
@@ -233,7 +276,14 @@ def set_file(self, name, path, file_name, nx=False, xx=False, decode_keys=False)
233276

234277
return self.set(name, path, file_content, nx=nx, xx=xx, decode_keys=decode_keys)
235278

236-
def set_path(self, json_path, root_folder, nx=False, xx=False, decode_keys=False):
279+
def set_path(
280+
self,
281+
json_path: str,
282+
root_folder: str,
283+
nx: Optional[bool] = False,
284+
xx: Optional[bool] = False,
285+
decode_keys: Optional[bool] = False,
286+
) -> List[Dict[str, bool]]:
237287
"""
238288
Iterate over ``root_folder`` and set each JSON file to a value
239289
under ``json_path`` with the file name as the key.
@@ -264,7 +314,7 @@ def set_path(self, json_path, root_folder, nx=False, xx=False, decode_keys=False
264314

265315
return set_files_result
266316

267-
def strlen(self, name, path=None):
317+
def strlen(self, name: str, path: Optional[str] = None) -> List[Union[int, None]]:
268318
"""Return the length of the string JSON value under ``path`` at key
269319
``name``.
270320
@@ -275,15 +325,19 @@ def strlen(self, name, path=None):
275325
pieces.append(str(path))
276326
return self.execute_command("JSON.STRLEN", *pieces)
277327

278-
def toggle(self, name, path=Path.root_path()):
328+
def toggle(
329+
self, name: str, path: Optional[str] = Path.root_path()
330+
) -> Union[bool, List[Optional[int]]]:
279331
"""Toggle boolean value under ``path`` at key ``name``.
280332
returning the new value.
281333
282334
For more information: https://oss.redis.com/redisjson/commands/#jsontoggle
283335
""" # noqa
284336
return self.execute_command("JSON.TOGGLE", name, str(path))
285337

286-
def strappend(self, name, value, path=Path.root_path()):
338+
def strappend(
339+
self, name: str, value: str, path: Optional[int] = Path.root_path()
340+
) -> Union[int, List[Optional[int]]]:
287341
"""Append to the string JSON value. If two options are specified after
288342
the key name, the path is determined to be the first. If a single
289343
option is passed, then the root_path (i.e Path.root_path()) is used.
@@ -293,11 +347,16 @@ def strappend(self, name, value, path=Path.root_path()):
293347
pieces = [name, str(path), self._encode(value)]
294348
return self.execute_command("JSON.STRAPPEND", *pieces)
295349

296-
def debug(self, subcommand, key=None, path=Path.root_path()):
350+
def debug(
351+
self,
352+
subcommand: str,
353+
key: Optional[str] = None,
354+
path: Optional[str] = Path.root_path(),
355+
) -> Union[int, List[str]]:
297356
"""Return the memory usage in bytes of a value under ``path`` from
298357
key ``name``.
299358
300-
For more information: https://oss.redis.com/redisjson/commands/#jsondebg
359+
For more information: https://oss.redis.com/redisjson/commands/#jsondebug
301360
""" # noqa
302361
valid_subcommands = ["MEMORY", "HELP"]
303362
if subcommand not in valid_subcommands:

0 commit comments

Comments
 (0)