mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-26 17:42:24 +02:00
Follow-up to review on #8537: turn on ruff's `PLC0415` (`import-outside-top-level`) so deferred imports in tests stop accumulating. Scoped to `checkpoint-postgres` and `checkpoint-sqlite` rather than repo-wide, because the sweep turns up three different things and only one of them is a style problem. ### What the rule finds today ``` package tests src files checkpoint 13 10 11 checkpoint-conformance 0 10 4 checkpoint-postgres 6 0 2 checkpoint-sqlite 9 0 3 langgraph 130 23 32 prebuilt 14 3 7 cli 9 14 10 sdk-py 189 23 38 ──────────────────── 370 83 107 ``` 453 violations across 107 files, and ruff has no autofix for this rule. ### Three categories, not one **Style — hoist.** `checkpoint-sqlite/tests/test_store.py` deferred `math`, `random`, `time`, `Counter` and `defaultdict` inside methods for no reason. **Deliberate — keep, annotate.** `checkpoint-postgres/tests/test_async.py` defers behind `pytest.importorskip("langgraph.channels.delta")` because langgraph core is *not* a test dependency of that package. Hoisting would break the skip. Those get `# noqa: PLC0415` and a comment. **Redundant guard — hoist.** `checkpoint-sqlite/tests/test_conformance_delta.py` deferred imports only to get past its own `importorskip`. Imports move up; the `aiosqlite` guard stays, since that dependency genuinely can be absent. The second category is why I did not enable this everywhere in one go. Most of the 83 source-level violations look like the same pattern — optional-dependency handling and circular-import avoidance in `jsonplus.py`, `embed.py`, `encrypted.py` and friends. Blanket-enabling would mean `# noqa` on a lot of correct code, and each one wants an owner's eye rather than a mechanical pass. These two packages are clean to enforce today because both have **zero** source-level violations. ### Suggested rollout for the rest Either extend package by package as owners confirm which deferrals are intentional, or enable everywhere at once with `per-file-ignores` grandfathering the current 107 files so new code is blocked immediately and the debt burns down. Happy to do either — the second is a smaller diff but leaves a long ignore list. ### Verified `checkpoint-sqlite` 118 passed, `checkpoint-postgres` 264 passed on PG 15 and 16, `make lint` clean in both. One overlap worth flagging: `checkpoint-sqlite/tests/test_conformance_delta.py` is also touched by #8537. The change is identical in both, so it should merge cleanly either way.
36 lines
1.1 KiB
Python
36 lines
1.1 KiB
Python
"""Run delta-channel conformance capabilities against AsyncSqliteSaver."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
pytest.importorskip(
|
|
"langgraph.checkpoint.conformance",
|
|
reason="langgraph-checkpoint-conformance not installed",
|
|
)
|
|
pytest.importorskip("aiosqlite", reason="aiosqlite not installed")
|
|
|
|
from langgraph.checkpoint.conformance import validate # noqa: E402
|
|
from langgraph.checkpoint.conformance.initializer import checkpointer_test # noqa: E402
|
|
|
|
from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver # noqa: E402
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delta_channel_conformance():
|
|
@checkpointer_test(name="AsyncSqliteSaver")
|
|
async def sqlite_saver():
|
|
async with AsyncSqliteSaver.from_conn_string(":memory:") as saver:
|
|
yield saver
|
|
|
|
report = await validate(
|
|
sqlite_saver,
|
|
capabilities={
|
|
"delta_channel_history",
|
|
},
|
|
)
|
|
for cap, result in report.results.items():
|
|
if result.passed is False:
|
|
details = "\n".join(result.failures or [])
|
|
pytest.fail(f"Capability {cap} failed:\n{details}")
|