docs: refresh translations, and translate pages in parallel (#3458)
This commit is contained in:
parent
08a3bc8eaf
commit
fd66270926
4 changed files with 4821 additions and 2277 deletions
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
translation:
|
||||
sections: [0355618e5f4d5fe4, 1821eaf50f2d0b64, 82e0b28ebd3abf5a, 8ac39614c094f2d0, dab6ff945501ab2a, bd5565c3b2d4f959, 96819ce3d63a0487]
|
||||
sections: [0355618e5f4d5fe4, 0fefa31fb7c7b585, 5c53e7487c9c70cc, 8ac39614c094f2d0, dab6ff945501ab2a, bd5565c3b2d4f959, 96819ce3d63a0487]
|
||||
tool: 1
|
||||
---
|
||||
# MCP Apps {#mcp-apps}
|
||||
|
|
@ -18,7 +18,7 @@ SDK इसे built-in `Apps` extension (`io.modelcontextprotocol/ui`) के
|
|||
|
||||
## चेहरे वाली घड़ी {#a-clock-with-a-face}
|
||||
|
||||
```python title="server.py" hl_lines="19 22 30 32"
|
||||
```python title="server.py" hl_lines="17 20 28 30"
|
||||
--8<-- "docs_src/apps/tutorial001.py"
|
||||
```
|
||||
|
||||
|
|
@ -49,15 +49,37 @@ model `content` पढ़ता है; iframe इंसानों के ल
|
|||
model को देता है, और text-only client को **सिर्फ़** वही मिलता है। इसलिए मानक
|
||||
pattern है: एक tool, दो जवाब। `get_time` को फिर से देखें:
|
||||
|
||||
```python title="server.py" hl_lines="23-27"
|
||||
```python title="server.py" hl_lines="21-25"
|
||||
--8<-- "docs_src/apps/tutorial001.py"
|
||||
```
|
||||
|
||||
`client_supports_apps(ctx)` तभी `True` होता है जब client ने
|
||||
`io.modelcontextprotocol/ui` extension declare किया हो **और** अपनी `mimeTypes`
|
||||
settings में `text/html;profile=mcp-app` सूचीबद्ध किया हो। यह field ज़रूरी है,
|
||||
इसलिए जो client इसे छोड़ देता है वह गिना नहीं जाता। इसी file में `main()` ठीक यही
|
||||
declare करता है: negotiation का client वाला आधा हिस्सा, और rich जवाब वापस आता है।
|
||||
इसलिए जो client इसे छोड़ देता है वह गिना नहीं जाता। negotiation का client वाला
|
||||
आधा हिस्सा यह रहा:
|
||||
|
||||
```python title="client.py" hl_lines="8 12"
|
||||
--8<-- "docs_src/apps/tutorial001_client.py"
|
||||
```
|
||||
|
||||
`server.py` को HTTP पर serve करें, फिर दूसरे terminal से client चलाएँ:
|
||||
|
||||
```console
|
||||
uv run mcp run server.py --transport streamable-http
|
||||
```
|
||||
|
||||
```console
|
||||
python client.py
|
||||
```
|
||||
|
||||
```text
|
||||
2026-06-26T12:00:00Z
|
||||
```
|
||||
|
||||
rich जवाब वापस आया। `Client` call से `extensions=[APPS_SUPPORT]` हटा दें, तो यही
|
||||
program इसकी जगह `The time is 2026-06-26T12:00:00Z.` print करता है, और text-only
|
||||
client को हमेशा बस इतना ही दिखता है।
|
||||
|
||||
!!! warning
|
||||
कभी भी `"[Rendered UI]"` जैसा placeholder अकेले content के रूप में न लौटाएँ।
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
translation:
|
||||
sections: [05891e7cc1938a13, b3c01a6af28c51ee, 7ffc91f5e38bdfe0, 717d3f235a8333a7, f471a13b2fe5d737, ed6af2df4b656dff]
|
||||
sections: [05891e7cc1938a13, b3c01a6af28c51ee, 6eba6ce094f4417e, 125f28588c85dd7b, ddd8969b698ca11c, ed6af2df4b656dff]
|
||||
tool: 1
|
||||
---
|
||||
# Extensions {#extensions}
|
||||
|
|
@ -49,7 +49,7 @@ prefix के रूप में ऐसा domain इस्तेमाल क
|
|||
|
||||
सबसे छोटा काम का extension एक tool और एक settings map है:
|
||||
|
||||
```python title="server.py" hl_lines="17 19-20 22-23 26"
|
||||
```python title="server.py" hl_lines="16 18-19 21-22 25"
|
||||
--8<-- "docs_src/extensions/tutorial003.py"
|
||||
```
|
||||
|
||||
|
|
@ -57,17 +57,23 @@ prefix के रूप में ऐसा domain इस्तेमाल क
|
|||
* `settings()` वह value है जो `capabilities.extensions["com.example/stamps"]` पर advertise होती है। बिना settings के extension advertise करने के लिए `{}` (default) लौटाएँ।
|
||||
* extension को server कभी नहीं मिलता। यह अपने योगदान data के रूप में declare करता है; `MCPServer` उन्हें consume करता है। mutate करने के लिए कोई `self.server` नहीं है।
|
||||
|
||||
और `main()` इसका सबूत है, सीधे `mcp` से जुड़ा एक in-memory client:
|
||||
इसे HTTP पर serve करें, और एक client इसका सबूत है:
|
||||
|
||||
```python title="server.py" hl_lines="29-34"
|
||||
--8<-- "docs_src/extensions/tutorial003.py"
|
||||
```console
|
||||
uv run mcp run server.py --transport streamable-http
|
||||
```
|
||||
|
||||
```python title="client.py" hl_lines="7-11"
|
||||
--8<-- "docs_src/extensions/tutorial003_client.py"
|
||||
```
|
||||
|
||||
इस page की हर `server.py` इसी command से serve होती है, और हर `client.py` उसके साथ-साथ दूसरे terminal से `python client.py` से चलती है।
|
||||
|
||||
### अपने methods serve करना {#serving-your-own-methods}
|
||||
|
||||
extension **नए request methods** register कर सकता है: उसके अपने verbs, जो spec के verbs के साथ-साथ serve होते हैं:
|
||||
|
||||
```python title="server.py" hl_lines="16-22 31 40-48"
|
||||
```python title="server.py" hl_lines="14-20 24 33-41"
|
||||
--8<-- "docs_src/extensions/tutorial004.py"
|
||||
```
|
||||
|
||||
|
|
@ -83,14 +89,15 @@ methods **सख़्ती से additive** हैं। SDK इसे constr
|
|||
|
||||
### Client side {#the-client-side}
|
||||
|
||||
उसी file का `main()` ही client की पूरी कहानी है, उसके दोनों हिस्से:
|
||||
client अपना अलग program है, और client की कहानी के दोनों हिस्से इसी में हैं:
|
||||
|
||||
```python title="server.py" hl_lines="54-58"
|
||||
--8<-- "docs_src/extensions/tutorial004.py"
|
||||
```python title="client.py" hl_lines="21-23 27-30"
|
||||
--8<-- "docs_src/extensions/tutorial004_client.py"
|
||||
```
|
||||
|
||||
* `Client(..., extensions=[advertise(EXTENSION_ID)])` extension declare करता है। ये declarations `ClientCapabilities.extensions` बन जाती हैं: 2026-07-28 connection पर यह map हर request के `_meta` envelope में जाता है, इसलिए server इसे **हर** request पर देखता है; legacy connection पर यह `initialize` handshake के साथ जाता है। server code को फ़र्क नहीं पड़ता कि कौन सा: `require_client_extension(ctx, ...)` और `ctx.session.check_client_capability(...)` दोनों रास्तों पर सही स्रोत पढ़ते हैं।
|
||||
* vendor methods एक परत नीचे `client.session.send_request(...)` पर उतरते हैं; `Client` सिर्फ़ spec verbs के लिए first-class methods जोड़ता है। `send_request` कोई भी `Request` subclass स्वीकार करता है, इसलिए vendor request जैसी है वैसी ही चली जाती है।
|
||||
* `SearchRequest` और उसके साथ जाने वाले दो models extension का wire contract हैं, इसलिए client उन्हें अपने लिए खुद declare करता है। published extension इन्हें ऐसे package में देगा जिसे दोनों पक्ष import करें।
|
||||
|
||||
### `tools/call` को intercept करना {#intercepting-toolscall}
|
||||
|
||||
|
|
@ -109,12 +116,18 @@ hook `tools/call` को wrap करता है, और कुछ नहीं
|
|||
|
||||
## client extension इस्तेमाल करना {#using-a-client-extension}
|
||||
|
||||
**client extension** वही contract है, इस्तेमाल करने वाले पक्ष से: एक identifier के पीछे client-side behaviour का bundle। instances को `Client(extensions=[...])` में पास करें और tools सामान्य तरीके से call करें:
|
||||
**client extension** वही contract है, इस्तेमाल करने वाले पक्ष से: एक identifier के पीछे client-side behaviour का bundle। यहाँ server `buy` का जवाब सामान के बजाय redeem करने लायक receipt से देता है, और सिर्फ़ उसी client को जिसने extension declare किया हो:
|
||||
|
||||
```python title="client.py" hl_lines="66-68"
|
||||
```python title="server.py" hl_lines="22-25"
|
||||
--8<-- "docs_src/extensions/tutorial006.py"
|
||||
```
|
||||
|
||||
client पर, instances को `Client(extensions=[...])` में पास करें और tools सामान्य तरीके से call करें:
|
||||
|
||||
```python title="client.py" hl_lines="33-35"
|
||||
--8<-- "docs_src/extensions/tutorial006_client.py"
|
||||
```
|
||||
|
||||
`call_tool("buy", ...)` हर दूसरे call की तरह सादा `CallToolResult` लौटाता है। extension ने जो बदला: server अब `buy` का जवाब final result के बजाय `receipt` **result shape** से दे सकता है, और `call_tool` के लौटने से पहले `Receipts` उसे पूरा कर देता है (यहाँ follow-up call से receipt redeem करके)। call site में कुछ नहीं हिलता।
|
||||
|
||||
extension हटा दें तो इनमें से कुछ भी मौजूद नहीं: server का gate उस client को मना कर देता है जिसने इसे declare नहीं किया (error -32021), और gate छोड़ने वाले server से आया claimed shape validation में fail होता है, ठीक वैसे जैसे spec अनजान `resultType` के लिए माँगता है। default रूप से बंद, wire के दोनों सिरों पर।
|
||||
|
|
@ -124,15 +137,15 @@ extension हटा दें तो इनमें से कुछ भी म
|
|||
```python
|
||||
from mcp.client import advertise
|
||||
|
||||
client = Client(mcp, extensions=[advertise("com.example/search")])
|
||||
client = Client("http://localhost:8000/mcp", extensions=[advertise("com.example/search")])
|
||||
```
|
||||
|
||||
## client extension लिखना {#writing-a-client-extension}
|
||||
|
||||
`ClientExtension` को subclass करें और सिर्फ़ वही override करें जिसकी ज़रूरत हो। योगदान के तीन प्रकार, हर एक का default: `settings()`, `claims()` और `notifications()`।
|
||||
|
||||
```python title="client.py" hl_lines="17-18 43-44 46-47"
|
||||
--8<-- "docs_src/extensions/tutorial006.py"
|
||||
```python title="client.py" hl_lines="16-17 25-26 28-29"
|
||||
--8<-- "docs_src/extensions/tutorial006_client.py"
|
||||
```
|
||||
|
||||
* identifier वही grammar मानता है जो server का, और class define होते ही validate होता है।
|
||||
|
|
@ -153,12 +166,18 @@ handler को validated params एक-एक करके, dispatch के क
|
|||
|
||||
### Extension verbs {#extension-verbs}
|
||||
|
||||
extension के अपने request methods को client-side registration की ज़रूरत नहीं। vendor request type `mcp.types.Request` को subclass करता है और `client.session.send_request` से जाता है, जैसा [अपने methods serve करना](#serving-your-own-methods) में है। एक बात और: जब किसी params key का `Mcp-Name` header में जाना ज़रूरी हो (tasks जैसे extension specs अपने verbs के लिए यह माँगते हैं), तो request type `name_param` declare करता है:
|
||||
extension के अपने request methods को client-side registration की ज़रूरत नहीं। vendor request type `mcp.types.Request` को subclass करता है और `client.session.send_request` से जाता है, जैसा [अपने methods serve करना](#serving-your-own-methods) में है। ऐसा server लें जिसका extension एक named job के बारे में एक verb serve करता है:
|
||||
|
||||
```python title="client.py" hl_lines="22-25 46-47"
|
||||
```python title="server.py" hl_lines="12-13 30"
|
||||
--8<-- "docs_src/extensions/tutorial007.py"
|
||||
```
|
||||
|
||||
client पर एक बात और जुड़ती है: जब किसी params key का `Mcp-Name` header में जाना ज़रूरी हो (tasks जैसे extension specs अपने verbs के लिए यह माँगते हैं), तो request type `name_param` declare करता है:
|
||||
|
||||
```python title="client.py" hl_lines="20-23 28-29"
|
||||
--8<-- "docs_src/extensions/tutorial007_client.py"
|
||||
```
|
||||
|
||||
session हर send path पर `params["jobId"]` को `Mcp-Name` में mirror करता है, और value न होने पर ज़रूरी header चुपचाप छोड़ने के बजाय साफ़ तौर पर fail होता है।
|
||||
|
||||
## extension क्या नहीं कर सकता {#what-an-extension-cannot-do}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
translation:
|
||||
sections: [2c79b6338e09b7ac, 7edc43b3fae11314, 1086e77ce561cd7f, a3f71823df5efc31, 9fc7109f72201cae, d50fe7faead8cf68, 7bf25983df655b66, 6330e1f4c6029683, 2f1749c8c133fa1c, 8db7116fc8ddd0ee, ebc33704fbd74262, cd0e9c933350390e]
|
||||
sections: [2c79b6338e09b7ac, 9d5d10a5f0405d0a, 1086e77ce561cd7f, a3f71823df5efc31, 9fc7109f72201cae, d50fe7faead8cf68, 7bf25983df655b66, 6330e1f4c6029683, 2f1749c8c133fa1c, 8db7116fc8ddd0ee, ebc33704fbd74262, 0fde3bcea081ba3a]
|
||||
tool: 1
|
||||
---
|
||||
# Low-level Server {#the-low-level-server}
|
||||
|
|
@ -25,9 +25,9 @@ translation:
|
|||
|
||||
तीन चीज़ें बदलीं, और पूरा low-level API बस यही है:
|
||||
|
||||
* **Handlers constructor parameters हैं।** `on_list_tools=` और `on_call_tool=` `Server(...)` में जाते हैं। यहाँ नीचे कोई decorator नहीं है, और हर handler का आकार एक ही है: `async (ctx, params) -> result`।
|
||||
* **Input schema आप लिखते हैं।** `Tool.input_schema` एक सादा JSON Schema `dict` है। कोई इसे type hints से नहीं निकालता, क्योंकि निकालने के लिए type hints हैं ही नहीं।
|
||||
* **Result आप बनाते हैं।** `CallToolResult(content=[TextContent(...)])`, हाथ से। न कुछ wrap होता है, न convert, न return annotation से अनुमान लगाया जाता है।
|
||||
* **handlers constructor parameters हैं।** `on_list_tools=` और `on_call_tool=` `Server(...)` में जाते हैं। यहाँ नीचे कोई decorator नहीं है, और हर handler का आकार एक ही है: `async (ctx, params) -> result`।
|
||||
* **input schema आप लिखते हैं।** `Tool.input_schema` एक सादा JSON Schema `dict` है। कोई इसे type hints से नहीं निकालता, क्योंकि निकालने के लिए type hints हैं ही नहीं।
|
||||
* **result आप बनाते हैं।** `CallToolResult(content=[TextContent(...)])`, हाथ से। न कुछ wrap होता है, न convert, न return annotation से अनुमान लगाया जाता है।
|
||||
|
||||
`params` parse की हुई request है: `CallToolRequestParams` आपको `.name` और `.arguments` देता है। `ctx` एक `ServerRequestContext` है: client से वापस बात करने के लिए `ctx.session`, `ctx.lifespan_context`, `ctx.request_id`, और `ctx.meta`, यानी request का आने वाला `_meta`।
|
||||
|
||||
|
|
@ -36,18 +36,22 @@ translation:
|
|||
|
||||
### इसे आज़माएँ {#try-it}
|
||||
|
||||
इसके लिए कोई Inspector नहीं है: `mcp dev` और `mcp run` सिर्फ़ `MCPServer` स्वीकार करते हैं। In-memory `Client` को कोई फ़र्क नहीं पड़ता; वह low-level `Server` को ठीक वैसे ही लेता है जैसे `MCPServer` को:
|
||||
`mcp dev` और `mcp run` सिर्फ़ `MCPServer` स्वीकार करते हैं, इसलिए इसे serve आप खुद करते हैं। `server.py` की आख़िरी line इससे एक साधारण ASGI app बनाती है, और uvicorn उसे चलाता है:
|
||||
|
||||
```python title="main.py"
|
||||
```console
|
||||
uvicorn server:app --port 8000
|
||||
```
|
||||
|
||||
Inspector को, या किसी भी client को, `http://localhost:8000/mcp` पर point करें:
|
||||
|
||||
```python title="client.py"
|
||||
import asyncio
|
||||
|
||||
from mcp import Client
|
||||
|
||||
from server import server
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
async with Client(server) as client:
|
||||
async with Client("http://localhost:8000/mcp") as client:
|
||||
result = await client.call_tool("search_books", {"query": "dune", "limit": 5})
|
||||
print(result.content)
|
||||
|
||||
|
|
@ -61,8 +65,10 @@ asyncio.run(main())
|
|||
|
||||
वही text जो `@mcp.tool()` वाले version ने दिया था। दो असली अंतर:
|
||||
|
||||
* `result.structured_content` `None` है। High-level server आपके लिए `-> str` को `{"result": ...}` में wrap कर देता है; यहाँ जो आपने नहीं बनाया, उसे कोई नहीं बनाता।
|
||||
* `list_tools` वही schema लौटाता है जो **आपने** type किया, अक्षर-दर-अक्षर। High-level version में हर property पर `"title": "Query"` था और root पर `"title": "search_booksArguments"`: Pydantic की देन। यहाँ नीचे, अगर कुछ wire पर है, तो उसे वहाँ आपने रखा है।
|
||||
* `result.structured_content` `None` है। high-level server आपके लिए `-> str` को `{"result": ...}` में wrap कर देता है; यहाँ जो आपने नहीं बनाया, उसे कोई नहीं बनाता।
|
||||
* `list_tools` वही schema लौटाता है जो **आपने** type किया, अक्षर-दर-अक्षर। high-level version में हर property पर `"title": "Query"` था और root पर `"title": "search_booksArguments"`: Pydantic की देन। यहाँ नीचे, अगर कुछ wire पर है, तो उसे वहाँ आपने रखा है।
|
||||
|
||||
test में आप uvicorn और port दोनों छोड़ देते हैं: `Client(server)` low-level `Server` को in-process ठीक वैसे ही लेता है जैसे `MCPServer` को, और **[Testing](../get-started/testing.md)** यही pattern है।
|
||||
|
||||
## आपके लिए कुछ जाँचा नहीं जाता {#nothing-is-checked-for-you}
|
||||
|
||||
|
|
@ -207,12 +213,12 @@ Handshake runner का है। `server/discover`, `ping`, और बाकी
|
|||
|
||||
## सारांश {#recap}
|
||||
|
||||
* Low-level `Server` अपने handlers `on_*` **constructor parameters** के रूप में लेता है; हर handler `async (ctx, params) -> result` है।
|
||||
* low-level `Server` अपने handlers `on_*` **constructor parameters** के रूप में लेता है; हर handler `async (ctx, params) -> result` है।
|
||||
* `input_schema` dict आप लिखते हैं और `CallToolResult` आप बनाते हैं। आपके लिए न कुछ derive होता है, न wrap, न validate।
|
||||
* Handler में exception `-32603` protocol error है। जिस tool error को model पढ़ सके, वह `is_error=True` वाला `CallToolResult` है जिसे **आप** लौटाते हैं।
|
||||
* Result पर `_meta` client application के नाम है, model के नहीं।
|
||||
* handler में exception `-32603` protocol error है। जिस tool error को model पढ़ सके, वह `is_error=True` वाला `CallToolResult` है जिसे **आप** लौटाते हैं।
|
||||
* result पर `_meta` client application के नाम है, model के नहीं।
|
||||
* `Server[T]` उस चीज़ में generic है जो उसका lifespan yield करता है; `ctx.lifespan_context` एक typed `T` है।
|
||||
* `add_request_handler(method, params_type, handler)` कोई भी method serve करता है। `initialize` reserved है।
|
||||
* `Server` जो capabilities advertise करता है, वे इससे निकलती हैं कि आपने कौन से handlers register किए।
|
||||
|
||||
`Client(server)` ने दोनों servers के साथ एक जैसा बर्ताव किया क्योंकि वे एक ही protocol **हैं**, और यही असली बात है। इससे नीचे की अगली layer कोई class है ही नहीं: वह **[Middleware](middleware.md)** है।
|
||||
client ने दोनों servers के साथ एक जैसा बर्ताव किया क्योंकि वे एक ही protocol **हैं**, और यही असली बात है। इससे नीचे की अगली layer कोई class है ही नहीं: वह **[Middleware](middleware.md)** है।
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
translation:
|
||||
sections: [a9aba7a026c7bd85, ed32bda7ba9ae33a, 7e64cc5646abb91f, 22a0129ee78b3c63, d875373c06d8d2f9]
|
||||
sections: [a9aba7a026c7bd85, 83e2a08b9d46a398, 9fd8a0aa384b3257, 22a0129ee78b3c63, d875373c06d8d2f9]
|
||||
tool: 1
|
||||
---
|
||||
# Pagination {#pagination}
|
||||
|
|
@ -31,9 +31,13 @@ Pagination उस server के लिए है जिसकी resource list
|
|||
|
||||
### इसे आज़माएँ {#try-it}
|
||||
|
||||
`Client(server)` memory में low-level `Server` से ठीक वैसे ही जुड़ता है जैसे `MCPServer` से।
|
||||
`mcp run` सिर्फ़ `MCPServer` स्वीकार करता है, इसलिए इसे आप ख़ुद serve करते हैं। `server.py` की आख़िरी line `Server` से एक साधारण ASGI app बनाती है, और uvicorn उसी को चलाता है:
|
||||
|
||||
बिना arguments के `list_resources()` call करें। आपको दस resources मिलते हैं, `book-1` से `book-10` तक, और `next_cursor` string `"10"` है।
|
||||
```console
|
||||
uvicorn server:app --port 8000
|
||||
```
|
||||
|
||||
किसी भी client (**[The Client](../client/index.md)**, या Inspector) को `http://localhost:8000/mcp` की ओर point करें और बिना arguments के `list_resources()` call करें। आपको दस resources मिलते हैं, `book-1` से `book-10` तक, और `next_cursor` string `"10"` है।
|
||||
|
||||
इसे `list_resources(cursor="10")` से वापस दें, तो पहला resource `book-11` है और नया `next_cursor` `"20"` है।
|
||||
|
||||
|
|
@ -43,7 +47,7 @@ Pagination उस server के लिए है जिसकी resource list
|
|||
|
||||
`Client` का हर `list_*` method (`list_tools`, `list_resources`, `list_resource_templates`, `list_prompts`) `cursor=` keyword लेता है। Paged list को पूरा खींचना एक `while True` है:
|
||||
|
||||
```python title="client.py" hl_lines="26-32"
|
||||
```python title="client.py" hl_lines="9-15"
|
||||
--8<-- "docs_src/pagination/tutorial002.py"
|
||||
```
|
||||
|
||||
|
|
@ -51,7 +55,7 @@ Pagination उस server के लिए है जिसकी resource list
|
|||
* `next_cursor` देखने से **पहले** extend करें: आख़िरी page में भी resources होते हैं।
|
||||
* `next_cursor is None` ही बाहर निकलने का रास्ता है। बाकी कुछ भी सीधे `cursor=` में वापस जाता है, बिना छेड़े।
|
||||
|
||||
इसका `main()` चलाएँ और यह `100 resources` print करता है: दस-दस के दस pages, एक ऐसे loop से जुड़े हुए जिसे कभी पता ही नहीं था कि दस pages थे।
|
||||
uvicorn अब भी `server.py` serve कर रहा हो, तब दूसरे terminal में `python client.py` चलाएँ। यह `100 resources` print करता है: दस-दस के दस pages, एक ऐसे loop से जुड़े हुए जिसे कभी पता ही नहीं था कि दस pages थे।
|
||||
|
||||
यह वही loop है जो **[The Client](../client/index.md)** हर `list_*` verb के लिए दिखाता है, और paging न करने वाले server पर इसकी कोई क़ीमत नहीं: पहले ही response में `next_cursor` `None` होता है और loop एक बार चलता है।
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue