diff --git a/libs/langgraph/poetry.lock b/libs/langgraph/poetry.lock index 85e8807d1..afab707a2 100644 --- a/libs/langgraph/poetry.lock +++ b/libs/langgraph/poetry.lock @@ -1287,7 +1287,7 @@ typing-extensions = ">=4.7" [[package]] name = "langgraph-checkpoint" -version = "2.0.18" +version = "2.0.21" description = "Library with base interfaces for LangGraph checkpoint savers." optional = false python-versions = "^3.9.0,<4.0" @@ -1304,7 +1304,7 @@ url = "../checkpoint" [[package]] name = "langgraph-checkpoint-postgres" -version = "2.0.16" +version = "2.0.18" description = "Library with a Postgres implementation of LangGraph checkpoint saver." optional = false python-versions = "^3.9.0,<4.0" @@ -1340,7 +1340,7 @@ url = "../checkpoint-sqlite" [[package]] name = "langgraph-prebuilt" -version = "0.1.2" +version = "0.1.3" description = "Library with high-level APIs for creating and executing LangGraph agents and tools." optional = false python-versions = "^3.9.0,<4.0" @@ -1357,7 +1357,7 @@ url = "../prebuilt" [[package]] name = "langgraph-sdk" -version = "0.1.55" +version = "0.1.58" description = "SDK for interacting with LangGraph API" optional = false python-versions = "^3.9.0,<4.0" @@ -1717,24 +1717,6 @@ files = [ {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, ] -[[package]] -name = "networkx" -version = "3.2.1" -description = "Python package for creating and manipulating graphs and networks" -optional = false -python-versions = ">=3.9" -files = [ - {file = "networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2"}, - {file = "networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6"}, -] - -[package.extras] -default = ["matplotlib (>=3.5)", "numpy (>=1.22)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"] -developer = ["changelist (==0.4)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] -doc = ["nb2plots (>=0.7)", "nbconvert (<7.9)", "numpydoc (>=1.6)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"] -extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.11)", "sympy (>=1.10)"] -test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] - [[package]] name = "notebook" version = "7.2.2" @@ -2753,20 +2735,6 @@ files = [ attrs = ">=22.2.0" rpds-py = ">=0.7.0" -[[package]] -name = "referrers" -version = "0.12.0" -description = "Finds the graph of referrers for a Python object" -optional = false -python-versions = ">=3.8" -files = [ - {file = "referrers-0.12.0-py3-none-any.whl", hash = "sha256:a59a302b0d314f426cd309c0c4d0f1b66fd266a1c46784b590a0c067385a0276"}, - {file = "referrers-0.12.0.tar.gz", hash = "sha256:47d37a7a53c086070c0751e825143feb008bac603c4cddf897d655db28804003"}, -] - -[package.dependencies] -networkx = ">=2.4" - [[package]] name = "requests" version = "2.32.3" @@ -3425,4 +3393,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.0" python-versions = ">=3.9.0,<4.0" -content-hash = "ded968afc6be33e48198c04606493c161d27a44e1f11eeecf9be573ddb6b73b1" +content-hash = "b8641a0b2d92bee0363602e69f99b23366b2035b7e17ff017708194e6fbd0ac5" diff --git a/libs/langgraph/pyproject.toml b/libs/langgraph/pyproject.toml index 5a0feccdf..6b6f821db 100644 --- a/libs/langgraph/pyproject.toml +++ b/libs/langgraph/pyproject.toml @@ -38,7 +38,6 @@ pyperf = "^2.7.0" py-spy = "^0.3.14" types-requests = "^2.32.0.20240914" pycryptodome = "^3.21.0" -referrers = "^0.12.0" [tool.ruff] lint.select = [ "E", "F", "I", "TID251" ] diff --git a/libs/langgraph/tests/conftest.py b/libs/langgraph/tests/conftest.py index 82b0fe33e..68b0f6b60 100644 --- a/libs/langgraph/tests/conftest.py +++ b/libs/langgraph/tests/conftest.py @@ -5,7 +5,6 @@ from typing import AsyncIterator, Optional from uuid import UUID, uuid4 import pytest -import referrers from langchain_core import __version__ as core_version from packaging import version from psycopg import AsyncConnection, Connection @@ -452,10 +451,10 @@ async def awith_store(store_name: Optional[str]) -> AsyncIterator[BaseStore]: @pytest.fixture(autouse=True) def check_live_objects() -> None: """Check for live objects after each test.""" - gc.collect() - gc.disable() try: - yield + gc.disable() + # Should we be yielding? + gc.collect() leaked_objs = [ o for o in gc.get_objects() @@ -470,7 +469,7 @@ def check_live_objects() -> None: ), ) ] - assert not leaked_objs, f"""Leaked objects at end of test: {referrers.get_referrer_graph_for_list(leaked_objs, exclude_object_ids=(id(leaked_objs),))}""" + assert not leaked_objs, f"{len(leaked_objs)} leaked objects at end of test." finally: gc.enable() diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index 40fc5f1b9..678a87342 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -7623,37 +7623,28 @@ def test_parallel_interrupts_double( def test_pregel_loop_refcount(): - gc.collect() - try: - gc.disable() + class State(TypedDict): + messages: Annotated[list, add_messages] - class State(TypedDict): - messages: Annotated[list, add_messages] + graph_builder = StateGraph(State) - graph_builder = StateGraph(State) + def chatbot(state: State): + return {"messages": [("ai", "HIYA")]} - def chatbot(state: State): - return {"messages": [("ai", "HIYA")]} + graph_builder.add_node("chatbot", chatbot) + graph_builder.set_entry_point("chatbot") + graph_builder.set_finish_point("chatbot") + graph = graph_builder.compile() - graph_builder.add_node("chatbot", chatbot) - graph_builder.set_entry_point("chatbot") - graph_builder.set_finish_point("chatbot") - graph = graph_builder.compile() - - for _ in range(5): - graph.invoke({"messages": [{"role": "user", "content": "hi"}]}) - assert ( - len( - [obj for obj in gc.get_objects() if isinstance(obj, SyncPregelLoop)] - ) - == 0 - ) - assert ( - len([obj for obj in gc.get_objects() if isinstance(obj, PregelRunner)]) - == 0 - ) - finally: - gc.enable() + for _ in range(5): + graph.invoke({"messages": [{"role": "user", "content": "hi"}]}) + assert ( + len([obj for obj in gc.get_objects() if isinstance(obj, SyncPregelLoop)]) + == 0 + ) + assert ( + len([obj for obj in gc.get_objects() if isinstance(obj, PregelRunner)]) == 0 + ) @pytest.mark.parametrize("checkpointer_name", REGULAR_CHECKPOINTERS_SYNC) diff --git a/libs/langgraph/tests/test_pregel_async.py b/libs/langgraph/tests/test_pregel_async.py index 58bb15cdc..e42bcad08 100644 --- a/libs/langgraph/tests/test_pregel_async.py +++ b/libs/langgraph/tests/test_pregel_async.py @@ -7848,41 +7848,28 @@ async def test_handles_multiple_interrupts_from_tasks() -> None: async def test_pregel_loop_refcount(): - gc.collect() - try: - gc.disable() + class State(TypedDict): + messages: Annotated[list, add_messages] - class State(TypedDict): - messages: Annotated[list, add_messages] + graph_builder = StateGraph(State) - graph_builder = StateGraph(State) + async def chatbot(state: State): + return {"messages": [("ai", "HIYA")]} - async def chatbot(state: State): - return {"messages": [("ai", "HIYA")]} + graph_builder.add_node("chatbot", chatbot) + graph_builder.set_entry_point("chatbot") + graph_builder.set_finish_point("chatbot") + graph = graph_builder.compile() - graph_builder.add_node("chatbot", chatbot) - graph_builder.set_entry_point("chatbot") - graph_builder.set_finish_point("chatbot") - graph = graph_builder.compile() - - for _ in range(5): - await graph.ainvoke({"messages": [{"role": "user", "content": "hi"}]}) - assert ( - len( - [ - obj - for obj in gc.get_objects() - if isinstance(obj, AsyncPregelLoop) - ] - ) - == 0 - ) - assert ( - len([obj for obj in gc.get_objects() if isinstance(obj, PregelRunner)]) - == 0 - ) - finally: - gc.enable() + for _ in range(5): + await graph.ainvoke({"messages": [{"role": "user", "content": "hi"}]}) + assert ( + len([obj for obj in gc.get_objects() if isinstance(obj, AsyncPregelLoop)]) + == 0 + ) + assert ( + len([obj for obj in gc.get_objects() if isinstance(obj, PregelRunner)]) == 0 + ) @pytest.mark.parametrize("checkpointer_name", REGULAR_CHECKPOINTERS_ASYNC)