From: Tom Christie Date: Thu, 6 Jan 2022 14:06:35 +0000 (+0000) Subject: Fix for stream uploads that subclass SyncByteStream/AsyncByteStream (#2016) X-Git-Tag: 0.21.3~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b7dc0c3df68279ce89f016a69a41b27a2346d54d;p=thirdparty%2Fhttpx.git Fix for stream uploads that subclass SyncByteStream/AsyncByteStream (#2016) --- diff --git a/httpx/_content.py b/httpx/_content.py index f210c4a8..4871a8de 100644 --- a/httpx/_content.py +++ b/httpx/_content.py @@ -50,7 +50,9 @@ class IteratorByteStream(SyncByteStream): raise StreamConsumed() self._is_stream_consumed = True - if hasattr(self._stream, "read"): + if hasattr(self._stream, "read") and not isinstance( + self._stream, SyncByteStream + ): # File-like interfaces should use 'read' directly. chunk = self._stream.read(self.CHUNK_SIZE) # type: ignore while chunk: @@ -75,7 +77,9 @@ class AsyncIteratorByteStream(AsyncByteStream): raise StreamConsumed() self._is_stream_consumed = True - if hasattr(self._stream, "aread"): + if hasattr(self._stream, "aread") and not isinstance( + self._stream, AsyncByteStream + ): # File-like interfaces should use 'aread' directly. chunk = await self._stream.aread(self.CHUNK_SIZE) # type: ignore while chunk: diff --git a/tests/test_api.py b/tests/test_api.py index b6c2421a..22ab7969 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -28,6 +28,18 @@ def test_post_byte_iterator(server): assert response.reason_phrase == "OK" +def test_post_byte_stream(server): + class Data(httpx.SyncByteStream): + def __iter__(self): + yield b"Hello" + yield b", " + yield b"world!" + + response = httpx.post(server.url, content=Data()) + assert response.status_code == 200 + assert response.reason_phrase == "OK" + + def test_options(server): response = httpx.options(server.url) assert response.status_code == 200