From 840d12f8146a1d133922160c56f15a772b6b6f5e Mon Sep 17 00:00:00 2001 From: Deepanshu Date: Fri, 21 Aug 2026 09:54:37 -0400 Subject: [PATCH] fix(rate-limiting): satisfy stricter test-lint and type-discipline gates picked up by rebase The base branch added a stricter ruff config for tests (PT011/B017) and this branch's own type-discipline gate flagged a mutable dict type annotation -- neither introduced by this branch's own changes, both surfaced by rebasing onto a newer base. Narrowed the blind pytest.raises(Exception/ValueError) assertions to ValidationError with a match on the actual validator message, and annotated a Redis read-only result as Mapping instead of dict. --- litellm/proxy/hooks/tag_rate_limiter.py | 5 +++-- .../test_litellm/proxy/hooks/test_tag_rate_limiter.py | 11 ++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/litellm/proxy/hooks/tag_rate_limiter.py b/litellm/proxy/hooks/tag_rate_limiter.py index 63c408cdd5d..e8b727b6736 100644 --- a/litellm/proxy/hooks/tag_rate_limiter.py +++ b/litellm/proxy/hooks/tag_rate_limiter.py @@ -1151,10 +1151,11 @@ class _PROXY_TagRateLimiter( # pyright: ignore[reportUnusedClass] # only refer # bypassing that in-memory layer, is the only way this # read-then-later-increment split stays coherent. # not `Final`: rebound each loop iteration, which basedpyright's - # LIT010/Final-in-loop check forbids; explicitly typed since + # LIT010/Final-in-loop check forbids; explicitly typed (as the + # read-only supertype, since this is never mutated) since # RedisCache.async_batch_get_cache's own signature returns a # bare, unparameterized dict - redis_values: dict[str, object] = await redis_cache.async_batch_get_cache( + redis_values: Mapping[str, object] = await redis_cache.async_batch_get_cache( key_list=keys, parent_otel_span=parent_otel_span ) resolved = [redis_values.get(key) for key in keys] # mutable-ok: needs a real list diff --git a/tests/test_litellm/proxy/hooks/test_tag_rate_limiter.py b/tests/test_litellm/proxy/hooks/test_tag_rate_limiter.py index 8ca45f9dbd6..d6b7b744657 100644 --- a/tests/test_litellm/proxy/hooks/test_tag_rate_limiter.py +++ b/tests/test_litellm/proxy/hooks/test_tag_rate_limiter.py @@ -12,6 +12,7 @@ from types import SimpleNamespace from typing import Final import pytest +from pydantic import ValidationError import litellm from litellm.caching.dual_cache import DualCache @@ -239,12 +240,12 @@ def test_extract_team_id_ignores_a_forged_value_in_the_non_authoritative_field() def test_tag_rate_limit_entry_rejects_zero_period_seconds(): - with pytest.raises(Exception): + with pytest.raises(ValidationError, match="period_seconds must be a positive integer"): TagRateLimitEntry(name="n", limit=1, period_seconds=0) def test_tag_rate_limit_entry_rejects_negative_period_seconds(): - with pytest.raises(Exception): + with pytest.raises(ValidationError, match="period_seconds must be a positive integer"): TagRateLimitEntry(name="n", limit=1, period_seconds=-1) @@ -3409,7 +3410,7 @@ def test_ttl_for_concurrency_never_drops_below_the_safety_floor_even_with_a_lowe def test_tag_rate_limit_entry_rejects_non_positive_key_ttl_seconds(): - with pytest.raises(ValueError): + with pytest.raises(ValidationError, match="key_ttl_seconds must be a positive integer"): TagRateLimitEntry(name="per_minute", limit=1, period_seconds=60, key_ttl_seconds=0) @@ -3420,7 +3421,7 @@ def test_tag_rate_limit_entry_rejects_key_ttl_seconds_shorter_than_period_second resetting the counter to zero mid-window and letting tagged traffic exceed the configured limit. """ - with pytest.raises(ValueError): + with pytest.raises(ValidationError, match="key_ttl_seconds must be at least period_seconds"): TagRateLimitEntry(name="per_minute", limit=1, period_seconds=60, key_ttl_seconds=59) @@ -3430,7 +3431,7 @@ def test_tag_rate_limit_entry_rejects_key_ttl_seconds_shorter_than_period_second def test_tag_rate_limit_entry_rejects_non_positive_max_in_memory_cache_size(): - with pytest.raises(ValueError): + with pytest.raises(ValidationError, match="max_in_memory_cache_size must be a positive integer"): TagRateLimitEntry(name="per_minute", limit=1, period_seconds=60, max_in_memory_cache_size=0)