refactor(langgraph): move typing constructs in constants.py -> _internal/_typing.py (#5518)

This commit is contained in:
Sydney Runkle
2025-07-15 16:13:34 -04:00
committed by GitHub
parent 0837263542
commit d935a2d110
25 changed files with 78 additions and 63 deletions
@@ -9,9 +9,7 @@ from typing import Annotated, Any, Optional, Union, get_type_hints
from pydantic import BaseModel
from typing_extensions import NotRequired, ReadOnly, Required, get_origin
# NOTE: this is redefined here separately from langgraph.constants
# to avoid a circular import
MISSING = object()
from langgraph._internal._typing import MISSING
def _is_optional_type(type_: Any) -> bool:
@@ -48,7 +48,7 @@ from langgraph._internal._config import (
get_callback_manager_for_config,
patch_config,
)
from langgraph._internal._typing import UNSET
from langgraph._internal._typing import MISSING
from langgraph.constants import (
CONF,
CONFIG_KEY_RUNTIME,
@@ -335,7 +335,7 @@ class RunnableCallable(Runnable):
if kw in kwargs:
continue
kw_value: Any = UNSET
kw_value: Any = MISSING
if kw == "config":
kw_value = config
elif runtime:
@@ -347,7 +347,7 @@ class RunnableCallable(Runnable):
except AttributeError:
pass
if kw_value is UNSET:
if kw_value is MISSING:
if default is inspect.Parameter.empty:
raise ValueError(
f"Missing required config key '{runtime_key}' for '{self.name}'."
@@ -407,7 +407,7 @@ class RunnableCallable(Runnable):
if kw in kwargs:
continue
kw_value: Any = UNSET
kw_value: Any = MISSING
if kw == "config":
kw_value = config
elif runtime:
@@ -418,7 +418,7 @@ class RunnableCallable(Runnable):
kw_value = getattr(runtime, runtime_key)
except AttributeError:
pass
if kw_value is UNSET:
if kw_value is MISSING:
if default is inspect.Parameter.empty:
raise ValueError(
f"Missing required config key '{runtime_key}' for '{self.name}'."
@@ -42,13 +42,13 @@ It can either be a `TypedDict`, `dataclass`, or Pydantic `BaseModel`.
Note: we cannot use either `TypedDict` or `dataclass` directly due to limitations in type checking.
"""
class Unset:
"""A sentinel value to represent an unset type."""
UNSET: Unset = Unset()
MISSING = object()
"""Unset sentinel value."""
class DeprecatedKwargs(TypedDict):
"""TypedDict to use for extra keyword arguments, enabling type checking warnings for deprecated arguments."""
EMPTY_SEQ: tuple[str, ...] = tuple()
"""An empty sequence of strings."""
@@ -1,10 +1,12 @@
from __future__ import annotations
from collections.abc import Sequence
from typing import Any, Generic
from typing_extensions import Self
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel, Value
from langgraph.constants import MISSING
from langgraph.errors import EmptyChannelError
__all__ = ("AnyValue",)
@@ -16,6 +18,8 @@ class AnyValue(Generic[Value], BaseChannel[Value, Value, Value]):
__slots__ = ("typ", "value")
value: Value | Any
def __init__(self, typ: Any, key: str = "") -> None:
super().__init__(typ, key)
self.value = MISSING
+7 -5
View File
@@ -1,20 +1,22 @@
from __future__ import annotations
from abc import ABC, abstractmethod
from collections.abc import Sequence
from typing import Any, Generic, TypeVar
from typing_extensions import Self
from langgraph.constants import MISSING
from langgraph._internal._typing import MISSING
from langgraph.errors import EmptyChannelError
Value = TypeVar("Value")
Update = TypeVar("Update")
C = TypeVar("C")
Checkpoint = TypeVar("Checkpoint")
__all__ = ("BaseChannel",)
class BaseChannel(Generic[Value, Update, C], ABC):
class BaseChannel(Generic[Value, Update, Checkpoint], ABC):
"""Base class for all channels."""
__slots__ = ("key", "typ")
@@ -41,7 +43,7 @@ class BaseChannel(Generic[Value, Update, C], ABC):
Subclasses can override this method with a more efficient implementation."""
return self.from_checkpoint(self.checkpoint())
def checkpoint(self) -> C:
def checkpoint(self) -> Checkpoint | Any:
"""Return a serializable representation of the channel's current state.
Raises EmptyChannelError if the channel is empty (never updated yet),
or doesn't support checkpoints."""
@@ -51,7 +53,7 @@ class BaseChannel(Generic[Value, Update, C], ABC):
return MISSING
@abstractmethod
def from_checkpoint(self, checkpoint: C) -> Self:
def from_checkpoint(self, checkpoint: Checkpoint | Any) -> Self:
"""Return a new identical channel, optionally initialized from a checkpoint.
If the checkpoint contains complex data structures, they should be copied."""
+1 -1
View File
@@ -4,8 +4,8 @@ from typing import Callable, Generic
from typing_extensions import NotRequired, Required, Self
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel, Value
from langgraph.constants import MISSING
from langgraph.errors import EmptyChannelError
__all__ = ("BinaryOperatorAggregate",)
@@ -1,10 +1,12 @@
from __future__ import annotations
from collections.abc import Sequence
from typing import Any, Generic
from typing_extensions import Self
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel, Value
from langgraph.constants import MISSING
from langgraph.errors import EmptyChannelError, InvalidUpdateError
__all__ = ("EphemeralValue",)
@@ -15,6 +17,9 @@ class EphemeralValue(Generic[Value], BaseChannel[Value, Value, Value]):
__slots__ = ("value", "guard")
value: Value | Any
guard: bool
def __init__(self, typ: Any, guard: bool = True) -> None:
super().__init__(typ)
self.guard = guard
@@ -1,10 +1,12 @@
from __future__ import annotations
from collections.abc import Sequence
from typing import Any, Generic
from typing_extensions import Self
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel, Value
from langgraph.constants import MISSING
from langgraph.errors import (
EmptyChannelError,
ErrorCode,
@@ -20,6 +22,8 @@ class LastValue(Generic[Value], BaseChannel[Value, Value, Value]):
__slots__ = ("value",)
value: Value | Any
def __init__(self, typ: Any, key: str = "") -> None:
super().__init__(typ, key)
self.value = MISSING
@@ -82,6 +86,9 @@ class LastValueAfterFinish(
__slots__ = ("value", "finished")
value: Value | Any
finished: bool
def __init__(self, typ: Any, key: str = "") -> None:
super().__init__(typ, key)
self.value = MISSING
@@ -100,19 +107,19 @@ class LastValueAfterFinish(
"""The type of the update received by the channel."""
return self.typ
def checkpoint(self) -> tuple[Value, bool]:
def checkpoint(self) -> tuple[Value | Any, bool] | Any:
if self.value is MISSING:
return MISSING
return (self.value, self.finished)
def from_checkpoint(self, checkpoint: tuple[Value, bool]) -> Self:
def from_checkpoint(self, checkpoint: tuple[Value | Any, bool] | Any) -> Self:
empty = self.__class__(self.typ)
empty.key = self.key
if checkpoint is not MISSING:
empty.value, empty.finished = checkpoint
return empty
def update(self, values: Sequence[Value]) -> bool:
def update(self, values: Sequence[Value | Any]) -> bool:
if len(values) == 0:
return False
@@ -3,8 +3,8 @@ from typing import Generic
from typing_extensions import Self
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel, Value
from langgraph.constants import MISSING
from langgraph.errors import EmptyChannelError, InvalidUpdateError
__all__ = ("NamedBarrierValue", "NamedBarrierValueAfterFinish")
+1 -1
View File
@@ -5,8 +5,8 @@ from typing import Any, Generic, Union
from typing_extensions import Self
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel, Value
from langgraph.constants import MISSING
from langgraph.errors import EmptyChannelError
__all__ = ("Topic",)
@@ -1,10 +1,12 @@
from __future__ import annotations
from collections.abc import Sequence
from typing import Generic
from typing import Any, Generic
from typing_extensions import Self
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel, Value
from langgraph.constants import MISSING
from langgraph.errors import EmptyChannelError, InvalidUpdateError
__all__ = ("UntrackedValue",)
@@ -15,6 +17,9 @@ class UntrackedValue(Generic[Value], BaseChannel[Value, Value, Value]):
__slots__ = ("value", "guard")
guard: bool
value: Value | Any
def __init__(self, typ: type[Value], guard: bool = True) -> None:
super().__init__(typ)
self.guard = guard
@@ -40,7 +45,7 @@ class UntrackedValue(Generic[Value], BaseChannel[Value, Value, Value]):
empty.value = self.value
return empty
def checkpoint(self) -> Value:
def checkpoint(self) -> Value | Any:
return MISSING
def from_checkpoint(self, checkpoint: Value) -> Self:
-4
View File
@@ -31,10 +31,6 @@ def __getattr__(name: str) -> Any:
raise AttributeError(f"module has no attribute '{name}'")
# --- Empty read-only containers ---
EMPTY_SEQ: tuple[str, ...] = tuple()
MISSING = object()
# --- Public constants ---
TAG_NOSTREAM = sys.intern("nostream")
"""Tag to disable streaming for a chat model."""
+4 -4
View File
@@ -20,7 +20,7 @@ from typing import (
from typing_extensions import Unpack
from langgraph._internal._typing import UNSET, DeprecatedKwargs
from langgraph._internal._typing import MISSING, DeprecatedKwargs
from langgraph.cache.base import BaseCache
from langgraph.channels.ephemeral_value import EphemeralValue
from langgraph.channels.last_value import LastValue
@@ -180,7 +180,7 @@ def task(
await add_one.ainvoke([1, 2, 3]) # Returns [2, 3, 4]
```
"""
if (retry := kwargs.get("retry", UNSET)) is not UNSET:
if (retry := kwargs.get("retry", MISSING)) is not MISSING:
warnings.warn(
"`retry` is deprecated and will be removed. Please use `retry_policy` instead.",
category=LangGraphDeprecatedSinceV05,
@@ -383,7 +383,7 @@ class entrypoint(Generic[ContextT]):
**kwargs: Unpack[DeprecatedKwargs],
) -> None:
"""Initialize the entrypoint decorator."""
if (config_schema := kwargs.get("config_schema", UNSET)) is not UNSET:
if (config_schema := kwargs.get("config_schema", MISSING)) is not MISSING:
warnings.warn(
"`config_schema` is deprecated and will be removed. Please use `context_schema` instead.",
category=LangGraphDeprecatedSinceV10,
@@ -392,7 +392,7 @@ class entrypoint(Generic[ContextT]):
if context_schema is None:
context_schema = cast(type[ContextT], config_schema)
if (retry := kwargs.get("retry", UNSET)) is not UNSET:
if (retry := kwargs.get("retry", MISSING)) is not MISSING:
warnings.warn(
"`retry` is deprecated and will be removed. Please use `retry_policy` instead.",
category=LangGraphDeprecatedSinceV05,
+1 -1
View File
@@ -8,7 +8,7 @@ from typing import Any, Generic, Protocol, Union
from langchain_core.runnables import Runnable, RunnableConfig
from typing_extensions import TypeAlias
from langgraph.constants import EMPTY_SEQ
from langgraph._internal._typing import EMPTY_SEQ
from langgraph.runtime import Runtime
from langgraph.store.base import BaseStore
from langgraph.types import CachePolicy, RetryPolicy, StreamWriter
+6 -8
View File
@@ -34,7 +34,7 @@ from langgraph._internal._fields import (
)
from langgraph._internal._pydantic import create_model
from langgraph._internal._runnable import coerce_to_runnable
from langgraph._internal._typing import UNSET, DeprecatedKwargs
from langgraph._internal._typing import EMPTY_SEQ, MISSING, DeprecatedKwargs
from langgraph.cache.base import BaseCache
from langgraph.channels.base import BaseChannel
from langgraph.channels.binop import BinaryOperatorAggregate
@@ -46,10 +46,8 @@ from langgraph.channels.named_barrier_value import (
)
from langgraph.checkpoint.base import Checkpoint
from langgraph.constants import (
EMPTY_SEQ,
END,
INTERRUPT,
MISSING,
NS_END,
NS_SEP,
START,
@@ -193,7 +191,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
output_schema: type[OutputT] | None = None,
**kwargs: Unpack[DeprecatedKwargs],
) -> None:
if (config_schema := kwargs.get("config_schema", UNSET)) is not UNSET:
if (config_schema := kwargs.get("config_schema", MISSING)) is not MISSING:
warnings.warn(
"`config_schema` is deprecated and will be removed. Please use `context_schema` instead.",
category=LangGraphDeprecatedSinceV10,
@@ -202,7 +200,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
if context_schema is None:
context_schema = cast(type[ContextT], config_schema)
if (input_ := kwargs.get("input", UNSET)) is not UNSET:
if (input_ := kwargs.get("input", MISSING)) is not MISSING:
warnings.warn(
"`input` is deprecated and will be removed. Please use `input_schema` instead.",
category=LangGraphDeprecatedSinceV05,
@@ -211,7 +209,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
if input_schema is None:
input_schema = cast(type[InputT], input_)
if (output := kwargs.get("output", UNSET)) is not UNSET:
if (output := kwargs.get("output", MISSING)) is not MISSING:
warnings.warn(
"`output` is deprecated and will be removed. Please use `output_schema` instead.",
category=LangGraphDeprecatedSinceV05,
@@ -412,7 +410,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
Returns:
Self: The instance of the state graph, allowing for method chaining.
"""
if (retry := kwargs.get("retry", UNSET)) is not UNSET:
if (retry := kwargs.get("retry", MISSING)) is not MISSING:
warnings.warn(
"`retry` is deprecated and will be removed. Please use `retry_policy` instead.",
category=LangGraphDeprecatedSinceV05,
@@ -420,7 +418,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
if retry_policy is None:
retry_policy = retry # type: ignore[assignment]
if (input_ := kwargs.get("input", UNSET)) is not UNSET:
if (input_ := kwargs.get("input", MISSING)) is not MISSING:
warnings.warn(
"`input` is deprecated and will be removed. Please use `input_schema` instead.",
category=LangGraphDeprecatedSinceV05,
+1 -2
View File
@@ -27,6 +27,7 @@ from xxhash import xxh3_128_hexdigest
from langgraph._internal._config import merge_configs, patch_config
from langgraph._internal._runtime import patch_runtime_non_null
from langgraph._internal._typing import EMPTY_SEQ, MISSING
from langgraph.channels.base import BaseChannel
from langgraph.channels.topic import Topic
from langgraph.checkpoint.base import (
@@ -49,10 +50,8 @@ from langgraph.constants import (
CONFIG_KEY_SCRATCHPAD,
CONFIG_KEY_SEND,
CONFIG_KEY_TASK_ID,
EMPTY_SEQ,
ERROR,
INTERRUPT,
MISSING,
NO_WRITES,
NS_END,
NS_SEP,
@@ -3,10 +3,10 @@ from __future__ import annotations
from collections.abc import Mapping
from datetime import datetime, timezone
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel
from langgraph.checkpoint.base import Checkpoint
from langgraph.checkpoint.base.id import uuid6
from langgraph.constants import MISSING
from langgraph.managed.base import ManagedValueMapping, ManagedValueSpec
LATEST_VERSION = 4
+1 -2
View File
@@ -4,12 +4,11 @@ from collections import Counter
from collections.abc import Iterator, Mapping, Sequence
from typing import Any, Literal
from langgraph._internal._typing import EMPTY_SEQ, MISSING
from langgraph.channels.base import BaseChannel, EmptyChannelError
from langgraph.constants import (
EMPTY_SEQ,
ERROR,
INTERRUPT,
MISSING,
NULL_TASK_ID,
RESUME,
RETURN,
+1 -2
View File
@@ -28,6 +28,7 @@ from langchain_core.runnables import RunnableConfig
from typing_extensions import ParamSpec, Self
from langgraph._internal._config import patch_configurable
from langgraph._internal._typing import EMPTY_SEQ, MISSING
from langgraph.cache.base import BaseCache
from langgraph.channels.base import BaseChannel
from langgraph.checkpoint.base import (
@@ -50,11 +51,9 @@ from langgraph.constants import (
CONFIG_KEY_STREAM,
CONFIG_KEY_TASK_ID,
CONFIG_KEY_THREAD_ID,
EMPTY_SEQ,
ERROR,
INPUT,
INTERRUPT,
MISSING,
NS_END,
NS_SEP,
NULL_TASK_ID,
+1 -1
View File
@@ -20,13 +20,13 @@ from typing import (
from langchain_core.callbacks import Callbacks
from langgraph._internal._future import chain_future, run_coroutine_threadsafe
from langgraph._internal._typing import MISSING
from langgraph.constants import (
CONF,
CONFIG_KEY_CALL,
CONFIG_KEY_SCRATCHPAD,
ERROR,
INTERRUPT,
MISSING,
NO_WRITES,
RESUME,
RETURN,
+2 -1
View File
@@ -14,7 +14,8 @@ from typing import (
from langchain_core.runnables import Runnable, RunnableConfig
from langgraph._internal._runnable import RunnableCallable
from langgraph.constants import CONF, CONFIG_KEY_SEND, MISSING, TASKS
from langgraph._internal._typing import MISSING
from langgraph.constants import CONF, CONFIG_KEY_SEND, TASKS
from langgraph.errors import InvalidUpdateError
from langgraph.types import Send
+1 -1
View File
@@ -9,6 +9,7 @@ from langchain_core.runnables import RunnableConfig
from typing_extensions import TypedDict
from langgraph._internal._config import patch_checkpoint_map
from langgraph._internal._typing import MISSING
from langgraph.channels.base import BaseChannel
from langgraph.checkpoint.base import CheckpointMetadata, PendingWrite
from langgraph.constants import (
@@ -16,7 +17,6 @@ from langgraph.constants import (
CONFIG_KEY_CHECKPOINT_NS,
ERROR,
INTERRUPT,
MISSING,
NS_END,
NS_SEP,
RETURN,
+2 -2
View File
@@ -25,7 +25,7 @@ from xxhash import xxh3_128_hexdigest
from langgraph._internal._cache import default_cache_key
from langgraph._internal._fields import get_cached_annotated_keys, get_update_as_tuples
from langgraph._internal._retry import default_retry_on
from langgraph._internal._typing import UNSET, DeprecatedKwargs
from langgraph._internal._typing import MISSING, DeprecatedKwargs
from langgraph.checkpoint.base import BaseCheckpointSaver, CheckpointMetadata
from langgraph.warnings import LangGraphDeprecatedSinceV10
@@ -157,7 +157,7 @@ class Interrupt:
self.value = value
if (
(ns := deprecated_kwargs.get("ns", UNSET)) is not UNSET
(ns := deprecated_kwargs.get("ns", MISSING)) is not MISSING
and (id == _DEFAULT_INTERRUPT_ID)
and (isinstance(ns, Sequence))
):
+1 -1
View File
@@ -4,10 +4,10 @@ from typing import Union
import pytest
from langgraph._internal._typing import MISSING
from langgraph.channels.binop import BinaryOperatorAggregate
from langgraph.channels.last_value import LastValue
from langgraph.channels.topic import Topic
from langgraph.constants import MISSING
from langgraph.errors import EmptyChannelError, InvalidUpdateError
pytestmark = pytest.mark.anyio
@@ -36,7 +36,7 @@ from pydantic import BaseModel
from typing_extensions import Annotated, TypedDict
from langgraph._internal._runnable import RunnableCallable, RunnableLike
from langgraph._internal._typing import UNSET
from langgraph._internal._typing import MISSING
from langgraph.errors import ErrorCode, create_error_message
from langgraph.graph import END, StateGraph
from langgraph.graph.message import add_messages
@@ -405,7 +405,9 @@ def create_react_agent(
print(chunk)
```
"""
if (config_schema := deprecated_kwargs.pop("config_schema", UNSET)) is not UNSET:
if (
config_schema := deprecated_kwargs.pop("config_schema", MISSING)
) is not MISSING:
warn(
"`config_schema` is no longer supported. Use `context_schema` instead.",
category=LangGraphDeprecatedSinceV10,