mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-03 07:23:33 +00:00
fix(redis): register transport tests and pass CI gates
This commit is contained in:
parent
fe2f2f0e9d
commit
facaebccb2
4 changed files with 41 additions and 8 deletions
1
.github/workflows/test-unit.yml
vendored
1
.github/workflows/test-unit.yml
vendored
|
|
@ -669,6 +669,7 @@ jobs:
|
|||
- shard: caching-local
|
||||
test-path: >-
|
||||
tests/unit/caching
|
||||
tests/unit/redis
|
||||
python-version: "3.12"
|
||||
workers: 2
|
||||
reruns: 0
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import hashlib
|
||||
from collections.abc import Awaitable, Callable, Sequence
|
||||
from collections.abc import Awaitable, Callable, Iterator, Sequence
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import Final, Protocol, TypeVar
|
||||
|
|
@ -128,6 +128,27 @@ def _int_reply(reply: object) -> int | RedisFailure:
|
|||
|
||||
|
||||
def _eval_reply(reply: object) -> EvalReply | RedisFailure:
|
||||
frames: Final[list[tuple[Iterator[object], list[EvalReply]]]] = [ # mutable-ok: linear-time traversal stack
|
||||
(iter((reply,)), [])
|
||||
]
|
||||
while frames:
|
||||
pending, values = frames[-1]
|
||||
for item in pending:
|
||||
if (array := _array(item)) is not None:
|
||||
frames.append((iter(array), []))
|
||||
break
|
||||
if isinstance(scalar := _eval_scalar(item), RedisFailure):
|
||||
return scalar
|
||||
values.append(scalar)
|
||||
else:
|
||||
frames.pop()
|
||||
if not frames:
|
||||
return values[0]
|
||||
frames[-1][1].append(tuple(values))
|
||||
return _decode_failure(reply)
|
||||
|
||||
|
||||
def _eval_scalar(reply: object) -> int | bytes | None | RedisFailure:
|
||||
if isinstance(reply, RedisFailure) or reply is None or isinstance(reply, bytes):
|
||||
return reply
|
||||
if isinstance(reply, bool):
|
||||
|
|
@ -136,9 +157,4 @@ def _eval_reply(reply: object) -> EvalReply | RedisFailure:
|
|||
return reply
|
||||
if isinstance(reply, str):
|
||||
return reply.encode()
|
||||
array: Final = _array(reply)
|
||||
if array is None:
|
||||
return _decode_failure(reply)
|
||||
items: Final = tuple(_eval_reply(item) for item in array)
|
||||
failure: Final = next((item for item in items if isinstance(item, RedisFailure)), None)
|
||||
return failure if failure is not None else tuple(item for item in items if not isinstance(item, RedisFailure))
|
||||
return _decode_failure(reply)
|
||||
|
|
|
|||
|
|
@ -153,6 +153,22 @@ async def test_eval_namespaces_keys_and_returns_nested_replies(
|
|||
assert await raw.get("ns:k") == b"w"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("decode_responses", (False, True))
|
||||
async def test_eval_preserves_empty_arrays_and_sibling_order(
|
||||
server: fakeredis.FakeServer, decode_responses: bool
|
||||
) -> None:
|
||||
raw = fakeredis.FakeAsyncRedis(server=server, decode_responses=decode_responses)
|
||||
transport = fake_redis_transport(raw, failure_threshold=1)
|
||||
|
||||
assert await transport.eval('return {{}, {1, {"hello", {}}}, {}, 0}', (), ()) == (
|
||||
(),
|
||||
(1, (b"hello", ())),
|
||||
(),
|
||||
0,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_eval_survives_a_script_flush(server: fakeredis.FakeServer, raw: fakeredis.FakeAsyncRedis) -> None:
|
||||
transport = fake_redis_cache(server).transport()
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ _REPO: Final = Path(__file__).resolve().parents[2]
|
|||
|
||||
_REDIS_PRODUCER_ROOTS: Final = ("litellm", "enterprise")
|
||||
# The cache implementations and facades: they emit the service events, their callers declare the family.
|
||||
_CACHE_LAYER_DIRS: Final = ("litellm/caching", "litellm/_v2/cache")
|
||||
_CACHE_LAYER_DIRS: Final = ("litellm/caching", "litellm/_v2/cache", "litellm/redis/transport")
|
||||
# Helpers that act on a cache handed in by the declaring caller, or forward to the response-cache facade.
|
||||
_CACHE_PARAMETER_HELPERS: Final = frozenset(
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue