langgraph-checkpoint-postgres 2.0.23__tar.gz → 2.0.25__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/PKG-INFO +2 -2
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/checkpoint/postgres/__init__.py +10 -13
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/checkpoint/postgres/aio.py +10 -12
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/checkpoint/postgres/base.py +15 -2
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/checkpoint/postgres/shallow.py +14 -14
- langgraph_checkpoint_postgres-2.0.25/langgraph/store/postgres/__init__.py +4 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/pyproject.toml +2 -2
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/test_async.py +37 -11
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/test_store.py +40 -2
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/test_sync.py +36 -11
- langgraph_checkpoint_postgres-2.0.25/uv.lock +1211 -0
- langgraph_checkpoint_postgres-2.0.23/langgraph/store/postgres/__init__.py +0 -4
- langgraph_checkpoint_postgres-2.0.23/uv.lock +0 -1225
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/.gitignore +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/Makefile +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/README.md +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/checkpoint/postgres/_ainternal.py +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/checkpoint/postgres/_internal.py +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/checkpoint/postgres/py.typed +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/store/postgres/aio.py +5 -5
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/store/postgres/base.py +8 -8
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/langgraph/store/postgres/py.typed +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/__init__.py +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/compose-postgres.yml +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/conftest.py +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/embed_test_utils.py +0 -0
- {langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/test_async_store.py +2 -2
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-checkpoint-postgres
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.25
|
|
4
4
|
Summary: Library with a Postgres implementation of LangGraph checkpoint saver.
|
|
5
5
|
Project-URL: Repository, https://www.github.com/langchain-ai/langgraph
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Requires-Python: >=3.9
|
|
8
|
-
Requires-Dist: langgraph-checkpoint<3.0.0,>=2.
|
|
8
|
+
Requires-Dist: langgraph-checkpoint<3.0.0,>=2.1.2
|
|
9
9
|
Requires-Dist: orjson>=3.10.1
|
|
10
10
|
Requires-Dist: psycopg-pool>=3.2.0
|
|
11
11
|
Requires-Dist: psycopg>=3.2.0
|
|
@@ -7,11 +7,6 @@ from contextlib import contextmanager
|
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
9
|
from langchain_core.runnables import RunnableConfig
|
|
10
|
-
from psycopg import Capabilities, Connection, Cursor, Pipeline
|
|
11
|
-
from psycopg.rows import DictRow, dict_row
|
|
12
|
-
from psycopg.types.json import Jsonb
|
|
13
|
-
from psycopg_pool import ConnectionPool
|
|
14
|
-
|
|
15
10
|
from langgraph.checkpoint.base import (
|
|
16
11
|
WRITES_IDX_MAP,
|
|
17
12
|
ChannelVersions,
|
|
@@ -19,12 +14,17 @@ from langgraph.checkpoint.base import (
|
|
|
19
14
|
CheckpointMetadata,
|
|
20
15
|
CheckpointTuple,
|
|
21
16
|
get_checkpoint_id,
|
|
22
|
-
|
|
17
|
+
get_serializable_checkpoint_metadata,
|
|
23
18
|
)
|
|
19
|
+
from langgraph.checkpoint.serde.base import SerializerProtocol
|
|
20
|
+
from psycopg import Capabilities, Connection, Cursor, Pipeline
|
|
21
|
+
from psycopg.rows import DictRow, dict_row
|
|
22
|
+
from psycopg.types.json import Jsonb
|
|
23
|
+
from psycopg_pool import ConnectionPool
|
|
24
|
+
|
|
24
25
|
from langgraph.checkpoint.postgres import _internal
|
|
25
26
|
from langgraph.checkpoint.postgres.base import BasePostgresSaver
|
|
26
27
|
from langgraph.checkpoint.postgres.shallow import ShallowPostgresSaver
|
|
27
|
-
from langgraph.checkpoint.serde.base import SerializerProtocol
|
|
28
28
|
|
|
29
29
|
Conn = _internal.Conn # For backward compatibility
|
|
30
30
|
|
|
@@ -284,10 +284,7 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
284
284
|
configurable = config["configurable"].copy()
|
|
285
285
|
thread_id = configurable.pop("thread_id")
|
|
286
286
|
checkpoint_ns = configurable.pop("checkpoint_ns")
|
|
287
|
-
checkpoint_id = configurable.pop(
|
|
288
|
-
"checkpoint_id", configurable.pop("thread_ts", None)
|
|
289
|
-
)
|
|
290
|
-
|
|
287
|
+
checkpoint_id = configurable.pop("checkpoint_id", None)
|
|
291
288
|
copy = checkpoint.copy()
|
|
292
289
|
copy["channel_values"] = copy["channel_values"].copy()
|
|
293
290
|
next_config = {
|
|
@@ -328,7 +325,7 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
328
325
|
checkpoint["id"],
|
|
329
326
|
checkpoint_id,
|
|
330
327
|
Jsonb(copy),
|
|
331
|
-
Jsonb(
|
|
328
|
+
Jsonb(get_serializable_checkpoint_metadata(config, metadata)),
|
|
332
329
|
),
|
|
333
330
|
)
|
|
334
331
|
return next_config
|
|
@@ -453,7 +450,7 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
453
450
|
{
|
|
454
451
|
**value["checkpoint"],
|
|
455
452
|
"channel_values": {
|
|
456
|
-
**value["checkpoint"].get("channel_values"),
|
|
453
|
+
**(value["checkpoint"].get("channel_values") or {}),
|
|
457
454
|
**self._load_blobs(value["channel_values"]),
|
|
458
455
|
},
|
|
459
456
|
},
|
|
@@ -7,11 +7,6 @@ from contextlib import asynccontextmanager
|
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
9
|
from langchain_core.runnables import RunnableConfig
|
|
10
|
-
from psycopg import AsyncConnection, AsyncCursor, AsyncPipeline, Capabilities
|
|
11
|
-
from psycopg.rows import DictRow, dict_row
|
|
12
|
-
from psycopg.types.json import Jsonb
|
|
13
|
-
from psycopg_pool import AsyncConnectionPool
|
|
14
|
-
|
|
15
10
|
from langgraph.checkpoint.base import (
|
|
16
11
|
WRITES_IDX_MAP,
|
|
17
12
|
ChannelVersions,
|
|
@@ -19,12 +14,17 @@ from langgraph.checkpoint.base import (
|
|
|
19
14
|
CheckpointMetadata,
|
|
20
15
|
CheckpointTuple,
|
|
21
16
|
get_checkpoint_id,
|
|
22
|
-
|
|
17
|
+
get_serializable_checkpoint_metadata,
|
|
23
18
|
)
|
|
19
|
+
from langgraph.checkpoint.serde.base import SerializerProtocol
|
|
20
|
+
from psycopg import AsyncConnection, AsyncCursor, AsyncPipeline, Capabilities
|
|
21
|
+
from psycopg.rows import DictRow, dict_row
|
|
22
|
+
from psycopg.types.json import Jsonb
|
|
23
|
+
from psycopg_pool import AsyncConnectionPool
|
|
24
|
+
|
|
24
25
|
from langgraph.checkpoint.postgres import _ainternal
|
|
25
26
|
from langgraph.checkpoint.postgres.base import BasePostgresSaver
|
|
26
27
|
from langgraph.checkpoint.postgres.shallow import AsyncShallowPostgresSaver
|
|
27
|
-
from langgraph.checkpoint.serde.base import SerializerProtocol
|
|
28
28
|
|
|
29
29
|
Conn = _ainternal.Conn # For backward compatibility
|
|
30
30
|
|
|
@@ -240,9 +240,7 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
240
240
|
configurable = config["configurable"].copy()
|
|
241
241
|
thread_id = configurable.pop("thread_id")
|
|
242
242
|
checkpoint_ns = configurable.pop("checkpoint_ns")
|
|
243
|
-
checkpoint_id = configurable.pop(
|
|
244
|
-
"checkpoint_id", configurable.pop("thread_ts", None)
|
|
245
|
-
)
|
|
243
|
+
checkpoint_id = configurable.pop("checkpoint_id", None)
|
|
246
244
|
|
|
247
245
|
copy = checkpoint.copy()
|
|
248
246
|
copy["channel_values"] = copy["channel_values"].copy()
|
|
@@ -285,7 +283,7 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
285
283
|
checkpoint["id"],
|
|
286
284
|
checkpoint_id,
|
|
287
285
|
Jsonb(copy),
|
|
288
|
-
Jsonb(
|
|
286
|
+
Jsonb(get_serializable_checkpoint_metadata(config, metadata)),
|
|
289
287
|
),
|
|
290
288
|
)
|
|
291
289
|
return next_config
|
|
@@ -411,7 +409,7 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
411
409
|
{
|
|
412
410
|
**value["checkpoint"],
|
|
413
411
|
"channel_values": {
|
|
414
|
-
**value["checkpoint"].get("channel_values"),
|
|
412
|
+
**(value["checkpoint"].get("channel_values") or {}),
|
|
415
413
|
**self._load_blobs(value["channel_values"]),
|
|
416
414
|
},
|
|
417
415
|
},
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import random
|
|
4
|
+
import warnings
|
|
4
5
|
from collections.abc import Sequence
|
|
6
|
+
from importlib.metadata import version as get_version
|
|
5
7
|
from typing import Any, Optional, cast
|
|
6
8
|
|
|
7
9
|
from langchain_core.runnables import RunnableConfig
|
|
8
|
-
from psycopg.types.json import Jsonb
|
|
9
|
-
|
|
10
10
|
from langgraph.checkpoint.base import (
|
|
11
11
|
WRITES_IDX_MAP,
|
|
12
12
|
BaseCheckpointSaver,
|
|
@@ -14,9 +14,22 @@ from langgraph.checkpoint.base import (
|
|
|
14
14
|
get_checkpoint_id,
|
|
15
15
|
)
|
|
16
16
|
from langgraph.checkpoint.serde.types import TASKS
|
|
17
|
+
from psycopg.types.json import Jsonb
|
|
17
18
|
|
|
18
19
|
MetadataInput = Optional[dict[str, Any]]
|
|
19
20
|
|
|
21
|
+
try:
|
|
22
|
+
major, minor = get_version("langgraph").split(".")[:2]
|
|
23
|
+
if int(major) == 0 and int(minor) < 5:
|
|
24
|
+
warnings.warn(
|
|
25
|
+
"You're using incompatible versions of langgraph and checkpoint-postgres. Please upgrade langgraph to avoid unexpected behavior.",
|
|
26
|
+
DeprecationWarning,
|
|
27
|
+
stacklevel=2,
|
|
28
|
+
)
|
|
29
|
+
except Exception:
|
|
30
|
+
# skip version check if running from source
|
|
31
|
+
pass
|
|
32
|
+
|
|
20
33
|
"""
|
|
21
34
|
To add a new migration, add a new string to the MIGRATIONS list.
|
|
22
35
|
The position of the migration in the list is the version number.
|
|
@@ -6,6 +6,16 @@ from contextlib import asynccontextmanager, contextmanager
|
|
|
6
6
|
from typing import Any, Optional
|
|
7
7
|
|
|
8
8
|
from langchain_core.runnables import RunnableConfig
|
|
9
|
+
from langgraph.checkpoint.base import (
|
|
10
|
+
WRITES_IDX_MAP,
|
|
11
|
+
ChannelVersions,
|
|
12
|
+
Checkpoint,
|
|
13
|
+
CheckpointMetadata,
|
|
14
|
+
CheckpointTuple,
|
|
15
|
+
get_serializable_checkpoint_metadata,
|
|
16
|
+
)
|
|
17
|
+
from langgraph.checkpoint.serde.base import SerializerProtocol
|
|
18
|
+
from langgraph.checkpoint.serde.types import TASKS
|
|
9
19
|
from psycopg import (
|
|
10
20
|
AsyncConnection,
|
|
11
21
|
AsyncCursor,
|
|
@@ -19,18 +29,8 @@ from psycopg.rows import DictRow, dict_row
|
|
|
19
29
|
from psycopg.types.json import Jsonb
|
|
20
30
|
from psycopg_pool import AsyncConnectionPool, ConnectionPool
|
|
21
31
|
|
|
22
|
-
from langgraph.checkpoint.base import (
|
|
23
|
-
WRITES_IDX_MAP,
|
|
24
|
-
ChannelVersions,
|
|
25
|
-
Checkpoint,
|
|
26
|
-
CheckpointMetadata,
|
|
27
|
-
CheckpointTuple,
|
|
28
|
-
get_checkpoint_metadata,
|
|
29
|
-
)
|
|
30
32
|
from langgraph.checkpoint.postgres import _ainternal, _internal
|
|
31
33
|
from langgraph.checkpoint.postgres.base import BasePostgresSaver
|
|
32
|
-
from langgraph.checkpoint.serde.base import SerializerProtocol
|
|
33
|
-
from langgraph.checkpoint.serde.types import TASKS
|
|
34
34
|
|
|
35
35
|
"""
|
|
36
36
|
To add a new migration, add a new string to the MIGRATIONS list.
|
|
@@ -191,7 +191,7 @@ class ShallowPostgresSaver(BasePostgresSaver):
|
|
|
191
191
|
) -> None:
|
|
192
192
|
warnings.warn(
|
|
193
193
|
"ShallowPostgresSaver is deprecated as of version 2.0.20 and will be removed in 3.0.0. "
|
|
194
|
-
"Use PostgresSaver instead, and invoke the graph with `graph.invoke(...,
|
|
194
|
+
"Use PostgresSaver instead, and invoke the graph with `graph.invoke(..., durability='exit')`.",
|
|
195
195
|
DeprecationWarning,
|
|
196
196
|
stacklevel=2,
|
|
197
197
|
)
|
|
@@ -441,7 +441,7 @@ class ShallowPostgresSaver(BasePostgresSaver):
|
|
|
441
441
|
thread_id,
|
|
442
442
|
checkpoint_ns,
|
|
443
443
|
Jsonb(copy),
|
|
444
|
-
Jsonb(
|
|
444
|
+
Jsonb(get_serializable_checkpoint_metadata(config, metadata)),
|
|
445
445
|
),
|
|
446
446
|
)
|
|
447
447
|
return next_config
|
|
@@ -547,7 +547,7 @@ class AsyncShallowPostgresSaver(BasePostgresSaver):
|
|
|
547
547
|
) -> None:
|
|
548
548
|
warnings.warn(
|
|
549
549
|
"AsyncShallowPostgresSaver is deprecated as of version 2.0.20 and will be removed in 3.0.0. "
|
|
550
|
-
"Use AsyncPostgresSaver instead, and invoke the graph with `await graph.ainvoke(...,
|
|
550
|
+
"Use AsyncPostgresSaver instead, and invoke the graph with `await graph.ainvoke(..., durability='exit')`.",
|
|
551
551
|
DeprecationWarning,
|
|
552
552
|
stacklevel=2,
|
|
553
553
|
)
|
|
@@ -774,7 +774,7 @@ class AsyncShallowPostgresSaver(BasePostgresSaver):
|
|
|
774
774
|
thread_id,
|
|
775
775
|
checkpoint_ns,
|
|
776
776
|
Jsonb(copy),
|
|
777
|
-
Jsonb(
|
|
777
|
+
Jsonb(get_serializable_checkpoint_metadata(config, metadata)),
|
|
778
778
|
),
|
|
779
779
|
)
|
|
780
780
|
return next_config
|
{langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/pyproject.toml
RENAMED
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "langgraph-checkpoint-postgres"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.25"
|
|
8
8
|
description = "Library with a Postgres implementation of LangGraph checkpoint saver."
|
|
9
9
|
authors = []
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -12,7 +12,7 @@ readme = "README.md"
|
|
|
12
12
|
license = "MIT"
|
|
13
13
|
license-files = ['LICENSE']
|
|
14
14
|
dependencies = [
|
|
15
|
-
"langgraph-checkpoint>=2.
|
|
15
|
+
"langgraph-checkpoint>=2.1.2,<3.0.0",
|
|
16
16
|
"orjson>=3.10.1",
|
|
17
17
|
"psycopg>=3.2.0",
|
|
18
18
|
"psycopg-pool>=3.2.0",
|
{langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/test_async.py
RENAMED
|
@@ -6,10 +6,6 @@ from uuid import uuid4
|
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
8
8
|
from langchain_core.runnables import RunnableConfig
|
|
9
|
-
from psycopg import AsyncConnection
|
|
10
|
-
from psycopg.rows import dict_row
|
|
11
|
-
from psycopg_pool import AsyncConnectionPool
|
|
12
|
-
|
|
13
9
|
from langgraph.checkpoint.base import (
|
|
14
10
|
EXCLUDED_METADATA_KEYS,
|
|
15
11
|
Checkpoint,
|
|
@@ -17,11 +13,15 @@ from langgraph.checkpoint.base import (
|
|
|
17
13
|
create_checkpoint,
|
|
18
14
|
empty_checkpoint,
|
|
19
15
|
)
|
|
16
|
+
from langgraph.checkpoint.serde.types import TASKS
|
|
17
|
+
from psycopg import AsyncConnection
|
|
18
|
+
from psycopg.rows import dict_row
|
|
19
|
+
from psycopg_pool import AsyncConnectionPool
|
|
20
|
+
|
|
20
21
|
from langgraph.checkpoint.postgres.aio import (
|
|
21
22
|
AsyncPostgresSaver,
|
|
22
23
|
AsyncShallowPostgresSaver,
|
|
23
24
|
)
|
|
24
|
-
from langgraph.checkpoint.serde.types import TASKS
|
|
25
25
|
from tests.conftest import DEFAULT_POSTGRES_URI
|
|
26
26
|
|
|
27
27
|
|
|
@@ -161,8 +161,7 @@ def test_data():
|
|
|
161
161
|
config_1: RunnableConfig = {
|
|
162
162
|
"configurable": {
|
|
163
163
|
"thread_id": "thread-1",
|
|
164
|
-
|
|
165
|
-
"thread_ts": "1",
|
|
164
|
+
"checkpoint_id": "1",
|
|
166
165
|
"checkpoint_ns": "",
|
|
167
166
|
}
|
|
168
167
|
}
|
|
@@ -188,13 +187,11 @@ def test_data():
|
|
|
188
187
|
metadata_1: CheckpointMetadata = {
|
|
189
188
|
"source": "input",
|
|
190
189
|
"step": 2,
|
|
191
|
-
"writes": {},
|
|
192
190
|
"score": 1,
|
|
193
191
|
}
|
|
194
192
|
metadata_2: CheckpointMetadata = {
|
|
195
193
|
"source": "loop",
|
|
196
194
|
"step": 1,
|
|
197
|
-
"writes": {"foo": "bar"},
|
|
198
195
|
"score": None,
|
|
199
196
|
}
|
|
200
197
|
metadata_3: CheckpointMetadata = {}
|
|
@@ -221,7 +218,6 @@ async def test_combined_metadata(saver_name: str, test_data) -> None:
|
|
|
221
218
|
metadata: CheckpointMetadata = {
|
|
222
219
|
"source": "loop",
|
|
223
220
|
"step": 1,
|
|
224
|
-
"writes": {"foo": "bar"},
|
|
225
221
|
"score": None,
|
|
226
222
|
}
|
|
227
223
|
await saver.aput(config, chkpnt, metadata, {})
|
|
@@ -247,7 +243,6 @@ async def test_asearch(saver_name: str, test_data) -> None:
|
|
|
247
243
|
query_1 = {"source": "input"} # search by 1 key
|
|
248
244
|
query_2 = {
|
|
249
245
|
"step": 1,
|
|
250
|
-
"writes": {"foo": "bar"},
|
|
251
246
|
} # search by multiple keys
|
|
252
247
|
query_3: dict[str, Any] = {} # search by no keys, return all checkpoints
|
|
253
248
|
query_4 = {"source": "update", "step": 1} # no match
|
|
@@ -345,3 +340,34 @@ async def test_pending_sends_migration(saver_name: str) -> None:
|
|
|
345
340
|
TASKS: ["send-1", "send-2", "send-3"]
|
|
346
341
|
}
|
|
347
342
|
assert TASKS in search_results[0].checkpoint["channel_versions"]
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
@pytest.mark.parametrize("saver_name", ["base", "pool", "pipe"])
|
|
346
|
+
async def test_get_checkpoint_no_channel_values(
|
|
347
|
+
monkeypatch, saver_name: str, test_data
|
|
348
|
+
) -> None:
|
|
349
|
+
"""Backwards compatibility test that verifies a checkpoint with no channel_values key can be retrieved without throwing an error."""
|
|
350
|
+
async with _saver(saver_name) as saver:
|
|
351
|
+
config = {
|
|
352
|
+
"configurable": {
|
|
353
|
+
"thread_id": "thread-2",
|
|
354
|
+
"checkpoint_ns": "",
|
|
355
|
+
"__super_private_key": "super_private_value",
|
|
356
|
+
},
|
|
357
|
+
"metadata": {"run_id": "my_run_id"},
|
|
358
|
+
}
|
|
359
|
+
chkpnt: Checkpoint = create_checkpoint(empty_checkpoint(), {}, 1)
|
|
360
|
+
await saver.aput(config, chkpnt, {}, {})
|
|
361
|
+
|
|
362
|
+
load_checkpoint_tuple = saver._load_checkpoint_tuple
|
|
363
|
+
|
|
364
|
+
def patched_load_checkpoint_tuple(value):
|
|
365
|
+
value["checkpoint"].pop("channel_values", None)
|
|
366
|
+
return load_checkpoint_tuple(value)
|
|
367
|
+
|
|
368
|
+
monkeypatch.setattr(
|
|
369
|
+
saver, "_load_checkpoint_tuple", patched_load_checkpoint_tuple
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
checkpoint = await saver.aget_tuple(config)
|
|
373
|
+
assert checkpoint.checkpoint["channel_values"] == {}
|
{langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/test_store.py
RENAMED
|
@@ -9,8 +9,6 @@ from uuid import uuid4
|
|
|
9
9
|
|
|
10
10
|
import pytest
|
|
11
11
|
from langchain_core.embeddings import Embeddings
|
|
12
|
-
from psycopg import Connection
|
|
13
|
-
|
|
14
12
|
from langgraph.store.base import (
|
|
15
13
|
GetOp,
|
|
16
14
|
Item,
|
|
@@ -19,6 +17,8 @@ from langgraph.store.base import (
|
|
|
19
17
|
PutOp,
|
|
20
18
|
SearchOp,
|
|
21
19
|
)
|
|
20
|
+
from psycopg import Connection
|
|
21
|
+
|
|
22
22
|
from langgraph.store.postgres import PostgresStore
|
|
23
23
|
from tests.conftest import (
|
|
24
24
|
DEFAULT_URI,
|
|
@@ -861,3 +861,41 @@ def test_store_ttl(store):
|
|
|
861
861
|
# Now has been (TTL_SECONDS-2)*2 > TTL_SECONDS + TTL_SECONDS/2
|
|
862
862
|
res = store.search(ns, query="bar", refresh_ttl=False)
|
|
863
863
|
assert len(res) == 0
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
@pytest.mark.parametrize(
|
|
867
|
+
"vector_type,distance_type",
|
|
868
|
+
[
|
|
869
|
+
("vector", "cosine"),
|
|
870
|
+
("vector", "inner_product"),
|
|
871
|
+
("halfvec", "cosine"),
|
|
872
|
+
("halfvec", "inner_product"),
|
|
873
|
+
],
|
|
874
|
+
)
|
|
875
|
+
def test_non_ascii(
|
|
876
|
+
request: Any,
|
|
877
|
+
fake_embeddings: CharacterEmbeddings,
|
|
878
|
+
vector_type: str,
|
|
879
|
+
distance_type: str,
|
|
880
|
+
) -> None:
|
|
881
|
+
"""Test support for non-ascii characters"""
|
|
882
|
+
with _create_vector_store(vector_type, distance_type, fake_embeddings) as store:
|
|
883
|
+
store.put(("user_123", "memories"), "1", {"text": "这是中文"}) # Chinese
|
|
884
|
+
store.put(
|
|
885
|
+
("user_123", "memories"), "2", {"text": "これは日本語です"}
|
|
886
|
+
) # Japanese
|
|
887
|
+
store.put(("user_123", "memories"), "3", {"text": "이건 한국어야"}) # Korean
|
|
888
|
+
store.put(("user_123", "memories"), "4", {"text": "Это русский"}) # Russian
|
|
889
|
+
store.put(("user_123", "memories"), "5", {"text": "यह रूसी है"}) # Hindi
|
|
890
|
+
|
|
891
|
+
result1 = store.search(("user_123", "memories"), query="这是中文")
|
|
892
|
+
result2 = store.search(("user_123", "memories"), query="これは日本語です")
|
|
893
|
+
result3 = store.search(("user_123", "memories"), query="이건 한국어야")
|
|
894
|
+
result4 = store.search(("user_123", "memories"), query="Это русский")
|
|
895
|
+
result5 = store.search(("user_123", "memories"), query="यह रूसी है")
|
|
896
|
+
|
|
897
|
+
assert result1[0].key == "1"
|
|
898
|
+
assert result2[0].key == "2"
|
|
899
|
+
assert result3[0].key == "3"
|
|
900
|
+
assert result4[0].key == "4"
|
|
901
|
+
assert result5[0].key == "5"
|
{langgraph_checkpoint_postgres-2.0.23 → langgraph_checkpoint_postgres-2.0.25}/tests/test_sync.py
RENAMED
|
@@ -7,10 +7,6 @@ from uuid import uuid4
|
|
|
7
7
|
|
|
8
8
|
import pytest
|
|
9
9
|
from langchain_core.runnables import RunnableConfig
|
|
10
|
-
from psycopg import Connection
|
|
11
|
-
from psycopg.rows import dict_row
|
|
12
|
-
from psycopg_pool import ConnectionPool
|
|
13
|
-
|
|
14
10
|
from langgraph.checkpoint.base import (
|
|
15
11
|
EXCLUDED_METADATA_KEYS,
|
|
16
12
|
Checkpoint,
|
|
@@ -18,8 +14,12 @@ from langgraph.checkpoint.base import (
|
|
|
18
14
|
create_checkpoint,
|
|
19
15
|
empty_checkpoint,
|
|
20
16
|
)
|
|
21
|
-
from langgraph.checkpoint.postgres import PostgresSaver, ShallowPostgresSaver
|
|
22
17
|
from langgraph.checkpoint.serde.types import TASKS
|
|
18
|
+
from psycopg import Connection
|
|
19
|
+
from psycopg.rows import dict_row
|
|
20
|
+
from psycopg_pool import ConnectionPool
|
|
21
|
+
|
|
22
|
+
from langgraph.checkpoint.postgres import PostgresSaver, ShallowPostgresSaver
|
|
23
23
|
from tests.conftest import DEFAULT_POSTGRES_URI
|
|
24
24
|
|
|
25
25
|
|
|
@@ -143,8 +143,7 @@ def test_data():
|
|
|
143
143
|
config_1: RunnableConfig = {
|
|
144
144
|
"configurable": {
|
|
145
145
|
"thread_id": "thread-1",
|
|
146
|
-
|
|
147
|
-
"thread_ts": "1",
|
|
146
|
+
"checkpoint_id": "1",
|
|
148
147
|
"checkpoint_ns": "",
|
|
149
148
|
}
|
|
150
149
|
}
|
|
@@ -170,13 +169,11 @@ def test_data():
|
|
|
170
169
|
metadata_1: CheckpointMetadata = {
|
|
171
170
|
"source": "input",
|
|
172
171
|
"step": 2,
|
|
173
|
-
"writes": {},
|
|
174
172
|
"score": 1,
|
|
175
173
|
}
|
|
176
174
|
metadata_2: CheckpointMetadata = {
|
|
177
175
|
"source": "loop",
|
|
178
176
|
"step": 1,
|
|
179
|
-
"writes": {"foo": "bar"},
|
|
180
177
|
"score": None,
|
|
181
178
|
}
|
|
182
179
|
metadata_3: CheckpointMetadata = {}
|
|
@@ -203,7 +200,6 @@ def test_combined_metadata(saver_name: str, test_data) -> None:
|
|
|
203
200
|
metadata: CheckpointMetadata = {
|
|
204
201
|
"source": "loop",
|
|
205
202
|
"step": 1,
|
|
206
|
-
"writes": {"foo": "bar"},
|
|
207
203
|
"score": None,
|
|
208
204
|
}
|
|
209
205
|
saver.put(config, chkpnt, metadata, {})
|
|
@@ -229,7 +225,6 @@ def test_search(saver_name: str, test_data) -> None:
|
|
|
229
225
|
query_1 = {"source": "input"} # search by 1 key
|
|
230
226
|
query_2 = {
|
|
231
227
|
"step": 1,
|
|
232
|
-
"writes": {"foo": "bar"},
|
|
233
228
|
} # search by multiple keys
|
|
234
229
|
query_3: dict[str, Any] = {} # search by no keys, return all checkpoints
|
|
235
230
|
query_4 = {"source": "update", "step": 1} # no match
|
|
@@ -333,3 +328,33 @@ def test_pending_sends_migration(saver_name: str) -> None:
|
|
|
333
328
|
TASKS: ["send-1", "send-2", "send-3"]
|
|
334
329
|
}
|
|
335
330
|
assert TASKS in search_results[0].checkpoint["channel_versions"]
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
@pytest.mark.parametrize("saver_name", ["base", "pool", "pipe"])
|
|
334
|
+
def test_get_checkpoint_no_channel_values(
|
|
335
|
+
monkeypatch, saver_name: str, test_data
|
|
336
|
+
) -> None:
|
|
337
|
+
"""Backwards compatibility test that verifies a checkpoint with no channel_values key can be retrieved without throwing an error."""
|
|
338
|
+
with _saver(saver_name) as saver:
|
|
339
|
+
config = {
|
|
340
|
+
"configurable": {
|
|
341
|
+
"thread_id": "thread-2",
|
|
342
|
+
"checkpoint_ns": "",
|
|
343
|
+
"__super_private_key": "super_private_value",
|
|
344
|
+
},
|
|
345
|
+
}
|
|
346
|
+
chkpnt: Checkpoint = create_checkpoint(empty_checkpoint(), {}, 1)
|
|
347
|
+
saver.put(config, chkpnt, {}, {})
|
|
348
|
+
|
|
349
|
+
load_checkpoint_tuple = saver._load_checkpoint_tuple
|
|
350
|
+
|
|
351
|
+
def patched_load_checkpoint_tuple(value):
|
|
352
|
+
value["checkpoint"].pop("channel_values", None)
|
|
353
|
+
return load_checkpoint_tuple(value)
|
|
354
|
+
|
|
355
|
+
monkeypatch.setattr(
|
|
356
|
+
saver, "_load_checkpoint_tuple", patched_load_checkpoint_tuple
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
checkpoint = saver.get_tuple(config)
|
|
360
|
+
assert checkpoint.checkpoint["channel_values"] == {}
|