Skip to content

fix(redis): unwrap decorated __init__s when deriving the from_url kwargs allowlist - #36654

Merged
yassin-berriai merged 4 commits into
BerriAI:litellm_internal_stagingfrom
anmolg1997:fix/redis-url-kwargs-unwrap-deprecated-args
Aug 15, 2026
Merged

fix(redis): unwrap decorated __init__s when deriving the from_url kwargs allowlist#36654
yassin-berriai merged 4 commits into
BerriAI:litellm_internal_stagingfrom
anmolg1997:fix/redis-url-kwargs-unwrap-deprecated-args

Conversation

@anmolg1997

Copy link
Copy Markdown
Contributor

The regression

redis-py >= 7.4 decorates AbstractConnection.__init__ with @deprecated_args (redis/utils.py), whose wrapper is declared (self, *args, **kwargs). _init_arg_names introspects the wrapper directly, so from redis-py 7.4 the MRO walk loses every real connection parameter and the from_url allowlist silently drops socket_timeout/socket_connect_timeout again — the exact regression the allowlist rework (#35273) fixed, reintroduced one dependency version later from the other side. A url-configured Redis that blackholes packets (NetworkPolicy misconfig) then blocks callers indefinitely instead of timing out.

The fix

Follow the __wrapped__ chain with inspect.unwrap before introspecting each __init__. @deprecated_args uses functools.wraps, so the chain leads to the true signature; unwrap is a no-op for undecorated __init__s.

Measured (socket_timeout present in the derived allowlist, before -> after)

redis-py before after
6.4.0 yes yes
7.1.0 yes yes
7.4.1 no yes
8.1.0 no yes

tests/test_litellm/test_redis.py at redis-py 8.1.0: 10 failures before, 3 after — the residual trio (sentinel/cluster password handling) fails identically without this change and at 6.4.0, so it is unrelated. At 6.4.0 the module result is unchanged by this PR.

Tests added

  • test_init_arg_names_sees_through_decorated_inits — decorated-fake class proving the unwrap mechanism without depending on the installed redis-py.
  • test_url_allowlist_always_carries_socket_timeouts — live invariant against the installed redis-py; the first assertion to go red if a future release changes signature declaration again.

Found while pinning a downstream consumer's redis version: we bisected the allowlist across 6.4/7.1/7.4.1/8.1.0 and traced the loss to the decorator's signature shadowing.

yuneng-berri and others added 4 commits August 8, 2026 13:11
chore(ci): promote internal staging to main
chore(ci): promote internal staging to main
chore(ci): promote internal staging to main
…rgs allowlist

redis-py >= 7.4 decorates AbstractConnection.__init__ with @deprecated_args,
whose wrapper is declared (self, *args, **kwargs). _init_arg_names introspects
the wrapper directly, so from redis-py 7.4 the MRO walk loses every real
connection parameter and the from_url allowlist silently drops socket_timeout
and socket_connect_timeout again - the exact regression the allowlist rework
fixed, reintroduced one dependency version later. A url-configured Redis that
blackholes packets then blocks callers indefinitely instead of timing out.

Follow the __wrapped__ chain with inspect.unwrap before introspecting; a no-op
for undecorated __init__s.

Measured across redis-py lines (socket_timeout present in the allowlist):
6.4.0 before/after: yes/yes. 7.1.0: yes/yes. 7.4.1: NO/yes. 8.1.0: NO/yes.
tests/test_litellm/test_redis.py at redis-py 8.1.0: 10 failures before, 3
after (the residual trio is sentinel/cluster password handling, failing
identically without this change).

Two tests: a decorated-fake proving the unwrap mechanism, and a live-invariant
assertion that the installed redis-py's allowlist carries the socket timeouts -
the first thing to go red if a future redis-py changes signature declaration
again.
@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR unwraps decorated Redis connection initializers before deriving URL-compatible keyword arguments, restoring socket timeout forwarding with newer redis-py releases

  • Uses inspect.unwrap during MRO signature introspection
  • Adds synthetic decorator coverage and an installed-version timeout allowlist invariant

Confidence Score: 5/5

The PR appears safe to merge, with no concrete changed-code failure identified

The unwrap operation preserves undecorated behavior while recovering wrapped initializer signatures, and the new tests cover both the mechanism and resulting timeout allowlist

Important Files Changed

Filename Overview
litellm/_redis.py Correctly unwraps decorated Redis initializer functions before collecting accepted positional and keyword-only parameters
tests/test_litellm/test_redis.py Adds focused regression coverage without initiating Redis network traffic

Reviews (1): Last reviewed commit: "fix(redis): unwrap decorated __init__s w..." | Re-trigger Greptile

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing anmolg1997:fix/redis-url-kwargs-unwrap-deprecated-args (99716c5) with litellm_internal_staging (f64479e)

Open in CodSpeed

@yassin-berriai
yassin-berriai merged commit 592564d into BerriAI:litellm_internal_staging Aug 15, 2026
78 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants