33from collections .abc import AsyncIterator , Mapping
44from contextlib import AsyncExitStack , asynccontextmanager
55from typing import Any , cast
6+ from unittest .mock import AsyncMock
67
78import anyio
89import anyio .abc
@@ -1227,9 +1228,7 @@ async def test_dispatcher_keyword_preserves_caller_stream_exception_hook_on_exit
12271228 s2c_send , s2c_recv = anyio .create_memory_object_stream [SessionMessage | Exception ](1 )
12281229 c2s_send , c2s_recv = anyio .create_memory_object_stream [SessionMessage ](1 )
12291230 try :
1230- async def caller_hook (_exc : Exception ) -> None :
1231- pass
1232-
1231+ caller_hook = AsyncMock ()
12331232 dispatcher = JSONRPCDispatcher (s2c_recv , c2s_send , on_stream_exception = caller_hook )
12341233 async with ClientSession (dispatcher = dispatcher ):
12351234 pass
@@ -1242,6 +1241,28 @@ async def caller_hook(_exc: Exception) -> None:
12421241 c2s_recv .close ()
12431242
12441243
1244+ @pytest .mark .anyio
1245+ async def test_dispatcher_keyword_preserves_replacement_stream_exception_hook_on_exit ():
1246+ """A caller replacement made while a session is alive survives shutdown (SDK-defined ownership)."""
1247+ s2c_send , s2c_recv = anyio .create_memory_object_stream [SessionMessage | Exception ](1 )
1248+ c2s_send , c2s_recv = anyio .create_memory_object_stream [SessionMessage ](1 )
1249+ try :
1250+ dispatcher = JSONRPCDispatcher (s2c_recv , c2s_send )
1251+ session = ClientSession (dispatcher = dispatcher )
1252+ assert dispatcher .on_stream_exception is not None
1253+
1254+ caller_hook = AsyncMock ()
1255+ async with session :
1256+ dispatcher .on_stream_exception = caller_hook
1257+
1258+ assert dispatcher .on_stream_exception is caller_hook
1259+ finally :
1260+ s2c_send .close ()
1261+ s2c_recv .close ()
1262+ c2s_send .close ()
1263+ c2s_recv .close ()
1264+
1265+
12451266@pytest .mark .anyio
12461267async def test_direct_dispatch_roots_list_reaches_callback_with_synthesized_request_id ():
12471268 """A server-initiated roots/list over dispatcher= reaches the registered callback and round-trips
0 commit comments