Apply patch [skip ci]

This commit is contained in:
open-swe[bot]
2025-09-10 00:00:30 +00:00
parent 753bf15c29
commit 93296d5455
2 changed files with 34 additions and 42 deletions

View File

@@ -156,14 +156,14 @@ def _set_config_context(
class ConfigContext:
"""Context manager for setting child Runnable config + tracing context.
This class implements proper context manager protocol with state tracking
to prevent reuse and provide clear error messages.
"""
def __init__(self, config: RunnableConfig) -> None:
"""Initialize the context manager with a config.
Args:
config: The config to set.
"""
@@ -171,24 +171,24 @@ class ConfigContext:
self._entered = False
self._ctx: Optional[Context] = None
self._config_token: Optional[Token[Optional[RunnableConfig]]] = None
def __enter__(self) -> Context:
"""Enter the context manager.
Returns:
The config context.
Raises:
RuntimeError: If the context manager has already been entered.
"""
if self._entered:
raise RuntimeError("Cannot re-enter an already-entered context manager")
self._entered = True
self._ctx = copy_context()
self._config_token, _ = self._ctx.run(_set_config_context, self.config)
return self._ctx
def __exit__(
self,
exc_type: Optional[type[BaseException]],
@@ -196,18 +196,18 @@ class ConfigContext:
exc_tb: Optional[object],
) -> None:
"""Exit the context manager and reset the config.
Args:
exc_type: The exception type if an exception occurred.
exc_val: The exception value if an exception occurred.
exc_tb: The exception traceback if an exception occurred.
Raises:
RuntimeError: If the context manager was not entered.
"""
if not self._entered:
raise RuntimeError("Cannot exit context manager that was not entered")
if self._ctx is not None and self._config_token is not None:
self._ctx.run(var_child_runnable_config.reset, self._config_token)
self._ctx.run(
@@ -221,7 +221,7 @@ class ConfigContext:
"client": None,
},
)
# Mark as exited to prevent reuse
self._entered = False
@@ -669,6 +669,3 @@ async def run_in_executor(
)
return await asyncio.get_running_loop().run_in_executor(executor_or_config, wrapper)

View File

@@ -166,53 +166,54 @@ async def test_run_in_executor() -> None:
def test_set_config_context_reuse_raises_error() -> None:
"""Test that reusing the same context manager raises RuntimeError."""
from langchain_core.runnables.config import set_config_context
config = RunnableConfig(tags=["test"])
ctx_manager = set_config_context(config)
# First enter should work
with ctx_manager as ctx1:
assert ctx1 is not None
# Second enter should raise RuntimeError
with pytest.raises(RuntimeError) as exc_info:
with ctx_manager as ctx2:
pass # Should not reach here
assert "Cannot re-enter an already-entered context manager" in str(exc_info.value)
assert "Cannot re-enter an already-entered context manager" in str(
exc_info.value
)
def test_set_config_context_exit_without_enter() -> None:
"""Test that exiting without entering raises RuntimeError."""
from langchain_core.runnables.config import set_config_context
config = RunnableConfig(tags=["test"])
ctx_manager = set_config_context(config)
# Attempting to exit without entering should raise RuntimeError
with pytest.raises(RuntimeError) as exc_info:
ctx_manager.__exit__(None, None, None)
assert "Cannot exit context manager that was not entered" in str(exc_info.value)
def test_set_config_context_normal_usage() -> None:
"""Test that normal usage still works correctly."""
from langchain_core.runnables.config import set_config_context
config = RunnableConfig(
tags=["test"],
metadata={"key": "value"},
configurable={"param": "value"}
tags=["test"], metadata={"key": "value"}, configurable={"param": "value"}
)
# Normal usage should work without issues
with set_config_context(config) as ctx:
assert ctx is not None
# Context should be a contextvars.Context object
from contextvars import Context
assert isinstance(ctx, Context)
# After exiting, we should be able to create a new context manager
# with the same config
with set_config_context(config) as ctx2:
@@ -223,29 +224,23 @@ def test_set_config_context_normal_usage() -> None:
def test_set_config_context_nested_different_instances() -> None:
"""Test that using different instances in nested contexts works properly."""
from langchain_core.runnables.config import set_config_context
config1 = RunnableConfig(
tags=["outer"],
metadata={"level": "outer"}
)
config2 = RunnableConfig(
tags=["inner"],
metadata={"level": "inner"}
)
config1 = RunnableConfig(tags=["outer"], metadata={"level": "outer"})
config2 = RunnableConfig(tags=["inner"], metadata={"level": "inner"})
# Nested contexts with different instances should work
with set_config_context(config1) as ctx1:
assert ctx1 is not None
with set_config_context(config2) as ctx2:
assert ctx2 is not None
# Both contexts should be valid
from contextvars import Context
assert isinstance(ctx1, Context)
assert isinstance(ctx2, Context)
# They should be different contexts
assert ctx1 is not ctx2
# After inner context exits, outer should still be valid
assert ctx1 is not None