Skip to content

Commit b098c98

Browse files
committed
fix(deps): upgrade redisvl to 0.5.1 for Python 3.13 compatibility
1 parent 2a69947 commit b098c98

File tree

8 files changed

+119
-33
lines changed

8 files changed

+119
-33
lines changed

langgraph/checkpoint/redis/base.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,19 @@ async def aset_client_info(self) -> None:
154154
"""Set client info for Redis monitoring asynchronously."""
155155
from redis.exceptions import ResponseError
156156

157-
from langgraph.checkpoint.redis.version import __full_lib_name__
157+
from langgraph.checkpoint.redis.version import __lib_name__, __redisvl_version__
158+
159+
# Create the client info string with only the redisvl version
160+
client_info = f"redis-py(redisvl_v{__redisvl_version__})"
158161

159162
try:
160163
# Try to use client_setinfo command if available
161-
await self._redis.client_setinfo("LIB-NAME", __full_lib_name__) # type: ignore
164+
await self._redis.client_setinfo("LIB-NAME", client_info) # type: ignore
162165
except (ResponseError, AttributeError):
163166
# Fall back to a simple echo if client_setinfo is not available
164167
try:
165168
# Call with await to ensure it's an async call
166-
echo_result = self._redis.echo(__full_lib_name__)
169+
echo_result = self._redis.echo(client_info)
167170
if hasattr(echo_result, "__await__"):
168171
await echo_result
169172
except Exception:

langgraph/store/redis/base.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -252,15 +252,18 @@ def set_client_info(self) -> None:
252252
"""Set client info for Redis monitoring."""
253253
from redis.exceptions import ResponseError
254254

255-
from langgraph.checkpoint.redis.version import __full_lib_name__
255+
from langgraph.checkpoint.redis.version import __redisvl_version__
256+
257+
# Create the client info string with only the redisvl version
258+
client_info = f"redis-py(redisvl_v{__redisvl_version__})"
256259

257260
try:
258261
# Try to use client_setinfo command if available
259-
self._redis.client_setinfo("LIB-NAME", __full_lib_name__) # type: ignore
262+
self._redis.client_setinfo("LIB-NAME", client_info) # type: ignore
260263
except (ResponseError, AttributeError):
261264
# Fall back to a simple echo if client_setinfo is not available
262265
try:
263-
self._redis.echo(__full_lib_name__)
266+
self._redis.echo(client_info)
264267
except Exception:
265268
# Silently fail if even echo doesn't work
266269
pass
@@ -269,16 +272,19 @@ async def aset_client_info(self) -> None:
269272
"""Set client info for Redis monitoring asynchronously."""
270273
from redis.exceptions import ResponseError
271274

272-
from langgraph.checkpoint.redis.version import __full_lib_name__
275+
from langgraph.checkpoint.redis.version import __redisvl_version__
276+
277+
# Create the client info string with only the redisvl version
278+
client_info = f"redis-py(redisvl_v{__redisvl_version__})"
273279

274280
try:
275281
# Try to use client_setinfo command if available
276-
await self._redis.client_setinfo("LIB-NAME", __full_lib_name__) # type: ignore
282+
await self._redis.client_setinfo("LIB-NAME", client_info) # type: ignore
277283
except (ResponseError, AttributeError):
278284
# Fall back to a simple echo if client_setinfo is not available
279285
try:
280286
# Call with await to ensure it's an async call
281-
echo_result = self._redis.echo(__full_lib_name__)
287+
echo_result = self._redis.echo(client_info)
282288
if hasattr(echo_result, "__await__"):
283289
await echo_result
284290
except Exception:

poetry.lock

+36-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ packages = [{ include = "langgraph" }]
2020
[tool.poetry.dependencies]
2121
python = ">=3.9,<3.14"
2222
langgraph-checkpoint = "^2.0.24"
23-
redisvl = "^0.4.1"
23+
redisvl = "^0.5.1"
2424
redis = "^5.2.1"
2525
python-ulid = "^3.0.0"
2626
langgraph = "^0.3.0"

tests/test_async.py

+22-5
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,10 @@ async def test_from_conn_string_cleanup(redis_url: str) -> None:
285285
@pytest.mark.asyncio
286286
async def test_async_client_info_setting(redis_url: str, monkeypatch) -> None:
287287
"""Test that async client_setinfo is called with correct library information."""
288-
from langgraph.checkpoint.redis.version import __full_lib_name__
288+
from langgraph.checkpoint.redis.version import __redisvl_version__
289+
290+
# Expected client info format
291+
expected_client_info = f"redis-py(redisvl_v{__redisvl_version__})"
289292

290293
# Track if client_setinfo was called with the right parameters
291294
client_info_called = False
@@ -298,7 +301,7 @@ async def mock_client_setinfo(self, key, value):
298301
nonlocal client_info_called
299302
# Note: RedisVL might call this with its own lib name first
300303
# We only track calls with our full lib name
301-
if key == "LIB-NAME" and __full_lib_name__ in value:
304+
if key == "LIB-NAME" and value == expected_client_info:
302305
client_info_called = True
303306
# Call original method to ensure normal function
304307
return await original_client_setinfo(self, key, value)
@@ -320,7 +323,10 @@ async def test_async_client_info_fallback_to_echo(redis_url: str, monkeypatch) -
320323
"""Test that async client_setinfo falls back to echo when not available."""
321324
from redis.exceptions import ResponseError
322325

323-
from langgraph.checkpoint.redis.version import __full_lib_name__
326+
from langgraph.checkpoint.redis.version import __redisvl_version__
327+
328+
# Expected client info format
329+
expected_client_info = f"redis-py(redisvl_v{__redisvl_version__})"
324330

325331
# Remove client_setinfo to simulate older Redis version
326332
async def mock_client_setinfo(self, key, value):
@@ -334,7 +340,7 @@ async def mock_client_setinfo(self, key, value):
334340
async def mock_echo(self, message):
335341
nonlocal echo_called
336342
echo_called = True
337-
assert message == __full_lib_name__
343+
assert message == expected_client_info
338344
return await original_echo(self, message)
339345

340346
# Apply the mocks
@@ -357,14 +363,25 @@ async def test_async_client_info_graceful_failure(redis_url: str, monkeypatch) -
357363
"""Test that async client info setting fails gracefully when all methods fail."""
358364
from redis.exceptions import ResponseError
359365

366+
# Create a patch for the RedisVL validation to avoid it using echo
367+
from redisvl.redis.connection import RedisConnectionFactory
368+
original_validate = RedisConnectionFactory.validate_async_redis
369+
370+
# Create a replacement validation function that doesn't use echo
371+
async def mock_validate(redis_client, lib_name=None):
372+
return redis_client
373+
374+
# Apply the validation mock first to prevent echo from being called by RedisVL
375+
monkeypatch.setattr(RedisConnectionFactory, "validate_async_redis", mock_validate)
376+
360377
# Simulate failures for both methods
361378
async def mock_client_setinfo(self, key, value):
362379
raise ResponseError("ERR unknown command")
363380

364381
async def mock_echo(self, message):
365382
raise ResponseError("ERR connection broken")
366383

367-
# Apply the mocks
384+
# Apply the Redis mocks
368385
monkeypatch.setattr(Redis, "client_setinfo", mock_client_setinfo)
369386
monkeypatch.setattr(Redis, "echo", mock_echo)
370387

tests/test_async_store.py

+22-5
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,10 @@ async def test_async_redis_store_client_info(redis_url: str, monkeypatch) -> Non
547547
"""Test that AsyncRedisStore sets client info correctly."""
548548
from redis.asyncio import Redis
549549

550-
from langgraph.checkpoint.redis.version import __full_lib_name__
550+
from langgraph.checkpoint.redis.version import __redisvl_version__
551+
552+
# Expected client info format
553+
expected_client_info = f"redis-py(redisvl_v{__redisvl_version__})"
551554

552555
# Track if client_setinfo was called with the right parameters
553556
client_info_called = False
@@ -560,7 +563,7 @@ async def mock_client_setinfo(self, key, value):
560563
nonlocal client_info_called
561564
# Note: RedisVL might call this with its own lib name first
562565
# We only track calls with our full lib name
563-
if key == "LIB-NAME" and __full_lib_name__ in value:
566+
if key == "LIB-NAME" and value == expected_client_info:
564567
client_info_called = True
565568
# Call original method to ensure normal function
566569
return await original_client_setinfo(self, key, value)
@@ -584,7 +587,10 @@ async def test_async_redis_store_client_info_fallback(
584587
from redis.asyncio import Redis
585588
from redis.exceptions import ResponseError
586589

587-
from langgraph.checkpoint.redis.version import __full_lib_name__
590+
from langgraph.checkpoint.redis.version import __redisvl_version__
591+
592+
# Expected client info format
593+
expected_client_info = f"redis-py(redisvl_v{__redisvl_version__})"
588594

589595
# Remove client_setinfo to simulate older Redis version
590596
async def mock_client_setinfo(self, key, value):
@@ -598,7 +604,7 @@ async def mock_client_setinfo(self, key, value):
598604
async def mock_echo(self, message):
599605
nonlocal echo_called
600606
echo_called = True
601-
assert message == __full_lib_name__
607+
assert message == expected_client_info
602608
return await original_echo(self, message)
603609

604610
# Apply the mocks
@@ -621,14 +627,25 @@ async def test_async_redis_store_graceful_failure(redis_url: str, monkeypatch) -
621627
from redis.asyncio import Redis
622628
from redis.exceptions import ResponseError
623629

630+
# Create a patch for the RedisVL validation to avoid it using echo
631+
from redisvl.redis.connection import RedisConnectionFactory
632+
original_validate = RedisConnectionFactory.validate_async_redis
633+
634+
# Create a replacement validation function that doesn't use echo
635+
async def mock_validate(redis_client, lib_name=None):
636+
return redis_client
637+
638+
# Apply the validation mock first to prevent echo from being called by RedisVL
639+
monkeypatch.setattr(RedisConnectionFactory, "validate_async_redis", mock_validate)
640+
624641
# Simulate failures for both methods
625642
async def mock_client_setinfo(self, key, value):
626643
raise ResponseError("ERR unknown command")
627644

628645
async def mock_echo(self, message):
629646
raise ResponseError("ERR connection broken")
630647

631-
# Apply the mocks
648+
# Apply the Redis mocks
632649
monkeypatch.setattr(Redis, "client_setinfo", mock_client_setinfo)
633650
monkeypatch.setattr(Redis, "echo", mock_echo)
634651

tests/test_shallow_async.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,10 @@ async def test_from_conn_string_errors(redis_url: str) -> None:
262262
@pytest.mark.asyncio
263263
async def test_async_shallow_client_info_setting(redis_url: str, monkeypatch) -> None:
264264
"""Test that client_setinfo is called with correct library information in AsyncShallowRedisSaver."""
265-
from langgraph.checkpoint.redis.version import __full_lib_name__
265+
from langgraph.checkpoint.redis.version import __redisvl_version__
266+
267+
# Expected client info format
268+
expected_client_info = f"redis-py(redisvl_v{__redisvl_version__})"
266269

267270
# Track if client_setinfo was called with the right parameters
268271
client_info_called = False
@@ -275,7 +278,7 @@ async def mock_client_setinfo(self, key, value):
275278
nonlocal client_info_called
276279
# Note: RedisVL might call this with its own lib name first
277280
# We only track calls with our full lib name
278-
if key == "LIB-NAME" and __full_lib_name__ in value:
281+
if key == "LIB-NAME" and value == expected_client_info:
279282
client_info_called = True
280283
# Call original method to ensure normal function
281284
return await original_client_setinfo(self, key, value)
@@ -297,7 +300,10 @@ async def test_async_shallow_client_info_fallback(redis_url: str, monkeypatch) -
297300
from redis.asyncio import Redis
298301
from redis.exceptions import ResponseError
299302

300-
from langgraph.checkpoint.redis.version import __full_lib_name__
303+
from langgraph.checkpoint.redis.version import __redisvl_version__
304+
305+
# Expected client info format
306+
expected_client_info = f"redis-py(redisvl_v{__redisvl_version__})"
301307

302308
# Create a Redis client directly first - this bypasses RedisVL validation
303309
client = Redis.from_url(redis_url)
@@ -315,7 +321,7 @@ async def mock_client_setinfo(self, key, value):
315321
async def mock_echo(self, message):
316322
nonlocal echo_called, echo_messages
317323
echo_messages.append(message)
318-
if __full_lib_name__ in message:
324+
if message == expected_client_info:
319325
echo_called = True
320326
return (
321327
await original_echo(self, message)

tests/test_store.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,10 @@ def test_redis_store_client_info(redis_url: str, monkeypatch) -> None:
535535
"""Test that RedisStore sets client info correctly."""
536536
from redis import Redis as NativeRedis
537537

538-
from langgraph.checkpoint.redis.version import __full_lib_name__
538+
from langgraph.checkpoint.redis.version import __redisvl_version__
539+
540+
# Expected client info format
541+
expected_client_info = f"redis-py(redisvl_v{__redisvl_version__})"
539542

540543
# Create a direct Redis client to bypass RedisVL validation
541544
client = NativeRedis.from_url(redis_url)
@@ -548,7 +551,7 @@ def test_redis_store_client_info(redis_url: str, monkeypatch) -> None:
548551
def mock_client_setinfo(self, key, value):
549552
nonlocal client_info_called
550553
# We only track calls with our full lib name
551-
if key == "LIB-NAME" and __full_lib_name__ in value:
554+
if key == "LIB-NAME" and value == expected_client_info:
552555
client_info_called = True
553556
return original_client_setinfo(self, key, value)
554557

@@ -570,7 +573,10 @@ def test_redis_store_client_info_fallback(redis_url: str, monkeypatch) -> None:
570573
"""Test that RedisStore falls back to echo when client_setinfo is not available."""
571574
from redis import Redis as NativeRedis
572575

573-
from langgraph.checkpoint.redis.version import __full_lib_name__
576+
from langgraph.checkpoint.redis.version import __redisvl_version__
577+
578+
# Expected client info format
579+
expected_client_info = f"redis-py(redisvl_v{__redisvl_version__})"
574580

575581
# Create a direct Redis client to bypass RedisVL validation
576582
client = NativeRedis.from_url(redis_url)
@@ -587,7 +593,7 @@ def mock_client_setinfo(self, key, value):
587593
def mock_echo(self, message):
588594
nonlocal echo_called
589595
# We only want to track our library's echo calls
590-
if __full_lib_name__ in message:
596+
if message == expected_client_info:
591597
echo_called = True
592598
return original_echo(self, message)
593599

0 commit comments

Comments
 (0)