Skip to content

Issue: redis.asyncio.Redis.spop type hint is incorrect (missing Awaitable) #3886

@kkeolmusae

Description

@kkeolmusae

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:

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 mypy and other static type checkers when using redis.asyncio
  • Forces users to use # type: ignore or unsafe cast()
  • The issue affects spop and 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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions