From 3a168a8a5b3bb13d193cf8c90364a53f607dd701 Mon Sep 17 00:00:00 2001 From: dongjiang Date: Mon, 13 Jul 2026 15:23:13 +0800 Subject: [PATCH 1/4] docs: add examples for closing HTTP client on user side The connect client's close() method only marks the client as closed. Users who provide their own HTTP client are responsible for closing it themselves. Add documentation and examples to clarify this. Addresses review feedback on PR #298. Signed-off-by: dongjiang --- src/connectrpc/_client_async.py | 27 ++++++++++++++++++++++++++- src/connectrpc/_client_sync.py | 23 ++++++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/connectrpc/_client_async.py b/src/connectrpc/_client_async.py index 9de08d9b..8e0bed0b 100644 --- a/src/connectrpc/_client_async.py +++ b/src/connectrpc/_client_async.py @@ -175,7 +175,32 @@ def __init__( self._execute_bidi_stream = execute_bidi_stream async def close(self) -> None: - """Close the HTTP client. After closing, the client cannot be used to make requests.""" + """Mark the client as closed. + + After closing, the client cannot be used to make requests. + + Note: + This method does not close the underlying HTTP client. If you provided + your own HTTP client, you are responsible for closing it yourself. + + Example:: + + import asyncio + from pyqwest import Client + from my_service import MyServiceClient + + async def main(): + http_client = Client() + client = MyServiceClient("http://localhost", http_client=http_client) + try: + # Use the client... + pass + finally: + await client.close() # Marks connect client as closed + await http_client.aclose() # You must close the HTTP client yourself + + asyncio.run(main()) + """ if not self._closed: self._closed = True diff --git a/src/connectrpc/_client_sync.py b/src/connectrpc/_client_sync.py index abdfe88a..27a474a1 100644 --- a/src/connectrpc/_client_sync.py +++ b/src/connectrpc/_client_sync.py @@ -174,7 +174,28 @@ def __init__( self._execute_bidi_stream = execute_bidi_stream def close(self) -> None: - """Close the HTTP client. After closing, the client cannot be used to make requests.""" + """Mark the client as closed. + + After closing, the client cannot be used to make requests. + + Note: + This method does not close the underlying HTTP client. If you provided + your own HTTP client, you are responsible for closing it yourself. + + Example:: + + from pyqwest import SyncClient + from my_service import MyServiceClient + + http_client = SyncClient() + client = MyServiceClient("http://localhost", http_client=http_client) + try: + # Use the client... + pass + finally: + client.close() # Marks connect client as closed + http_client.close() # You must close the HTTP client yourself + """ if not self._closed: self._closed = True From b63b79f69d19e63ce9dcc0e8c17d093df858fbbc Mon Sep 17 00:00:00 2001 From: dongjiang Date: Mon, 13 Jul 2026 17:03:32 +0800 Subject: [PATCH 2/4] style: fix ruff format in _client_async.py Signed-off-by: dongjiang --- src/connectrpc/_client_async.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/connectrpc/_client_async.py b/src/connectrpc/_client_async.py index 8e0bed0b..28b60ce8 100644 --- a/src/connectrpc/_client_async.py +++ b/src/connectrpc/_client_async.py @@ -189,6 +189,7 @@ async def close(self) -> None: from pyqwest import Client from my_service import MyServiceClient + async def main(): http_client = Client() client = MyServiceClient("http://localhost", http_client=http_client) @@ -197,7 +198,10 @@ async def main(): pass finally: await client.close() # Marks connect client as closed - await http_client.aclose() # You must close the HTTP client yourself + await ( + http_client.aclose() + ) # You must close the HTTP client yourself + asyncio.run(main()) """ From c58bdc4fb6f8985ad06efef0bb53b50e72ef702e Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Tue, 14 Jul 2026 10:15:11 +0900 Subject: [PATCH 3/4] Move docs to init Signed-off-by: Anuraag Agrawal --- src/connectrpc/_client_async.py | 46 ++++++++++++--------------------- src/connectrpc/_client_sync.py | 38 ++++++++++++--------------- 2 files changed, 32 insertions(+), 52 deletions(-) diff --git a/src/connectrpc/_client_async.py b/src/connectrpc/_client_async.py index 28b60ce8..c44068c8 100644 --- a/src/connectrpc/_client_async.py +++ b/src/connectrpc/_client_async.py @@ -101,6 +101,21 @@ def __init__( ) -> None: """Creates a new asynchronous Connect client. + When providing an HTTP client, for example to configure TLS settings, + it is the caller's responsibility to close it. + + Examples: + ```python + from pyqwest import Client + from my_service import MyServiceClient + + async with ( + Client() as http_client, + MyServiceClient("http://localhost:8000", http_client=http_client) as client, + ): + # Use the client! + ``` + Args: address: The address of the server to connect to, including scheme. codec: The [Codec][] to use for requests. If unset, defaults to binary protobuf. @@ -175,36 +190,7 @@ def __init__( self._execute_bidi_stream = execute_bidi_stream async def close(self) -> None: - """Mark the client as closed. - - After closing, the client cannot be used to make requests. - - Note: - This method does not close the underlying HTTP client. If you provided - your own HTTP client, you are responsible for closing it yourself. - - Example:: - - import asyncio - from pyqwest import Client - from my_service import MyServiceClient - - - async def main(): - http_client = Client() - client = MyServiceClient("http://localhost", http_client=http_client) - try: - # Use the client... - pass - finally: - await client.close() # Marks connect client as closed - await ( - http_client.aclose() - ) # You must close the HTTP client yourself - - - asyncio.run(main()) - """ + """Close the client. After closing, the client cannot be used to make requests.""" if not self._closed: self._closed = True diff --git a/src/connectrpc/_client_sync.py b/src/connectrpc/_client_sync.py index 27a474a1..07e509ee 100644 --- a/src/connectrpc/_client_sync.py +++ b/src/connectrpc/_client_sync.py @@ -94,6 +94,21 @@ def __init__( ) -> None: """Creates a new synchronous Connect client. + When providing an HTTP client, for example to configure TLS settings, + it is the caller's responsibility to close it. + + Examples: + ```python + from pyqwest import SyncClient + from my_service import MyServiceClientSync + + with ( + SyncClient() as http_client, + MyServiceClientSync("http://localhost:8000", http_client=http_client) as client, + ): + # Use the client! + ``` + Args: address: The address of the server to connect to, including scheme. codec: The [Codec][] to use for requests. If unset, defaults to binary protobuf. @@ -174,28 +189,7 @@ def __init__( self._execute_bidi_stream = execute_bidi_stream def close(self) -> None: - """Mark the client as closed. - - After closing, the client cannot be used to make requests. - - Note: - This method does not close the underlying HTTP client. If you provided - your own HTTP client, you are responsible for closing it yourself. - - Example:: - - from pyqwest import SyncClient - from my_service import MyServiceClient - - http_client = SyncClient() - client = MyServiceClient("http://localhost", http_client=http_client) - try: - # Use the client... - pass - finally: - client.close() # Marks connect client as closed - http_client.close() # You must close the HTTP client yourself - """ + """Close the client. After closing, the client cannot be used to make requests.""" if not self._closed: self._closed = True From cd9b9990f49d6427b57748eaec5a49b1c3e33282 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Tue, 14 Jul 2026 10:19:15 +0900 Subject: [PATCH 4/4] Add pyqwest objects.inv Signed-off-by: Anuraag Agrawal --- zensical.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zensical.toml b/zensical.toml index a63142f8..f07b2ed8 100644 --- a/zensical.toml +++ b/zensical.toml @@ -36,7 +36,8 @@ alternate_style = true [project.plugins.mkdocstrings.handlers.python] inventories = [ "https://docs.python.org/3/objects.inv", - "https://protobufpy.com/objects.inv" + "https://protobufpy.com/objects.inv", + "https://pyqwest.dev/objects.inv", ] paths = ["src"]