- Notifications
You must be signed in to change notification settings - Fork 2.6k
Open
Description
Description
In redis-py, the spop method is available on both sync and asyncio clients.
However, the type hints for the asyncio client incorrectly declare a synchronous return type, which causes static type checkers (e.g. mypy) to report errors when using await.
Current implementation
In redis/commands/core.py, spop is defined as:
redis-py/redis/commands/core.py
Lines 3624 to 3631 in 0894218
| def spop(self, name: KeyT, count: Optional[int] = None) -> Union[str, List, None]: | |
| """ | |
| Remove and return a random member of set ``name`` | |
| For more information, see https://redis.io/commands/spop | |
| """ | |
| args = (count is not None) and [count] or [] | |
| return self.execute_command("SPOP", name, *args) |
Problem
redis.asyncio.Redis.execute_command()returns an awaitable- Therefore,
spop()on an asyncio client must be awaited at runtime - But the declared return type is:
Union[str, List, None]This causes type checkers to raise errors such as:
Incompatible types in "await" (actual type "str | list[Any] | None", expected type "Awaitable[Any]") even though the code is correct and required at runtime:
result = await redis_instance.spop(key, count)Expected behavior
For the asyncio client, the return type should be wrapped in Awaitable, for example:
from typing import Awaitable, Optional, Union, List def spop( self, name: KeyT, count: Optional[int] = None ) -> Awaitable[Optional[Union[str, List]]]: ...or, if overloads are preferred:
@overload def spop(self, name: KeyT, count: None = None) -> Awaitable[Optional[str]]: ... @overload def spop(self, name: KeyT, count: int) -> Awaitable[Optional[List[str]]]: ...Impact
- Breaks
mypyand other static type checkers when usingredis.asyncio - Forces users to use
# type: ignoreor unsafecast() - The issue affects
spopand potentially other set-related commands with similar signatures
Environment
- redis version:
^6.4.0(asyncio client) - Python:
3.12+ - Type checker:
mypy
Metadata
Metadata
Assignees
Labels
No labels