diff options
author | shacharPash <93581407+shacharPash@users.noreply.github.com> | 2023-05-16 13:52:09 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-16 13:52:09 +0300 |
commit | 2d9b5ac6fe03fdc572b8ca47f7134082bae2a5e2 (patch) | |
tree | a0780069a09c8ce427d9e3676a6f33d07b3d95aa | |
parent | 35b7e09a57a1b7e2931d90e4b13858b68cee97cf (diff) | |
download | redis-py-master.tar.gz |
* support JSON.MERGE Command
* linters
* try with abc instead person
* change @skip_ifmodversion_lt to latest ReJSON 2.4.7
* change version
* fix test
* linters
* add async test
-rw-r--r-- | redis/commands/json/__init__.py | 1 | ||||
-rw-r--r-- | redis/commands/json/commands.py | 22 | ||||
-rw-r--r-- | tests/test_asyncio/test_json.py | 35 | ||||
-rw-r--r-- | tests/test_json.py | 33 |
4 files changed, 91 insertions, 0 deletions
diff --git a/redis/commands/json/__init__.py b/redis/commands/json/__init__.py index 7d55023..77fb21c 100644 --- a/redis/commands/json/__init__.py +++ b/redis/commands/json/__init__.py @@ -38,6 +38,7 @@ class JSON(JSONCommands): "JSON.GET": self._decode, "JSON.MGET": bulk_of_jsons(self._decode), "JSON.SET": lambda r: r and nativestr(r) == "OK", + "JSON.MERGE": lambda r: r and nativestr(r) == "OK", "JSON.NUMINCRBY": self._decode, "JSON.NUMMULTBY": self._decode, "JSON.TOGGLE": self._decode, diff --git a/redis/commands/json/commands.py b/redis/commands/json/commands.py index c02c47a..5da9245 100644 --- a/redis/commands/json/commands.py +++ b/redis/commands/json/commands.py @@ -253,6 +253,28 @@ class JSONCommands: pieces.append("XX") return self.execute_command("JSON.SET", *pieces) + def merge( + self, + name: str, + path: str, + obj: JsonType, + decode_keys: Optional[bool] = False, + ) -> Optional[str]: + """ + Sets or updates the JSON value at a path.. + + ``decode_keys`` If set to True, the keys of ``obj`` will be decoded + with utf-8. + + For more information see `JSON.MERGE <https://redis.io/commands/json.merge>`_. + """ + if decode_keys: + obj = decode_dict_keys(obj) + + pieces = [name, str(path), self._encode(obj)] + + return self.execute_command("JSON.MERGE", *pieces) + def set_file( self, name: str, diff --git a/tests/test_asyncio/test_json.py b/tests/test_asyncio/test_json.py index fc530c6..7334399 100644 --- a/tests/test_asyncio/test_json.py +++ b/tests/test_asyncio/test_json.py @@ -40,6 +40,41 @@ async def test_json_get_jset(modclient: redis.Redis): @pytest.mark.redismod +@skip_ifmodversion_lt("2.6.0", "ReJSON") # todo: update after the release +async def test_json_merge(modclient: redis.Redis): + # Test with root path $ + assert await modclient.json().set( + "person_data", + "$", + {"person1": {"personal_data": {"name": "John"}}}, + ) + assert await modclient.json().merge( + "person_data", "$", {"person1": {"personal_data": {"hobbies": "reading"}}} + ) + assert await modclient.json().get("person_data") == { + "person1": {"personal_data": {"name": "John", "hobbies": "reading"}} + } + + # Test with root path path $.person1.personal_data + assert await modclient.json().merge( + "person_data", "$.person1.personal_data", {"country": "Israel"} + ) + assert await modclient.json().get("person_data") == { + "person1": { + "personal_data": {"name": "John", "hobbies": "reading", "country": "Israel"} + } + } + + # Test with null value to delete a value + assert await modclient.json().merge( + "person_data", "$.person1.personal_data", {"name": None} + ) + assert await modclient.json().get("person_data") == { + "person1": {"personal_data": {"country": "Israel", "hobbies": "reading"}} + } + + +@pytest.mark.redismod async def test_nonascii_setgetdelete(modclient: redis.Redis): assert await modclient.json().set("notascii", Path.root_path(), "hyvää-élève") assert "hyvää-élève" == await modclient.json().get("notascii", no_escape=True) diff --git a/tests/test_json.py b/tests/test_json.py index 8e8da05..0a85998 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -48,6 +48,39 @@ def test_json_get_jset(client): @pytest.mark.redismod +@skip_ifmodversion_lt("2.6.0", "ReJSON") # todo: update after the release +def test_json_merge(client): + # Test with root path $ + assert client.json().set( + "person_data", + "$", + {"person1": {"personal_data": {"name": "John"}}}, + ) + assert client.json().merge( + "person_data", "$", {"person1": {"personal_data": {"hobbies": "reading"}}} + ) + assert client.json().get("person_data") == { + "person1": {"personal_data": {"name": "John", "hobbies": "reading"}} + } + + # Test with root path path $.person1.personal_data + assert client.json().merge( + "person_data", "$.person1.personal_data", {"country": "Israel"} + ) + assert client.json().get("person_data") == { + "person1": { + "personal_data": {"name": "John", "hobbies": "reading", "country": "Israel"} + } + } + + # Test with null value to delete a value + assert client.json().merge("person_data", "$.person1.personal_data", {"name": None}) + assert client.json().get("person_data") == { + "person1": {"personal_data": {"country": "Israel", "hobbies": "reading"}} + } + + +@pytest.mark.redismod def test_nonascii_setgetdelete(client): assert client.json().set("notascii", Path.root_path(), "hyvää-élève") assert "hyvää-élève" == client.json().get("notascii", no_escape=True) |