langgraph-checkpoint-postgres 2.0.22__tar.gz → 2.0.24__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.22 → langgraph_checkpoint_postgres-2.0.24}/PKG-INFO +1 -1
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/checkpoint/postgres/__init__.py +33 -20
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/checkpoint/postgres/aio.py +34 -20
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/checkpoint/postgres/base.py +1 -2
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/checkpoint/postgres/shallow.py +12 -12
- langgraph_checkpoint_postgres-2.0.24/langgraph/store/postgres/__init__.py +4 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/store/postgres/base.py +9 -8
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/pyproject.toml +1 -1
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/tests/test_async.py +37 -7
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/tests/test_store.py +40 -2
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/tests/test_sync.py +36 -7
- langgraph_checkpoint_postgres-2.0.24/uv.lock +1211 -0
- langgraph_checkpoint_postgres-2.0.22/langgraph/store/postgres/__init__.py +0 -4
- langgraph_checkpoint_postgres-2.0.22/uv.lock +0 -1225
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/.gitignore +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/Makefile +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/README.md +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/checkpoint/postgres/_ainternal.py +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/checkpoint/postgres/_internal.py +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/checkpoint/postgres/py.typed +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/store/postgres/aio.py +5 -5
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/langgraph/store/postgres/py.typed +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/tests/__init__.py +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/tests/compose-postgres.yml +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/tests/conftest.py +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/tests/embed_test_utils.py +0 -0
- {langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/tests/test_async_store.py +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-checkpoint-postgres
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.24
|
|
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,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,
|
|
@@ -21,10 +16,15 @@ from langgraph.checkpoint.base import (
|
|
|
21
16
|
get_checkpoint_id,
|
|
22
17
|
get_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,11 +284,9 @@ 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()
|
|
289
|
+
copy["channel_values"] = copy["channel_values"].copy()
|
|
292
290
|
next_config = {
|
|
293
291
|
"configurable": {
|
|
294
292
|
"thread_id": thread_id,
|
|
@@ -297,16 +295,28 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
297
295
|
}
|
|
298
296
|
}
|
|
299
297
|
|
|
298
|
+
# inline primitive values in checkpoint table
|
|
299
|
+
# others are stored in blobs table
|
|
300
|
+
blob_values = {}
|
|
301
|
+
for k, v in checkpoint["channel_values"].items():
|
|
302
|
+
if v is None or isinstance(v, (str, int, float, bool)):
|
|
303
|
+
pass
|
|
304
|
+
else:
|
|
305
|
+
blob_values[k] = copy["channel_values"].pop(k)
|
|
306
|
+
|
|
300
307
|
with self._cursor(pipeline=True) as cur:
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
308
|
+
if blob_versions := {
|
|
309
|
+
k: v for k, v in new_versions.items() if k in blob_values
|
|
310
|
+
}:
|
|
311
|
+
cur.executemany(
|
|
312
|
+
self.UPSERT_CHECKPOINT_BLOBS_SQL,
|
|
313
|
+
self._dump_blobs(
|
|
314
|
+
thread_id,
|
|
315
|
+
checkpoint_ns,
|
|
316
|
+
blob_values,
|
|
317
|
+
blob_versions,
|
|
318
|
+
),
|
|
319
|
+
)
|
|
310
320
|
cur.execute(
|
|
311
321
|
self.UPSERT_CHECKPOINTS_SQL,
|
|
312
322
|
(
|
|
@@ -439,7 +449,10 @@ class PostgresSaver(BasePostgresSaver):
|
|
|
439
449
|
},
|
|
440
450
|
{
|
|
441
451
|
**value["checkpoint"],
|
|
442
|
-
"channel_values":
|
|
452
|
+
"channel_values": {
|
|
453
|
+
**(value["checkpoint"].get("channel_values") or {}),
|
|
454
|
+
**self._load_blobs(value["channel_values"]),
|
|
455
|
+
},
|
|
443
456
|
},
|
|
444
457
|
value["metadata"],
|
|
445
458
|
(
|
|
@@ -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,
|
|
@@ -21,10 +16,15 @@ from langgraph.checkpoint.base import (
|
|
|
21
16
|
get_checkpoint_id,
|
|
22
17
|
get_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,11 +240,10 @@ 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()
|
|
246
|
+
copy["channel_values"] = copy["channel_values"].copy()
|
|
248
247
|
next_config = {
|
|
249
248
|
"configurable": {
|
|
250
249
|
"thread_id": thread_id,
|
|
@@ -253,17 +252,29 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
253
252
|
}
|
|
254
253
|
}
|
|
255
254
|
|
|
255
|
+
# inline primitive values in checkpoint table
|
|
256
|
+
# others are stored in blobs table
|
|
257
|
+
blob_values = {}
|
|
258
|
+
for k, v in checkpoint["channel_values"].items():
|
|
259
|
+
if v is None or isinstance(v, (str, int, float, bool)):
|
|
260
|
+
pass
|
|
261
|
+
else:
|
|
262
|
+
blob_values[k] = copy["channel_values"].pop(k)
|
|
263
|
+
|
|
256
264
|
async with self._cursor(pipeline=True) as cur:
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
265
|
+
if blob_versions := {
|
|
266
|
+
k: v for k, v in new_versions.items() if k in blob_values
|
|
267
|
+
}:
|
|
268
|
+
await cur.executemany(
|
|
269
|
+
self.UPSERT_CHECKPOINT_BLOBS_SQL,
|
|
270
|
+
await asyncio.to_thread(
|
|
271
|
+
self._dump_blobs,
|
|
272
|
+
thread_id,
|
|
273
|
+
checkpoint_ns,
|
|
274
|
+
blob_values,
|
|
275
|
+
blob_versions,
|
|
276
|
+
),
|
|
277
|
+
)
|
|
267
278
|
await cur.execute(
|
|
268
279
|
self.UPSERT_CHECKPOINTS_SQL,
|
|
269
280
|
(
|
|
@@ -397,7 +408,10 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
|
|
397
408
|
},
|
|
398
409
|
{
|
|
399
410
|
**value["checkpoint"],
|
|
400
|
-
"channel_values":
|
|
411
|
+
"channel_values": {
|
|
412
|
+
**(value["checkpoint"].get("channel_values") or {}),
|
|
413
|
+
**self._load_blobs(value["channel_values"]),
|
|
414
|
+
},
|
|
401
415
|
},
|
|
402
416
|
value["metadata"],
|
|
403
417
|
(
|
|
@@ -5,8 +5,6 @@ from collections.abc import Sequence
|
|
|
5
5
|
from typing import Any, Optional, cast
|
|
6
6
|
|
|
7
7
|
from langchain_core.runnables import RunnableConfig
|
|
8
|
-
from psycopg.types.json import Jsonb
|
|
9
|
-
|
|
10
8
|
from langgraph.checkpoint.base import (
|
|
11
9
|
WRITES_IDX_MAP,
|
|
12
10
|
BaseCheckpointSaver,
|
|
@@ -14,6 +12,7 @@ from langgraph.checkpoint.base import (
|
|
|
14
12
|
get_checkpoint_id,
|
|
15
13
|
)
|
|
16
14
|
from langgraph.checkpoint.serde.types import TASKS
|
|
15
|
+
from psycopg.types.json import Jsonb
|
|
17
16
|
|
|
18
17
|
MetadataInput = Optional[dict[str, Any]]
|
|
19
18
|
|
|
@@ -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_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
|
)
|
|
@@ -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
|
)
|
|
@@ -22,14 +22,6 @@ from typing import (
|
|
|
22
22
|
)
|
|
23
23
|
|
|
24
24
|
import orjson
|
|
25
|
-
from psycopg import Capabilities, Connection, Cursor, Pipeline
|
|
26
|
-
from psycopg.rows import DictRow, dict_row
|
|
27
|
-
from psycopg.types.json import Jsonb
|
|
28
|
-
from psycopg_pool import ConnectionPool
|
|
29
|
-
from typing_extensions import TypedDict
|
|
30
|
-
|
|
31
|
-
from langgraph.checkpoint.postgres import _ainternal as _ainternal
|
|
32
|
-
from langgraph.checkpoint.postgres import _internal as _pg_internal
|
|
33
25
|
from langgraph.store.base import (
|
|
34
26
|
BaseStore,
|
|
35
27
|
GetOp,
|
|
@@ -46,6 +38,14 @@ from langgraph.store.base import (
|
|
|
46
38
|
get_text_at_path,
|
|
47
39
|
tokenize_path,
|
|
48
40
|
)
|
|
41
|
+
from psycopg import Capabilities, Connection, Cursor, Pipeline
|
|
42
|
+
from psycopg.rows import DictRow, dict_row
|
|
43
|
+
from psycopg.types.json import Jsonb
|
|
44
|
+
from psycopg_pool import ConnectionPool
|
|
45
|
+
from typing_extensions import TypedDict
|
|
46
|
+
|
|
47
|
+
from langgraph.checkpoint.postgres import _ainternal as _ainternal
|
|
48
|
+
from langgraph.checkpoint.postgres import _internal as _pg_internal
|
|
49
49
|
|
|
50
50
|
if TYPE_CHECKING:
|
|
51
51
|
from langchain_core.embeddings import Embeddings
|
|
@@ -756,6 +756,7 @@ class PostgresStore(BaseStore, BasePostgresStore[_pg_internal.Conn]):
|
|
|
756
756
|
If provided, will create a connection pool and use it instead of a single connection.
|
|
757
757
|
This overrides the `pipeline` argument.
|
|
758
758
|
index: The index configuration for the store.
|
|
759
|
+
ttl: The TTL configuration for the store.
|
|
759
760
|
|
|
760
761
|
Returns:
|
|
761
762
|
PostgresStore: A new PostgresStore instance.
|
{langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/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
|
}
|
|
@@ -345,3 +344,34 @@ async def test_pending_sends_migration(saver_name: str) -> None:
|
|
|
345
344
|
TASKS: ["send-1", "send-2", "send-3"]
|
|
346
345
|
}
|
|
347
346
|
assert TASKS in search_results[0].checkpoint["channel_versions"]
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
@pytest.mark.parametrize("saver_name", ["base", "pool", "pipe"])
|
|
350
|
+
async def test_get_checkpoint_no_channel_values(
|
|
351
|
+
monkeypatch, saver_name: str, test_data
|
|
352
|
+
) -> None:
|
|
353
|
+
"""Backwards compatibility test that verifies a checkpoint with no channel_values key can be retrieved without throwing an error."""
|
|
354
|
+
async with _saver(saver_name) as saver:
|
|
355
|
+
config = {
|
|
356
|
+
"configurable": {
|
|
357
|
+
"thread_id": "thread-2",
|
|
358
|
+
"checkpoint_ns": "",
|
|
359
|
+
"__super_private_key": "super_private_value",
|
|
360
|
+
},
|
|
361
|
+
"metadata": {"run_id": "my_run_id"},
|
|
362
|
+
}
|
|
363
|
+
chkpnt: Checkpoint = create_checkpoint(empty_checkpoint(), {}, 1)
|
|
364
|
+
await saver.aput(config, chkpnt, {}, {})
|
|
365
|
+
|
|
366
|
+
load_checkpoint_tuple = saver._load_checkpoint_tuple
|
|
367
|
+
|
|
368
|
+
def patched_load_checkpoint_tuple(value):
|
|
369
|
+
value["checkpoint"].pop("channel_values", None)
|
|
370
|
+
return load_checkpoint_tuple(value)
|
|
371
|
+
|
|
372
|
+
monkeypatch.setattr(
|
|
373
|
+
saver, "_load_checkpoint_tuple", patched_load_checkpoint_tuple
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
checkpoint = await saver.aget_tuple(config)
|
|
377
|
+
assert checkpoint.checkpoint["channel_values"] == {}
|
{langgraph_checkpoint_postgres-2.0.22 → langgraph_checkpoint_postgres-2.0.24}/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.22 → langgraph_checkpoint_postgres-2.0.24}/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
|
}
|
|
@@ -333,3 +332,33 @@ def test_pending_sends_migration(saver_name: str) -> None:
|
|
|
333
332
|
TASKS: ["send-1", "send-2", "send-3"]
|
|
334
333
|
}
|
|
335
334
|
assert TASKS in search_results[0].checkpoint["channel_versions"]
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
@pytest.mark.parametrize("saver_name", ["base", "pool", "pipe"])
|
|
338
|
+
def test_get_checkpoint_no_channel_values(
|
|
339
|
+
monkeypatch, saver_name: str, test_data
|
|
340
|
+
) -> None:
|
|
341
|
+
"""Backwards compatibility test that verifies a checkpoint with no channel_values key can be retrieved without throwing an error."""
|
|
342
|
+
with _saver(saver_name) as saver:
|
|
343
|
+
config = {
|
|
344
|
+
"configurable": {
|
|
345
|
+
"thread_id": "thread-2",
|
|
346
|
+
"checkpoint_ns": "",
|
|
347
|
+
"__super_private_key": "super_private_value",
|
|
348
|
+
},
|
|
349
|
+
}
|
|
350
|
+
chkpnt: Checkpoint = create_checkpoint(empty_checkpoint(), {}, 1)
|
|
351
|
+
saver.put(config, chkpnt, {}, {})
|
|
352
|
+
|
|
353
|
+
load_checkpoint_tuple = saver._load_checkpoint_tuple
|
|
354
|
+
|
|
355
|
+
def patched_load_checkpoint_tuple(value):
|
|
356
|
+
value["checkpoint"].pop("channel_values", None)
|
|
357
|
+
return load_checkpoint_tuple(value)
|
|
358
|
+
|
|
359
|
+
monkeypatch.setattr(
|
|
360
|
+
saver, "_load_checkpoint_tuple", patched_load_checkpoint_tuple
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
checkpoint = saver.get_tuple(config)
|
|
364
|
+
assert checkpoint.checkpoint["channel_values"] == {}
|