Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions docs/source/guide/basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,17 @@ async def main():
client = Client()
response = await client.get("https://httpbin.org/stream/10")

async for chunk in response.stream():
if isinstance(chunk, memoryview):
sys.stdout.buffer.write(chunk)
elif isinstance(chunk, HeaderMap):
print("Trailers:", chunk)
async with response:
async with response.stream() as streamer:
async for chunk in streamer:
if isinstance(chunk, memoryview):
sys.stdout.buffer.write(chunk)
elif isinstance(chunk, HeaderMap):
print("Trailers:", chunk)
```

Data chunks are read-only `memoryview` objects; trailer frames are `HeaderMap` objects. The example writes data directly through the buffer protocol. Each view stays valid after the stream is closed. See [Binary data](../getting-started/quickstart.md#binary-data) for copying and releasing views.

Finish a body read before closing the response. If a read task is still running, cancel it and await its cancellation first: `response.close()` does not cancel active reads or guarantee an immediate socket shutdown. `response.stream()` transfers the body to the streamer, so manage the streamer with its own context manager as shown above.

---
2 changes: 2 additions & 0 deletions docs/source/guide/blocking.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,5 @@ if __name__ == "__main__":
```

Data chunks are read-only `memoryview` objects that stay valid after the stream is closed. `resp.bytes()` returns the same type. Pass views directly to APIs that accept the buffer protocol; use `bytes(view)` or `view.tobytes()` only when you need a copy.

Do not close a response while another thread is reading its body. `resp.close()` discards the retained body and marks its connection as non-reusable, but does not guarantee an immediate socket shutdown or interrupt an active read. A body transferred by `resp.stream()` belongs to the streamer and needs its own context manager, as shown above.
10 changes: 5 additions & 5 deletions python/wreq/blocking.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ def bytes(self) -> memoryview:

def close(self) -> None:
r"""
Close the response.

This method closes the network connection regardless of whether connection pooling is
enabled or not. It is recommended to use context managers (`with` statement) to properly
manage response lifecycle instead of calling this method manually.
Discard the retained body and mark its connection as non-reusable.
This does not guarantee an immediate socket shutdown or interrupt an active read.
Do not close concurrently with a body read. A body transferred to a Streamer
is managed separately; previously returned memoryviews remain valid.
Prefer a context manager (`with`) for response cleanup.
"""

def __enter__(self) -> Any: ...
Expand Down
10 changes: 5 additions & 5 deletions python/wreq/wreq.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,11 +430,11 @@ async def bytes(self) -> memoryview:

async def close(self) -> None:
r"""
Close the response.

This method closes the network connection regardless of whether connection pooling is
enabled or not. It is recommended to use async context managers (`async with` statement)
to properly manage response lifecycle instead of calling this method manually.
Discard the retained body and mark its connection as non-reusable.
This does not guarantee an immediate socket shutdown or cancel an active read.
Cancel and await any body-read task before closing. A body transferred to a
Streamer is managed separately; previously returned memoryviews remain valid.
Prefer an async context manager (`async with`) for response cleanup.
"""

async def __aenter__(self) -> Any: ...
Expand Down
20 changes: 10 additions & 10 deletions src/client/resp/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,11 +249,11 @@ impl Response {
NoGIL::new(fut, cancel).await
}

/// Close the response.
///
/// This method closes the network connection regardless of whether connection pooling is
/// enabled or not. It is recommended to use async context managers (`async with` statement)
/// to properly manage response lifecycle instead of calling this method manually.
/// Discard the retained body and mark its connection as non-reusable.
/// This does not guarantee an immediate socket shutdown or cancel an active read.
/// Cancel and await any body-read task before closing. A body transferred to a
/// Streamer is managed separately; previously returned memoryviews remain valid.
/// Prefer an async context manager (`async with`) for response cleanup.
pub async fn close(&self) {
Python::attach(|py| {
py.detach(|| {
Expand Down Expand Up @@ -410,11 +410,11 @@ impl BlockingResponse {
})
}

/// Close the response.
///
/// This method closes the network connection regardless of whether connection pooling is
/// enabled or not. It is recommended to use context managers (`with` statement) to properly
/// manage response lifecycle instead of calling this method manually.
/// Discard the retained body and mark its connection as non-reusable.
/// This does not guarantee an immediate socket shutdown or interrupt an active read.
/// Do not close concurrently with a body read. A body transferred to a Streamer
/// is managed separately; previously returned memoryviews remain valid.
/// Prefer a context manager (`with`) for response cleanup.
#[inline]
pub fn close(&self, py: Python) {
py.detach(|| {
Expand Down
Loading