Restore compatibility with custom checkpointer classes created in prior versions (#5103)

This commit is contained in:
Nuno Campos
2025-06-13 16:36:36 -07:00
committed by GitHub
9 changed files with 957 additions and 850 deletions
+1
View File
@@ -328,6 +328,7 @@ dev = [
{ name = "mypy" },
{ name = "numpy" },
{ name = "pandas" },
{ name = "pandas-stubs", specifier = ">=2.2.2.240807" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-mock" },
+1
View File
@@ -340,6 +340,7 @@ dev = [
{ name = "mypy" },
{ name = "numpy" },
{ name = "pandas" },
{ name = "pandas-stubs", specifier = ">=2.2.2.240807" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-mock" },
@@ -1,8 +1,10 @@
from __future__ import annotations
from collections.abc import AsyncIterator, Iterator, Sequence
from inspect import signature
from typing import ( # noqa: UP035
Any,
ClassVar,
Generic,
Literal,
NamedTuple,
@@ -116,8 +118,19 @@ class BaseCheckpointSaver(Generic[V]):
versions to avoid blocking the main thread.
"""
_get_next_version_legacy: ClassVar[bool] = False
"""Flag indicating if get_next_version method is legacy (takes two parameters)."""
serde: SerializerProtocol = JsonPlusSerializer()
def __init_subclass__(cls) -> None:
cls._get_next_version_legacy = (
len(signature(cls.get_next_version).parameters) > 2 # self + current
if hasattr(cls, "get_next_version")
else False
)
return super().__init_subclass__()
def __init__(
self,
*,
@@ -1,4 +1,13 @@
from typing import Any, Protocol, TypeVar, runtime_checkable
from collections.abc import Sequence
from typing import (
Any,
Optional,
Protocol,
TypeVar,
runtime_checkable,
)
from typing_extensions import Self
ERROR = "__error__"
SCHEDULED = "__scheduled__"
@@ -11,6 +20,25 @@ Update = TypeVar("Update", contravariant=True)
C = TypeVar("C")
class ChannelProtocol(Protocol[Value, Update, C]):
# Mirrors langgraph.channels.base.BaseChannel
@property
def ValueType(self) -> Any: ...
@property
def UpdateType(self) -> Any: ...
def checkpoint(self) -> Optional[C]: ...
def from_checkpoint(self, checkpoint: Optional[C]) -> Self: ...
def update(self, values: Sequence[Update]) -> bool: ...
def get(self) -> Value: ...
def consume(self) -> bool: ...
@runtime_checkable
class SendProtocol(Protocol):
# Mirrors langgraph.constants.Send
+1
View File
@@ -31,6 +31,7 @@ dev = [
"dataclasses-json",
"numpy",
"pandas",
"pandas-stubs>=2.2.2.240807",
]
[tool.hatch.build.targets.wheel]
+895 -847
View File
File diff suppressed because it is too large Load Diff
+15 -2
View File
@@ -28,6 +28,7 @@ from typing_extensions import ParamSpec, Self
from langgraph.cache.base import BaseCache
from langgraph.channels.base import BaseChannel
from langgraph.channels.last_value import LastValue
from langgraph.checkpoint.base import (
EXCLUDED_METADATA_KEYS,
WRITES_IDX_MAP,
@@ -941,7 +942,13 @@ class SyncPregelLoop(PregelLoop, AbstractContextManager):
)
self.stack = ExitStack()
if checkpointer:
self.checkpointer_get_next_version = checkpointer.get_next_version
if checkpointer._get_next_version_legacy:
empty_channel: LastValue[Any] = LastValue(Any)
self.checkpointer_get_next_version = (
lambda c: checkpointer.get_next_version(c, empty_channel) # type: ignore[call-arg]
)
else:
self.checkpointer_get_next_version = checkpointer.get_next_version
self.checkpointer_put_writes = checkpointer.put_writes
self.checkpointer_put_writes_accepts_task_path = (
signature(checkpointer.put_writes).parameters.get("task_path")
@@ -1114,7 +1121,13 @@ class AsyncPregelLoop(PregelLoop, AbstractAsyncContextManager):
)
self.stack = AsyncExitStack()
if checkpointer:
self.checkpointer_get_next_version = checkpointer.get_next_version
if checkpointer._get_next_version_legacy:
empty_channel: LastValue[Any] = LastValue(Any)
self.checkpointer_get_next_version = (
lambda c: checkpointer.get_next_version(c, empty_channel) # type: ignore[call-arg]
)
else:
self.checkpointer_get_next_version = checkpointer.get_next_version
self.checkpointer_put_writes = checkpointer.aput_writes
self.checkpointer_put_writes_accepts_task_path = (
signature(checkpointer.aput_writes).parameters.get("task_path")
+1
View File
@@ -1330,6 +1330,7 @@ dev = [
{ name = "mypy" },
{ name = "numpy" },
{ name = "pandas" },
{ name = "pandas-stubs", specifier = ">=2.2.2.240807" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-mock" },
+1
View File
@@ -391,6 +391,7 @@ dev = [
{ name = "mypy" },
{ name = "numpy" },
{ name = "pandas" },
{ name = "pandas-stubs", specifier = ">=2.2.2.240807" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-mock" },