Add aiter methods on response (#610)
This commit is contained in:
parent
d15dc0b1f8
commit
ec40d04382
@ -28,10 +28,10 @@ async with request.stream("GET", "https://www.example.com") as response:
|
||||
|
||||
Within a `stream()` block request data is made available with:
|
||||
|
||||
* `.stream_bytes()` - Instead of `response.iter_content()`
|
||||
* `.stream_text()` - Instead of `response.iter_content(decode_unicode=True)`
|
||||
* `.stream_lines()` - Instead of `response.iter_lines()`
|
||||
* `.stream_raw()` - Use this instead of `response.raw`
|
||||
* `.aiter_bytes()` - Instead of `response.iter_content()`
|
||||
* `.aiter_text()` - Instead of `response.iter_content(decode_unicode=True)`
|
||||
* `.aiter_lines()` - Instead of `response.iter_lines()`
|
||||
* `.aiter_raw()` - Use this instead of `response.raw`
|
||||
* `.read()` - Read the entire response body, making `request.text` and `response.content` available.
|
||||
|
||||
## SSL configuration
|
||||
|
||||
@ -304,7 +304,7 @@ You can stream the binary content of the response...
|
||||
|
||||
```
|
||||
>>> async with httpx.stream("GET", "https://www.example.com") as r:
|
||||
... async for data in r.stream_bytes():
|
||||
... async for data in r.aiter_bytes():
|
||||
... print(data)
|
||||
```
|
||||
|
||||
@ -312,7 +312,7 @@ Or the text of the response...
|
||||
|
||||
```
|
||||
>>> async with httpx.stream("GET", "https://www.example.com") as r:
|
||||
... async for text in r.stream_text():
|
||||
... async for text in r.aiter_text():
|
||||
... print(text)
|
||||
```
|
||||
|
||||
@ -320,7 +320,7 @@ Or stream the text, on a line-by-line basis...
|
||||
|
||||
```
|
||||
>>> async with httpx.stream("GET", "https://www.example.com") as r:
|
||||
... async for line in r.stream_lines():
|
||||
... async for line in r.aiter_lines():
|
||||
... print(line)
|
||||
```
|
||||
|
||||
@ -330,7 +330,7 @@ In some cases you might want to access the raw bytes on the response without app
|
||||
|
||||
```
|
||||
>>> async with httpx.stream("GET", "https://www.example.com") as r:
|
||||
... async for chunk in r.stream_raw():
|
||||
... async for chunk in r.aiter_raw():
|
||||
... print(chunk)
|
||||
```
|
||||
|
||||
|
||||
@ -919,26 +919,26 @@ class Response:
|
||||
Read and return the response content.
|
||||
"""
|
||||
if not hasattr(self, "_content"):
|
||||
self._content = b"".join([part async for part in self.stream_bytes()])
|
||||
self._content = b"".join([part async for part in self.aiter_bytes()])
|
||||
return self._content
|
||||
|
||||
@property
|
||||
def stream(self): # type: ignore
|
||||
warnings.warn(
|
||||
"Response.stream() is due to be deprecated. "
|
||||
"Use Response.stream_bytes() instead."
|
||||
"Use Response.aiter_bytes() instead."
|
||||
)
|
||||
return self.stream_bytes
|
||||
return self.aiter_bytes
|
||||
|
||||
@property
|
||||
def raw(self): # type: ignore
|
||||
warnings.warn(
|
||||
"Response.raw() is due to be deprecated. "
|
||||
"Use Response.stream_raw() instead."
|
||||
"Use Response.aiter_raw() instead."
|
||||
)
|
||||
return self.stream_raw
|
||||
return self.aiter_raw
|
||||
|
||||
async def stream_bytes(self) -> typing.AsyncIterator[bytes]:
|
||||
async def aiter_bytes(self) -> typing.AsyncIterator[bytes]:
|
||||
"""
|
||||
A byte-iterator over the decoded response content.
|
||||
This allows us to handle gzip, deflate, and brotli encoded responses.
|
||||
@ -946,30 +946,30 @@ class Response:
|
||||
if hasattr(self, "_content"):
|
||||
yield self._content
|
||||
else:
|
||||
async for chunk in self.stream_raw():
|
||||
async for chunk in self.aiter_raw():
|
||||
yield self.decoder.decode(chunk)
|
||||
yield self.decoder.flush()
|
||||
|
||||
async def stream_text(self) -> typing.AsyncIterator[str]:
|
||||
async def aiter_text(self) -> typing.AsyncIterator[str]:
|
||||
"""
|
||||
A str-iterator over the decoded response content
|
||||
that handles both gzip, deflate, etc but also detects the content's
|
||||
string encoding.
|
||||
"""
|
||||
decoder = TextDecoder(encoding=self.charset_encoding)
|
||||
async for chunk in self.stream_bytes():
|
||||
async for chunk in self.aiter_bytes():
|
||||
yield decoder.decode(chunk)
|
||||
yield decoder.flush()
|
||||
|
||||
async def stream_lines(self) -> typing.AsyncIterator[str]:
|
||||
async def aiter_lines(self) -> typing.AsyncIterator[str]:
|
||||
decoder = LineDecoder()
|
||||
async for text in self.stream_text():
|
||||
async for text in self.aiter_text():
|
||||
for line in decoder.decode(text):
|
||||
yield line
|
||||
for line in decoder.flush():
|
||||
yield line
|
||||
|
||||
async def stream_raw(self) -> typing.AsyncIterator[bytes]:
|
||||
async def aiter_raw(self) -> typing.AsyncIterator[bytes]:
|
||||
"""
|
||||
A byte-iterator over the raw response content.
|
||||
"""
|
||||
|
||||
@ -71,7 +71,7 @@ async def test_stream_iterator(server):
|
||||
|
||||
async with httpx.Client() as client:
|
||||
async with client.stream("GET", server.url) as response:
|
||||
async for chunk in response.stream_bytes():
|
||||
async for chunk in response.aiter_bytes():
|
||||
body += chunk
|
||||
|
||||
assert response.status_code == 200
|
||||
@ -84,7 +84,7 @@ async def test_raw_iterator(server):
|
||||
|
||||
async with httpx.Client() as client:
|
||||
async with client.stream("GET", server.url) as response:
|
||||
async for chunk in response.stream_raw():
|
||||
async for chunk in response.aiter_raw():
|
||||
body += chunk
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
@ -137,41 +137,41 @@ async def test_raw_interface():
|
||||
response = httpx.Response(200, content=b"Hello, world!")
|
||||
|
||||
raw = b""
|
||||
async for part in response.stream_raw():
|
||||
async for part in response.aiter_raw():
|
||||
raw += part
|
||||
assert raw == b"Hello, world!"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_interface():
|
||||
async def test_bytes_interface():
|
||||
response = httpx.Response(200, content=b"Hello, world!")
|
||||
|
||||
content = b""
|
||||
async for part in response.stream_bytes():
|
||||
async for part in response.aiter_bytes():
|
||||
content += part
|
||||
assert content == b"Hello, world!"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_text():
|
||||
async def test_text_interface():
|
||||
response = httpx.Response(200, content=b"Hello, world!")
|
||||
|
||||
await response.read()
|
||||
|
||||
content = ""
|
||||
async for part in response.stream_text():
|
||||
async for part in response.aiter_text():
|
||||
content += part
|
||||
assert content == "Hello, world!"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_stream_lines():
|
||||
async def test_lines_interface():
|
||||
response = httpx.Response(200, content=b"Hello,\nworld!")
|
||||
|
||||
await response.read()
|
||||
|
||||
content = []
|
||||
async for line in response.stream_lines():
|
||||
async for line in response.aiter_lines():
|
||||
content.append(line)
|
||||
assert content == ["Hello,\n", "world!"]
|
||||
|
||||
@ -183,7 +183,7 @@ async def test_stream_interface_after_read():
|
||||
await response.read()
|
||||
|
||||
content = b""
|
||||
async for part in response.stream_bytes():
|
||||
async for part in response.aiter_bytes():
|
||||
content += part
|
||||
assert content == b"Hello, world!"
|
||||
|
||||
@ -207,7 +207,7 @@ async def test_cannot_read_after_stream_consumed():
|
||||
response = httpx.Response(200, content=async_streaming_body())
|
||||
|
||||
content = b""
|
||||
async for part in response.stream_bytes():
|
||||
async for part in response.aiter_bytes():
|
||||
content += part
|
||||
|
||||
with pytest.raises(httpx.StreamConsumed):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user