diff --git a/libs/langgraph/Makefile b/libs/langgraph/Makefile index bfad74585..c5ce24a43 100644 --- a/libs/langgraph/Makefile +++ b/libs/langgraph/Makefile @@ -44,13 +44,26 @@ stop-services: docker compose -f tests/compose-postgres.yml -f tests/compose-redis.yml down -v start-dev-server: - LOG_LEVEL=warning uv run langgraph dev --config tests/example_app/langgraph.json --no-browser & echo "$$!" > .devserver.pid - @echo "Dev server started." + uv sync --frozen --group test --no-dev + @LOG_LEVEL=warning uv run --no-sync langgraph dev --config tests/example_app/langgraph.json --no-browser --no-reload & \ + PID=$$!; echo "$$PID" > .devserver.pid; \ + for ATTEMPT in $$(seq 1 60); do \ + if ! kill -0 $$PID 2>/dev/null; then break; fi; \ + if curl --fail --silent --max-time 1 http://localhost:2024/ok >/dev/null; then \ + echo "Dev server ready."; exit 0; \ + fi; \ + sleep 1; \ + done; \ + echo "Dev server failed to become ready." >&2; \ + kill $$PID 2>/dev/null || true; \ + wait $$PID 2>/dev/null || true; \ + rm -f .devserver.pid; exit 1 stop-dev-server: @if [ -f .devserver.pid ]; then \ - kill `cat .devserver.pid` && rm .devserver.pid; \ - echo "Dev server stopped."; \ + kill $$(cat .devserver.pid) 2>/dev/null || true; \ + rm -f .devserver.pid; \ + echo "Dev server stopped."; \ else \ echo "No dev server PID file found."; \ fi @@ -60,13 +73,12 @@ NO_DOCKER ?= $(sh command -v docker >/dev/null 2>&1 && echo "false" || echo "tru test: if [ "$(NO_DOCKER)" = "false" ]; then \ - make start-services &&\ - make start-dev-server &&\ - uv run pytest $(TEST); \ - EXIT_CODE=$$?; \ - make stop-services; \ - make stop-dev-server; \ - exit $$EXIT_CODE; \ + trap '$(MAKE) stop-dev-server; $(MAKE) stop-services' EXIT; \ + trap 'exit 130' INT; trap 'exit 143' TERM; \ + $(MAKE) start-services &&\ + $(MAKE) start-dev-server &&\ + uv run --no-sync pytest $(TEST); \ + exit $$?; \ else \ NO_DOCKER=true uv run pytest $(TEST) ; \ EXIT_CODE=$$?; \ @@ -74,13 +86,12 @@ test: fi test_parallel: - make start-services &&\ - make start-dev-server &&\ - uv run pytest -n auto --dist worksteal $(TEST) -vv --lf; \ - EXIT_CODE=$$?; \ - make stop-services; \ - make stop-dev-server; \ - exit $$EXIT_CODE + trap '$(MAKE) stop-dev-server; $(MAKE) stop-services' EXIT; \ + trap 'exit 130' INT; trap 'exit 143' TERM; \ + $(MAKE) start-services &&\ + $(MAKE) start-dev-server &&\ + uv run --no-sync pytest -n auto --dist worksteal $(TEST) -vv --lf; \ + exit $$? integration_tests: uv run pytest integration_tests diff --git a/libs/langgraph/uv.lock b/libs/langgraph/uv.lock index 452d26676..2d93cae4d 100644 --- a/libs/langgraph/uv.lock +++ b/libs/langgraph/uv.lock @@ -1842,7 +1842,7 @@ dev = [ { name = "langgraph-checkpoint", editable = "../checkpoint" }, { name = "langgraph-checkpoint-postgres", editable = "../checkpoint-postgres" }, { name = "langgraph-checkpoint-sqlite", editable = "../checkpoint-sqlite" }, - { name = "psycopg-binary" }, + { name = "psycopg", extras = ["binary"] }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-mock" }, @@ -1862,7 +1862,7 @@ test = [ { name = "langgraph-checkpoint", editable = "../checkpoint" }, { name = "langgraph-checkpoint-postgres", editable = "../checkpoint-postgres" }, { name = "langgraph-checkpoint-sqlite", editable = "../checkpoint-sqlite" }, - { name = "psycopg-binary" }, + { name = "psycopg", extras = ["binary"] }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-mock" }, diff --git a/libs/prebuilt/pyproject.toml b/libs/prebuilt/pyproject.toml index 3c9c57315..dbd909273 100644 --- a/libs/prebuilt/pyproject.toml +++ b/libs/prebuilt/pyproject.toml @@ -46,7 +46,7 @@ test = [ "langgraph-checkpoint-sqlite", "langgraph-checkpoint-postgres", "syrupy", - "psycopg-binary", + "psycopg[binary]", ] lint = [ "ruff", diff --git a/libs/prebuilt/uv.lock b/libs/prebuilt/uv.lock index 386c58fe6..23566cb5a 100644 --- a/libs/prebuilt/uv.lock +++ b/libs/prebuilt/uv.lock @@ -527,7 +527,7 @@ dev = [ { name = "langgraph-checkpoint" }, { name = "langgraph-checkpoint-postgres" }, { name = "langgraph-checkpoint-sqlite" }, - { name = "psycopg-binary" }, + { name = "psycopg", extra = ["binary"] }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-mock" }, @@ -547,7 +547,7 @@ test = [ { name = "langgraph-checkpoint" }, { name = "langgraph-checkpoint-postgres" }, { name = "langgraph-checkpoint-sqlite" }, - { name = "psycopg-binary" }, + { name = "psycopg", extra = ["binary"] }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-mock" }, @@ -569,7 +569,7 @@ dev = [ { name = "langgraph-checkpoint", editable = "../checkpoint" }, { name = "langgraph-checkpoint-postgres", editable = "../checkpoint-postgres" }, { name = "langgraph-checkpoint-sqlite", editable = "../checkpoint-sqlite" }, - { name = "psycopg-binary" }, + { name = "psycopg", extras = ["binary"] }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-mock" }, @@ -589,7 +589,7 @@ test = [ { name = "langgraph-checkpoint", editable = "../checkpoint" }, { name = "langgraph-checkpoint-postgres", editable = "../checkpoint-postgres" }, { name = "langgraph-checkpoint-sqlite", editable = "../checkpoint-sqlite" }, - { name = "psycopg-binary" }, + { name = "psycopg", extras = ["binary"] }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-mock" }, @@ -821,15 +821,20 @@ wheels = [ [[package]] name = "psycopg" -version = "3.3.4" +version = "3.3.6" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.13'" }, { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" } +sdist = { url = "https://files.pythonhosted.org/packages/76/26/3ea4ca5eaea1c0debcdf7ee7c1613fbe721dc27a03c461c0817ffd8a0601/psycopg-3.3.6.tar.gz", hash = "sha256:c081f2250df751a943036e42db6df4571c66cd0aabe8291a7a506512b12007d2", size = 168171, upload-time = "2026-09-18T13:22:55.152Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" }, + { url = "https://files.pythonhosted.org/packages/4e/de/748bd7609c71cae5d737f0ba9192f19329f70180ecda8fff3cac02c5abe3/psycopg-3.3.6-py3-none-any.whl", hash = "sha256:a1db9f7148b06a28606767efaca51fa6f9398c5c0a3810519be69d7000bdb631", size = 215490, upload-time = "2026-09-18T13:15:29.374Z" }, +] + +[package.optional-dependencies] +binary = [ + { name = "psycopg-binary", marker = "implementation_name != 'pypy'" }, ] [[package]]