|
20 | 20 | # "auto" dispatches in process; "legacy" puts a JSON-RPC stream, and so a cancellation message, in between. |
21 | 21 | both_connections = pytest.mark.parametrize("mode", ["auto", "legacy"]) |
22 | 22 |
|
| 23 | +TITLES = ["Dune", "Emma", "Ulysses"] |
| 24 | + |
23 | 25 |
|
24 | 26 | async def abandon( |
25 | 27 | call: Callable[[], Awaitable[object]], started: anyio.Event, then: Callable[[], object] = lambda: None |
@@ -115,23 +117,35 @@ async def test_a_client_timeout_cancels_the_tool_the_same_way( |
115 | 117 |
|
116 | 118 | @both_connections |
117 | 119 | async def test_check_cancelled_stops_a_def_tool_at_its_next_check(mode: str, monkeypatch: pytest.MonkeyPatch) -> None: |
118 | | - """tutorial002: cancelled during the first book, the loop raises at its next check and indexes no more.""" |
| 120 | + """tutorial002: cancelled during the first book, the loop raises at its next check and the `finally` cleans up.""" |
119 | 121 | started = anyio.Event() |
120 | 122 | resume = threading.Event() |
121 | 123 | indexed: list[str] = [] |
122 | 124 |
|
123 | 125 | def index_book(title: str) -> None: |
| 126 | + assert tutorial002.offline == {"search"} |
124 | 127 | indexed.append(title) |
125 | 128 | anyio.from_thread.run_sync(started.set) |
126 | 129 | assert resume.wait(5) |
127 | 130 |
|
128 | 131 | monkeypatch.setattr(tutorial002, "index_book", index_book) |
129 | | - titles = ["Dune", "Emma", "Ulysses"] |
130 | 132 | with anyio.fail_after(5): |
131 | | - # Leaving the block waits for the tool's thread, so `indexed` is final after it. |
| 133 | + # Leaving the block waits for the tool's thread, so what it left behind is final after it. |
132 | 134 | async with Client(tutorial002.mcp, mode=mode) as client: |
133 | | - await abandon(lambda: client.call_tool("rebuild_index", {"titles": titles}), started, then=resume.set) |
| 135 | + await abandon(lambda: client.call_tool("rebuild_index", {"titles": TITLES}), started, then=resume.set) |
134 | 136 | assert indexed == ["Dune"] |
| 137 | + assert tutorial002.offline == set() |
| 138 | + |
| 139 | + |
| 140 | +async def test_a_def_tool_nobody_cancels_indexes_every_book_and_cleans_up(monkeypatch: pytest.MonkeyPatch) -> None: |
| 141 | + """tutorial002: while the call is live the checks do nothing, and the `finally` runs on a normal finish too.""" |
| 142 | + indexed: list[str] = [] |
| 143 | + monkeypatch.setattr(tutorial002, "index_book", indexed.append) |
| 144 | + async with Client(tutorial002.mcp) as client: |
| 145 | + result = await client.call_tool("rebuild_index", {"titles": TITLES}) |
| 146 | + assert result.structured_content == {"result": "Indexed 3 books."} |
| 147 | + assert indexed == TITLES |
| 148 | + assert tutorial002.offline == set() |
135 | 149 |
|
136 | 150 |
|
137 | 151 | async def test_a_def_tool_that_never_checks_runs_to_the_end() -> None: |
|
0 commit comments