Files
Max Isbey 1b74b06753 Tighten comments and docstrings repo-wide
Cut comment and docstring volume roughly in half across src, tests,
examples, and docs_src: removed comments that restate the adjacent code,
leftover development narration, section banners, and self-evident
Args/Returns blocks, and compressed the remaining docstrings to a
Google-style summary line plus only the detail that earns its place.

Kept (and tightened) the load-bearing content: Raises sections,
deprecation and version-availability notes, spec/RFC/issue references,
why-comments for non-obvious decisions, and all coverage pragmas. The
generated mcp_types.v* wire modules are untouched.
2026-06-29 15:10:27 +00:00

75 lines
2.8 KiB
Python

"""`docs/advanced/pagination.md`: every claim the page makes, proved against the real SDK."""
import pytest
from mcp_types import Resource
from docs_src.pagination import tutorial001, tutorial002
from mcp import Client, MCPError
from mcp.server import MCPServer
from mcp.server.mcpserver.resources import TextResource
# See test_index.py for why this is a per-module mark and not a conftest hook.
pytestmark = [pytest.mark.anyio, pytest.mark.filterwarnings("error::mcp.MCPDeprecationWarning")]
mcp = MCPServer("Bookshop")
for n in range(1, 101):
mcp.add_resource(TextResource(uri=f"books://catalog/book-{n}", name=f"book-{n}", text=f"book-{n}"))
async def test_mcpserver_never_pages() -> None:
async with Client(mcp) as client:
result = await client.list_resources()
assert len(result.resources) == 100
assert result.next_cursor is None
async def test_first_page_has_ten_resources_and_a_cursor() -> None:
async with Client(tutorial001.server) as client:
page = await client.list_resources()
assert [resource.name for resource in page.resources] == [f"book-{n}" for n in range(1, 11)]
assert page.next_cursor == "10"
async def test_the_cursor_resumes_where_the_last_page_stopped() -> None:
async with Client(tutorial001.server) as client:
page = await client.list_resources(cursor="10")
assert page.resources[0].name == "book-11"
assert page.next_cursor == "20"
async def test_the_last_page_carries_no_cursor() -> None:
async with Client(tutorial001.server) as client:
page = await client.list_resources(cursor="90")
assert len(page.resources) == 10
assert page.next_cursor is None
async def test_the_loop_collects_all_one_hundred() -> None:
async with Client(tutorial001.server) as client:
resources: list[Resource] = []
cursor: str | None = None
pages = 0
while True:
page = await client.list_resources(cursor=cursor)
resources.extend(page.resources)
pages += 1
if page.next_cursor is None:
break
cursor = page.next_cursor
assert pages == 10
assert len({resource.uri for resource in resources}) == 100
async def test_the_client_program_on_the_page_runs(capsys: pytest.CaptureFixture[str]) -> None:
await tutorial002.main()
assert capsys.readouterr().out == "100 resources\n"
async def test_an_invented_cursor_is_an_error() -> None:
"""Cursors are opaque: a string the server never minted blows up inside the handler."""
async with Client(tutorial001.server) as client:
with pytest.raises(MCPError) as excinfo:
await client.list_resources(cursor="page-2")
assert excinfo.value.code == -32603
assert str(excinfo.value) == "Internal server error"