mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-10 11:47:51 +02:00
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.
This commit is contained in:
@@ -72,10 +72,15 @@ lint.select = [
|
||||
"UP", # pyupgrade
|
||||
"B", # flake8-bugbear
|
||||
"I", # isort
|
||||
"PLC0415", # import-outside-top-level
|
||||
"RUF100", # unused noqa directive
|
||||
"UP", # pyupgrade
|
||||
]
|
||||
lint.ignore = ["E501", "B008"]
|
||||
# PLC0415 (import-outside-top-level) is enforced in tests only. Library code
|
||||
# still has deferred imports that have not been reviewed, so it stays exempt
|
||||
# for now.
|
||||
lint.per-file-ignores = { "langgraph_cli/**" = ["PLC0415"], "generate_schema.py" = ["PLC0415"] }
|
||||
target-version = "py310"
|
||||
|
||||
[tool.ty.rules]
|
||||
|
||||
@@ -11,6 +11,7 @@ from langgraph_cli.archive import (
|
||||
_tar_filter,
|
||||
create_archive,
|
||||
)
|
||||
from langgraph_cli.config import LocalDeps
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# _tar_filter
|
||||
@@ -198,7 +199,6 @@ class TestCreateArchive:
|
||||
|
||||
@patch("langgraph_cli.archive._assemble_local_deps")
|
||||
def test_yields_archive_with_config(self, mock_deps, tmp_path):
|
||||
from langgraph_cli.config import LocalDeps
|
||||
|
||||
config_file = self._make_project(tmp_path)
|
||||
mock_deps.return_value = LocalDeps(
|
||||
@@ -218,7 +218,6 @@ class TestCreateArchive:
|
||||
|
||||
@patch("langgraph_cli.archive._assemble_local_deps")
|
||||
def test_excludes_pycache(self, mock_deps, tmp_path):
|
||||
from langgraph_cli.config import LocalDeps
|
||||
|
||||
config_file = self._make_project(tmp_path)
|
||||
mock_deps.return_value = LocalDeps(
|
||||
@@ -232,7 +231,6 @@ class TestCreateArchive:
|
||||
|
||||
@patch("langgraph_cli.archive._assemble_local_deps")
|
||||
def test_cleans_up_tmp_dir_on_normal_exit(self, mock_deps, tmp_path):
|
||||
from langgraph_cli.config import LocalDeps
|
||||
|
||||
config_file = self._make_project(tmp_path)
|
||||
mock_deps.return_value = LocalDeps(
|
||||
@@ -247,7 +245,6 @@ class TestCreateArchive:
|
||||
|
||||
@patch("langgraph_cli.archive._assemble_local_deps")
|
||||
def test_cleans_up_tmp_dir_on_exception(self, mock_deps, tmp_path):
|
||||
from langgraph_cli.config import LocalDeps
|
||||
|
||||
config_file = self._make_project(tmp_path)
|
||||
mock_deps.return_value = LocalDeps(
|
||||
@@ -264,7 +261,6 @@ class TestCreateArchive:
|
||||
@patch("langgraph_cli.archive._assemble_local_deps")
|
||||
@patch("langgraph_cli.archive._MAX_SIZE", 10)
|
||||
def test_raises_on_oversized_archive(self, mock_deps, tmp_path):
|
||||
from langgraph_cli.config import LocalDeps
|
||||
|
||||
config_file = self._make_project(tmp_path)
|
||||
mock_deps.return_value = LocalDeps(
|
||||
@@ -278,7 +274,6 @@ class TestCreateArchive:
|
||||
@patch("langgraph_cli.archive._assemble_local_deps")
|
||||
def test_handles_extra_contexts(self, mock_deps, tmp_path):
|
||||
"""Monorepo case: project + sibling dependency directory."""
|
||||
from langgraph_cli.config import LocalDeps
|
||||
|
||||
project = tmp_path / "myproject"
|
||||
project.mkdir()
|
||||
|
||||
@@ -347,7 +347,6 @@ class TestCallHostBackendWithOptionalTenant:
|
||||
|
||||
def test_workspace_prompt_blocked_by_no_input(self, monkeypatch):
|
||||
"""With _no_input=True, 403 requiring workspace should raise ClickException."""
|
||||
import langgraph_cli.deploy as deploy_mod
|
||||
|
||||
monkeypatch.setattr(deploy_mod, "_no_input", True)
|
||||
|
||||
@@ -515,7 +514,6 @@ class TestEmitterTextMode:
|
||||
|
||||
class TestCreateHostBackendClientNoInput:
|
||||
def test_raises_when_no_api_key_and_no_input(self, monkeypatch, tmp_path):
|
||||
import langgraph_cli.deploy as deploy_mod
|
||||
|
||||
monkeypatch.setattr(deploy_mod, "_no_input", True)
|
||||
monkeypatch.delenv("LANGSMITH_API_KEY", raising=False)
|
||||
@@ -530,7 +528,6 @@ class TestCreateHostBackendClientNoInput:
|
||||
)
|
||||
|
||||
def test_succeeds_with_api_key_in_env(self, monkeypatch, tmp_path):
|
||||
import langgraph_cli.deploy as deploy_mod
|
||||
|
||||
monkeypatch.setattr(deploy_mod, "_no_input", True)
|
||||
monkeypatch.setenv("LANGSMITH_API_KEY", "lsv2_test")
|
||||
|
||||
Reference in New Issue
Block a user