Skip to content

Instantly share code, notes, and snippets.

@mahenzon
Created January 5, 2026 10:32
Show Gist options
  • Select an option

  • Save mahenzon/36490d9b0124f1033522dcb1936903ea to your computer and use it in GitHub Desktop.

Select an option

Save mahenzon/36490d9b0124f1033522dcb1936903ea to your computer and use it in GitHub Desktop.
how Redis-py annotations can be fixed for public methods
"""
Suggestion for implementing
https://github.com/redis/redis-py/pull/3619
Try it here:
https://mypy-play.net/?mypy=latest&python=3.14&gist=bded9af8fe83b0625ad6bf72ad4b9338&flags=strict
"""
from typing import Awaitable, Generic, Literal, TypeVar, overload, reveal_type
OptionalDecodedString = str | None
OptionalEncodedString = bytes | None
OptionalAnyString = OptionalDecodedString | OptionalEncodedString
ResponseTypeOptionalAnyString = TypeVar(
"ResponseTypeOptionalAnyString",
bound=Awaitable[OptionalAnyString] | OptionalAnyString,
)
class BasicCommands(
Generic[ResponseTypeOptionalAnyString],
):
def get(self, key: str) -> ResponseTypeOptionalAnyString:
# dummy method
return f"value-from-{key}" # type: ignore[return-value]
class Redis(BasicCommands[ResponseTypeOptionalAnyString]):
@overload
def __init__(
self: Redis[OptionalAnyString],
decode_responses: bool,
): ...
@overload
def __init__(
self: Redis[OptionalDecodedString],
decode_responses: Literal[True],
): ...
@overload
def __init__(
self: Redis[OptionalEncodedString],
decode_responses: Literal[False],
): ...
@overload
def __init__(
self: Redis[OptionalEncodedString],
decode_responses: Literal[False] = False,
): ...
def __init__(self, decode_responses: bool = False):
self.decode_responses = decode_responses
class AsyncRedis(BasicCommands[ResponseTypeOptionalAnyString]):
@overload
def __init__(
self: AsyncRedis[Awaitable[OptionalAnyString]],
decode_responses: bool,
): ...
@overload
def __init__(
self: AsyncRedis[Awaitable[OptionalDecodedString]],
decode_responses: Literal[True],
): ...
@overload
def __init__(
self: AsyncRedis[Awaitable[OptionalEncodedString]],
decode_responses: Literal[False],
): ...
@overload
def __init__(
self: AsyncRedis[Awaitable[OptionalEncodedString]],
decode_responses: Literal[False] = False,
): ...
def __init__(self, decode_responses: bool = False):
self.decode_responses = decode_responses
async def main() -> None:
decode_responses = bool("Any value. May be True or False. Resolved only at runtime.")
redis_sync_decoded = Redis(decode_responses=True)
redis_sync_encoded = Redis(decode_responses=False)
redis_sync_encoded_default = Redis()
redis_sync = Redis(decode_responses=decode_responses)
redis_async_decoded = AsyncRedis(decode_responses=True)
redis_async_encoded = AsyncRedis(decode_responses=False)
redis_async_encoded_default = AsyncRedis()
redis_async = AsyncRedis(decode_responses=decode_responses)
key = "key"
value_from_redis_sync_decoded = redis_sync_decoded.get(key)
# note: Revealed type is "builtins.str | None"
reveal_type(value_from_redis_sync_decoded)
value_from_redis_sync_encoded = redis_sync_encoded.get(key)
# note: Revealed type is "builtins.bytes | None"
reveal_type(value_from_redis_sync_encoded)
value_from_redis_sync_encoded_default = redis_sync_encoded_default.get(key)
# note: Revealed type is "builtins.bytes | None"
reveal_type(value_from_redis_sync_encoded_default)
value_from_redis_sync = redis_sync.get(key)
# note: Revealed type is "builtins.str | None | builtins.bytes"
reveal_type(value_from_redis_sync)
value_from_redis_async_decoded = await redis_async_decoded.get(key)
# note: Revealed type is "builtins.str | None"
reveal_type(value_from_redis_async_decoded)
value_from_redis_async_encoded = await redis_async_encoded.get(key)
# note: Revealed type is "builtins.bytes | None"
reveal_type(value_from_redis_async_encoded)
value_from_redis_async_encoded_default = await redis_async_encoded_default.get(key)
# note: Revealed type is "builtins.bytes | None"
reveal_type(value_from_redis_async_encoded_default)
value_from_redis_async = await redis_async.get(key)
# note: Revealed type is "builtins.str | None | builtins.bytes | None"
reveal_type(value_from_redis_async)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment