Files
langgraph/libs/sdk-py/tests/integration/conftest.py
T
Elior Nataf LackritzandGitHub ea5f9cc9fb chore: enforce PLC0415 in tests for the remaining packages (#8547)
Follow-up to #8540, which turned on `PLC0415` (import-outside-top-level)
for checkpoint-postgres and checkpoint-sqlite. This does the remaining
six packages: checkpoint, checkpoint-conformance, langgraph, prebuilt,
cli, sdk-py.

Scoped to tests, per @sydney-runkle's call on #8540: library code is
exempted with `per-file-ignores`, since it still has deferred imports
nobody has reviewed and mixing that in would make this hard to read.

## What changed

Function-level imports across 56 test files moved to module level. Nine
could not move and carry an explicit `# noqa: PLC0415` with a reason:

| File | Why it stays local |
|---|---|
| `libs/langgraph/tests/test_deprecation.py` (4) | the import has to run
inside `pytest.warns` for the warning to be observed |
| `libs/langgraph/tests/test_serde_allowlist.py` | try/except guard,
skips when langchain_core is absent |
| `libs/langgraph/tests/test_delta_channel_benchmark.py` | optional
psycopg probe |
| `libs/checkpoint/tests/test_conformance_delta.py` (3) | protected by a
module-level `pytest.importorskip`; hoisting past the guard turns a skip
into a collection error |

That last one is the trap: an import moved above `pytest.importorskip`
silently defeats the guard. I hit it locally and it turned the skip into
a `ModuleNotFoundError` at collection. Every file with an `importorskip`
or `except ImportError` was checked by hand for this.

## Verification

`make lint` and `make test` in each of the six:

| Package | Tests |
|---|---|
| checkpoint | 156 passed, 17 skipped |
| checkpoint-conformance | 1 passed |
| langgraph | 1968 passed, 4 skipped |
| prebuilt | 284 passed |
| cli | 336 passed |
| sdk-py | 493 passed |

Also confirmed the rule actually fires: a throwaway test file with a
function-level import is flagged in all six packages, and the source
exemption holds.
2026-08-07 09:40:18 -04:00

72 lines
2.3 KiB
Python

"""Shared fixtures for the integration suite.
These tests require a running langgraph-api server at `LANGGRAPH_INTEGRATION_URL`
(defaults to `http://localhost:2024`). Stand it up via the docker stack in
`libs/sdk-py/integration/`:
cd libs/sdk-py/integration && docker compose up -d
The `integration` marker is registered in `pyproject.toml` and excluded by
default in pytest's `addopts`; opt in with `pytest -m integration`.
"""
from __future__ import annotations
import os
from collections.abc import AsyncIterator, Iterator
import httpx
import pytest
from langgraph_sdk._async.http import HttpClient
from langgraph_sdk._async.threads import ThreadsClient
from langgraph_sdk._sync.http import SyncHttpClient
from langgraph_sdk._sync.threads import SyncThreadsClient
BASE_URL = os.environ.get("LANGGRAPH_INTEGRATION_URL", "http://localhost:2024")
ASSISTANT_ID = "agent"
TOOLS_ASSISTANT_ID = "tools_agent"
DEEP_AGENT_ASSISTANT_ID = "deep_agent"
FACTORY_ASSISTANT_ID = "factory_agent"
EXPECTED_TERMINAL_ITEMS = ["streamed", "tool", "asked", "sub"]
@pytest.fixture(scope="session", autouse=True)
def _require_running_api() -> None:
"""Skip the whole integration suite if the API isn't reachable.
Autouse + session-scoped so a missing stack short-circuits before any
test runs (no per-test connection timeouts piling up).
"""
try:
resp = httpx.get(f"{BASE_URL}/ok", timeout=2.0)
resp.raise_for_status()
except Exception as err:
pytest.skip(
f"langgraph-api not reachable at {BASE_URL}: {err!r}. "
f"Bring up the stack with `cd libs/sdk-py/integration && docker compose up -d`."
)
@pytest.fixture
async def async_threads() -> AsyncIterator[tuple[object, httpx.AsyncClient]]:
"""Build an async ThreadsClient. Yields `(threads, raw_httpx)` so tests can close raw."""
raw = httpx.AsyncClient(base_url=BASE_URL, timeout=30.0)
try:
yield ThreadsClient(HttpClient(raw)), raw
finally:
await raw.aclose()
@pytest.fixture
def sync_threads() -> Iterator[tuple[object, httpx.Client]]:
"""Build a sync ThreadsClient. Yields `(threads, raw_httpx)` so tests can close raw."""
raw = httpx.Client(base_url=BASE_URL, timeout=30.0)
try:
yield SyncThreadsClient(SyncHttpClient(raw)), raw
finally:
raw.close()