langgraph-checkpoint-sqlite 2.0.1__tar.gz → 2.0.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langgraph-checkpoint-sqlite
3
- Version: 2.0.1
3
+ Version: 2.0.3
4
4
  Summary: Library with a SQLite implementation of LangGraph checkpoint saver.
5
5
  Home-page: https://www.github.com/langchain-ai/langgraph
6
6
  License: MIT
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Requires-Dist: aiosqlite (>=0.20.0,<0.21.0)
15
- Requires-Dist: langgraph-checkpoint (>=2.0.2,<3.0.0)
15
+ Requires-Dist: langgraph-checkpoint (>=2.0.10,<3.0.0)
16
16
  Project-URL: Repository, https://www.github.com/langchain-ai/langgraph
17
17
  Description-Content-Type: text/markdown
18
18
 
@@ -110,7 +110,7 @@ class SqliteSaver(BaseCheckpointSaver[str]):
110
110
  check_same_thread=False,
111
111
  )
112
112
  ) as conn:
113
- yield SqliteSaver(conn)
113
+ yield cls(conn)
114
114
 
115
115
  def setup(self) -> None:
116
116
  """Set up the checkpoint database.
@@ -424,6 +424,7 @@ class SqliteSaver(BaseCheckpointSaver[str]):
424
424
  config: RunnableConfig,
425
425
  writes: Sequence[Tuple[str, Any]],
426
426
  task_id: str,
427
+ task_path: str = "",
427
428
  ) -> None:
428
429
  """Store intermediate writes linked to a checkpoint.
429
430
 
@@ -433,6 +434,7 @@ class SqliteSaver(BaseCheckpointSaver[str]):
433
434
  config (RunnableConfig): Configuration of the related checkpoint.
434
435
  writes (Sequence[Tuple[str, Any]]): List of writes to store, each as (channel, value) pair.
435
436
  task_id (str): Identifier for the task creating the writes.
437
+ task_path (str): Path of the task creating the writes.
436
438
  """
437
439
  query = (
438
440
  "INSERT OR REPLACE INTO writes (thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
@@ -1,17 +1,8 @@
1
1
  import asyncio
2
2
  import random
3
+ from collections.abc import AsyncIterator, Iterator, Sequence
3
4
  from contextlib import asynccontextmanager
4
- from typing import (
5
- Any,
6
- AsyncIterator,
7
- Callable,
8
- Dict,
9
- Iterator,
10
- Optional,
11
- Sequence,
12
- Tuple,
13
- TypeVar,
14
- )
5
+ from typing import Any, Callable, Optional, TypeVar
15
6
 
16
7
  import aiosqlite
17
8
  from langchain_core.runnables import RunnableConfig
@@ -137,7 +128,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
137
128
  AsyncSqliteSaver: A new AsyncSqliteSaver instance.
138
129
  """
139
130
  async with aiosqlite.connect(conn_string) as conn:
140
- yield AsyncSqliteSaver(conn)
131
+ yield cls(conn)
141
132
 
142
133
  def get_tuple(self, config: RunnableConfig) -> Optional[CheckpointTuple]:
143
134
  """Get a checkpoint tuple from the database.
@@ -159,7 +150,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
159
150
  if asyncio.get_running_loop() is self.loop:
160
151
  raise asyncio.InvalidStateError(
161
152
  "Synchronous calls to AsyncSqliteSaver are only allowed from a "
162
- "different thread. From the main thread, use the async interface."
153
+ "different thread. From the main thread, use the async interface. "
163
154
  "For example, use `await checkpointer.aget_tuple(...)` or `await "
164
155
  "graph.ainvoke(...)`."
165
156
  )
@@ -173,7 +164,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
173
164
  self,
174
165
  config: Optional[RunnableConfig],
175
166
  *,
176
- filter: Optional[Dict[str, Any]] = None,
167
+ filter: Optional[dict[str, Any]] = None,
177
168
  before: Optional[RunnableConfig] = None,
178
169
  limit: Optional[int] = None,
179
170
  ) -> Iterator[CheckpointTuple]:
@@ -191,11 +182,23 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
191
182
  Yields:
192
183
  Iterator[CheckpointTuple]: An iterator of matching checkpoint tuples.
193
184
  """
185
+ try:
186
+ # check if we are in the main thread, only bg threads can block
187
+ # we don't check in other methods to avoid the overhead
188
+ if asyncio.get_running_loop() is self.loop:
189
+ raise asyncio.InvalidStateError(
190
+ "Synchronous calls to AsyncSqliteSaver are only allowed from a "
191
+ "different thread. From the main thread, use the async interface. "
192
+ "For example, use `checkpointer.alist(...)` or `await "
193
+ "graph.ainvoke(...)`."
194
+ )
195
+ except RuntimeError:
196
+ pass
194
197
  aiter_ = self.alist(config, filter=filter, before=before, limit=limit)
195
198
  while True:
196
199
  try:
197
200
  yield asyncio.run_coroutine_threadsafe(
198
- anext(aiter_),
201
+ anext(aiter_), # noqa: F821
199
202
  self.loop,
200
203
  ).result()
201
204
  except StopAsyncIteration:
@@ -227,10 +230,14 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
227
230
  ).result()
228
231
 
229
232
  def put_writes(
230
- self, config: RunnableConfig, writes: Sequence[Tuple[str, Any]], task_id: str
233
+ self,
234
+ config: RunnableConfig,
235
+ writes: Sequence[tuple[str, Any]],
236
+ task_id: str,
237
+ task_path: str = "",
231
238
  ) -> None:
232
239
  return asyncio.run_coroutine_threadsafe(
233
- self.aput_writes(config, writes, task_id), self.loop
240
+ self.aput_writes(config, writes, task_id, task_path), self.loop
234
241
  ).result()
235
242
 
236
243
  async def setup(self) -> None:
@@ -360,7 +367,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
360
367
  self,
361
368
  config: Optional[RunnableConfig],
362
369
  *,
363
- filter: Optional[Dict[str, Any]] = None,
370
+ filter: Optional[dict[str, Any]] = None,
364
371
  before: Optional[RunnableConfig] = None,
365
372
  limit: Optional[int] = None,
366
373
  ) -> AsyncIterator[CheckpointTuple]:
@@ -386,9 +393,11 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
386
393
  ORDER BY checkpoint_id DESC"""
387
394
  if limit:
388
395
  query += f" LIMIT {limit}"
389
- async with self.lock, self.conn.execute(
390
- query, params
391
- ) as cur, self.conn.cursor() as wcur:
396
+ async with (
397
+ self.lock,
398
+ self.conn.execute(query, params) as cur,
399
+ self.conn.cursor() as wcur,
400
+ ):
392
401
  async for (
393
402
  thread_id,
394
403
  checkpoint_ns,
@@ -455,16 +464,19 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
455
464
  checkpoint_ns = config["configurable"]["checkpoint_ns"]
456
465
  type_, serialized_checkpoint = self.serde.dumps_typed(checkpoint)
457
466
  serialized_metadata = self.jsonplus_serde.dumps(metadata)
458
- async with self.lock, self.conn.execute(
459
- "INSERT OR REPLACE INTO checkpoints (thread_id, checkpoint_ns, checkpoint_id, parent_checkpoint_id, type, checkpoint, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)",
460
- (
461
- str(config["configurable"]["thread_id"]),
462
- checkpoint_ns,
463
- checkpoint["id"],
464
- config["configurable"].get("checkpoint_id"),
465
- type_,
466
- serialized_checkpoint,
467
- serialized_metadata,
467
+ async with (
468
+ self.lock,
469
+ self.conn.execute(
470
+ "INSERT OR REPLACE INTO checkpoints (thread_id, checkpoint_ns, checkpoint_id, parent_checkpoint_id, type, checkpoint, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)",
471
+ (
472
+ str(config["configurable"]["thread_id"]),
473
+ checkpoint_ns,
474
+ checkpoint["id"],
475
+ config["configurable"].get("checkpoint_id"),
476
+ type_,
477
+ serialized_checkpoint,
478
+ serialized_metadata,
479
+ ),
468
480
  ),
469
481
  ):
470
482
  await self.conn.commit()
@@ -479,8 +491,9 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
479
491
  async def aput_writes(
480
492
  self,
481
493
  config: RunnableConfig,
482
- writes: Sequence[Tuple[str, Any]],
494
+ writes: Sequence[tuple[str, Any]],
483
495
  task_id: str,
496
+ task_path: str = "",
484
497
  ) -> None:
485
498
  """Store intermediate writes linked to a checkpoint asynchronously.
486
499
 
@@ -490,6 +503,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
490
503
  config (RunnableConfig): Configuration of the related checkpoint.
491
504
  writes (Sequence[Tuple[str, Any]]): List of writes to store, each as (channel, value) pair.
492
505
  task_id (str): Identifier for the task creating the writes.
506
+ task_path (str): Path of the task creating the writes.
493
507
  """
494
508
  query = (
495
509
  "INSERT OR REPLACE INTO writes (thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langgraph-checkpoint-sqlite"
3
- version = "2.0.1"
3
+ version = "2.0.3"
4
4
  description = "Library with a SQLite implementation of LangGraph checkpoint saver."
5
5
  authors = []
6
6
  license = "MIT"
@@ -10,7 +10,7 @@ packages = [{ include = "langgraph" }]
10
10
 
11
11
  [tool.poetry.dependencies]
12
12
  python = "^3.9.0"
13
- langgraph-checkpoint = "^2.0.2"
13
+ langgraph-checkpoint = "^2.0.10"
14
14
  aiosqlite = "^0.20.0"
15
15
 
16
16
  [tool.poetry.group.dev.dependencies]