Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python: adds GEOHASH command #1281

Merged
merged 1 commit into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* Python: Added RENAME command ([#1252](https://github.com/aws/glide-for-redis/pull/1252))
* Python: Added APPEND command ([#1152](https://github.com/aws/glide-for-redis/pull/1152))
* Python: Added GEOADD command ([#1259](https://github.com/aws/glide-for-redis/pull/1259))
* Python: Added GEOHASH command ([#1281](https://github.com/aws/glide-for-redis/pull/1281))

#### Fixes
* Python: Fix typing error "‘type’ object is not subscriptable" ([#1203](https://github.com/aws/glide-for-redis/pull/1203))
Expand Down
1 change: 1 addition & 0 deletions glide-core/src/protobuf/redis_request.proto
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ enum RequestType {
SMIsMember = 118;
LastSave = 120;
GeoAdd = 121;
GeoHash = 122;
}

message Command {
Expand Down
3 changes: 3 additions & 0 deletions glide-core/src/request_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ pub enum RequestType {
SMIsMember = 118,
LastSave = 120,
GeoAdd = 121,
GeoHash = 122,
}

fn get_two_word_command(first: &str, second: &str) -> Cmd {
Expand Down Expand Up @@ -261,6 +262,7 @@ impl From<::protobuf::EnumOrUnknown<ProtobufRequestType>> for RequestType {
ProtobufRequestType::SMIsMember => RequestType::SMIsMember,
ProtobufRequestType::LastSave => RequestType::LastSave,
ProtobufRequestType::GeoAdd => RequestType::GeoAdd,
ProtobufRequestType::GeoHash => RequestType::GeoHash,
}
}
}
Expand Down Expand Up @@ -389,6 +391,7 @@ impl RequestType {
RequestType::SMIsMember => Some(cmd("SMISMEMBER")),
RequestType::LastSave => Some(cmd("LASTSAVE")),
RequestType::GeoAdd => Some(cmd("GEOADD")),
RequestType::GeoHash => Some(cmd("GEOHASH")),
}
}
}
25 changes: 25 additions & 0 deletions python/python/glide/async_commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1590,6 +1590,31 @@ async def geoadd(
await self._execute_command(RequestType.GeoAdd, args),
)

async def geohash(self, key: str, members: List[str]) -> List[Optional[str]]:
"""
Returns the GeoHash strings representing the positions of all the specified members in the sorted set stored at
`key`.

See https://valkey.io/commands/geohash for more details.

Args:
key (str): The key of the sorted set.
members (List[str]): The list of members whose GeoHash strings are to be retrieved.

Returns:
List[Optional[str]]: A list of GeoHash strings representing the positions of the specified members stored at `key`.
If a member does not exist in the sorted set, a None value is returned for that member.

Examples:
>>> await client.geoadd("my_geo_sorted_set", {"Palermo": GeospatialData(13.361389, 38.115556), "Catania": GeospatialData(15.087269, 37.502669)})
>>> await client.geohash("my_geo_sorted_set", ["Palermo", "Catania", "some city])
["sqc8b49rny0", "sqdtr74hyu0", None] # Indicates the GeoHash strings for the specified members.
"""
return cast(
List[Optional[str]],
await self._execute_command(RequestType.GeoHash, [key] + members),
)

async def zadd(
self,
key: str,
Expand Down
17 changes: 17 additions & 0 deletions python/python/glide/async_commands/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,23 @@ def geoadd(

return self.append_command(RequestType.GeoAdd, args)

def geohash(self: TTransaction, key: str, members: List[str]) -> TTransaction:
"""
Returns the GeoHash strings representing the positions of all the specified members in the sorted set stored at
`key`.

See https://valkey.io/commands/geohash for more details.

Args:
key (str): The key of the sorted set.
members (List[str]): The list of members whose GeoHash strings are to be retrieved.

Commands response:
List[Optional[str]]: A list of GeoHash strings representing the positions of the specified members stored at `key`.
If a member does not exist in the sorted set, a None value is returned for that member.
"""
return self.append_command(RequestType.GeoHash, [key] + members)

def zadd(
self: TTransaction,
key: str,
Expand Down
31 changes: 31 additions & 0 deletions python/python/tests/test_async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,37 @@ async def test_geoadd_invalid_args(self, redis_client: TRedisClient):
with pytest.raises(RequestError):
await redis_client.geoadd(key, {"Place": GeospatialData(0, -86)})

@pytest.mark.parametrize("cluster_mode", [True, False])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_geohash(self, redis_client: TRedisClient):
key = get_random_string(10)
members_coordinates = {
"Palermo": GeospatialData(13.361389, 38.115556),
"Catania": GeospatialData(15.087269, 37.502669),
}
assert await redis_client.geoadd(key, members_coordinates) == 2
assert await redis_client.geohash(key, ["Palermo", "Catania", "Place"]) == [
"sqc8b49rny0",
"sqdtr74hyu0",
None,
]

assert (
await redis_client.geohash(
"non_existing_key", ["Palermo", "Catania", "Place"]
)
== [None] * 3
)

# Neccessary to check since we are enforcing the user to pass a list of members while redis don't
# But when running the command with key only (and no members) the returned value will always be an empty list
# So in case of any changes, this test will fail and inform us that we should allow not passing any members.
assert await redis_client.geohash(key, []) == []

assert await redis_client.set(key, "value") == OK
with pytest.raises(RequestError):
await redis_client.geohash(key, ["Palermo", "Catania"])

@pytest.mark.parametrize("cluster_mode", [True, False])
@pytest.mark.parametrize("protocol", [ProtocolVersion.RESP2, ProtocolVersion.RESP3])
async def test_zadd_zaddincr(self, redis_client: TRedisClient):
Expand Down
2 changes: 2 additions & 0 deletions python/python/tests/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ async def transaction_test(
},
)
args.append(2)
transaction.geohash(key9, ["Palermo", "Catania", "Place"])
args.append(["sqc8b49rny0", "sqdtr74hyu0", None])
return args


Expand Down
Loading