From 5f049996c0c7903af831a4dcbc559ca47117d719 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 28 Apr 2021 09:32:07 +0100 Subject: [PATCH 1/3] Update brotli support to use the brotlicffi package --- README.md | 2 +- docs/index.md | 2 +- httpx/_decoders.py | 18 +++++++++--------- requirements.txt | 5 +---- setup.py | 2 +- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index e85a0142c9..1bae5926b4 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ The HTTPX project relies on these excellent libraries: * `idna` - Internationalized domain name support. * `sniffio` - Async library autodetection. * `async_generator` - Backport support for `contextlib.asynccontextmanager`. *(Only required for Python 3.6)* -* `brotlipy` - Decoding for "brotli" compressed responses. *(Optional)* +* `brotlicffi` - Decoding for "brotli" compressed responses. *(Optional)* A huge amount of credit is due to `requests` for the API layout that much of this work follows, as well as to `urllib3` for plenty of design diff --git a/docs/index.md b/docs/index.md index 8a41dca3b1..a550f7859d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -115,7 +115,7 @@ The HTTPX project relies on these excellent libraries: * `idna` - Internationalized domain name support. * `sniffio` - Async library autodetection. * `async_generator` - Backport support for `contextlib.asynccontextmanager`. *(Only required for Python 3.6)* -* `brotlipy` - Decoding for "brotli" compressed responses. *(Optional)* +* `brotlicffi` - Decoding for "brotli" compressed responses. *(Optional)* A huge amount of credit is due to `requests` for the API layout that much of this work follows, as well as to `urllib3` for plenty of design diff --git a/httpx/_decoders.py b/httpx/_decoders.py index c0d51a4cdc..2230b77a9f 100644 --- a/httpx/_decoders.py +++ b/httpx/_decoders.py @@ -11,9 +11,9 @@ from ._exceptions import DecodingError try: - import brotli + import brotlicffi except ImportError: # pragma: nocover - brotli = None + brotlicffi = None class ContentDecoder: @@ -99,14 +99,14 @@ class BrotliDecoder(ContentDecoder): """ def __init__(self) -> None: - if brotli is None: # pragma: nocover + if brotlicffi is None: # pragma: nocover raise ImportError( - "Using 'BrotliDecoder', but the 'brotlipy' or 'brotli' library " + "Using 'BrotliDecoder', but the 'brotlicffi' library " "is not installed." "Make sure to install httpx using `pip install httpx[brotli]`." ) from None - self.decompressor = brotli.Decompressor() + self.decompressor = brotlicffi.Decompressor() self.seen_data = False if hasattr(self.decompressor, "decompress"): self._decompress = self.decompressor.decompress @@ -118,8 +118,8 @@ def decode(self, data: bytes) -> bytes: return b"" self.seen_data = True try: - return self._decompress(data) - except brotli.error as exc: + return self.decompressor.decompress(data) + except brotlicffi.Error as exc: raise DecodingError(str(exc)) from exc def flush(self) -> bytes: @@ -129,7 +129,7 @@ def flush(self) -> bytes: if hasattr(self.decompressor, "finish"): self.decompressor.finish() return b"" - except brotli.error as exc: # pragma: nocover + except brotlicffi.Error as exc: # pragma: nocover raise DecodingError(str(exc)) from exc @@ -365,5 +365,5 @@ def flush(self) -> typing.List[str]: } -if brotli is None: +if brotlicffi is None: SUPPORTED_DECODERS.pop("br") # pragma: nocover diff --git a/requirements.txt b/requirements.txt index 725811da98..f34bdeaac6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,4 @@ --e .[http2] - -# Optional -brotlipy==0.7.* +-e .[http2,brotli] # Documentation mkdocs diff --git a/setup.py b/setup.py index 1ddae87a9b..e27cda8e16 100644 --- a/setup.py +++ b/setup.py @@ -64,7 +64,7 @@ def get_packages(package): ], extras_require={ "http2": "h2==3.*", - "brotli": "brotlipy==0.7.*", + "brotli": "brotlicffi==1.*", }, classifiers=[ "Development Status :: 4 - Beta", From 6d2f5013d34a0a4dfd040f1764860b5c69825c28 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 28 Apr 2021 09:36:21 +0100 Subject: [PATCH 2/3] Update tests to use brotlicffi package --- tests/test_decoders.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_decoders.py b/tests/test_decoders.py index faaf71d2fb..f681a57a7f 100644 --- a/tests/test_decoders.py +++ b/tests/test_decoders.py @@ -1,6 +1,6 @@ import zlib -import brotli +import brotlicffi import pytest import httpx @@ -69,7 +69,7 @@ def test_gzip(): def test_brotli(): body = b"test 123" - compressed_body = brotli.compress(body) + compressed_body = brotlicffi.compress(body) headers = [(b"Content-Encoding", b"br")] response = httpx.Response( @@ -102,7 +102,7 @@ def test_multi(): def test_multi_with_identity(): body = b"test 123" - compressed_body = brotli.compress(body) + compressed_body = brotlicffi.compress(body) headers = [(b"Content-Encoding", b"br, identity")] response = httpx.Response( @@ -165,7 +165,7 @@ def test_decoders_empty_cases(decoder): def test_decoding_errors(header_value): headers = [(b"Content-Encoding", header_value)] body = b"test 123" - compressed_body = brotli.compress(body)[3:] + compressed_body = brotlicffi.compress(body)[3:] with pytest.raises(httpx.DecodingError): request = httpx.Request("GET", "https://example.org") httpx.Response(200, headers=headers, content=compressed_body, request=request) From 60795c149ca2519d6c3f447ca53476eb4d0286fb Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 28 Apr 2021 09:40:29 +0100 Subject: [PATCH 3/3] Update tests to use brotlicffi package --- tests/models/test_responses.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/models/test_responses.py b/tests/models/test_responses.py index 5e2afc1bf3..742a15bea7 100644 --- a/tests/models/test_responses.py +++ b/tests/models/test_responses.py @@ -2,7 +2,7 @@ import pickle from unittest import mock -import brotli +import brotlicffi import pytest import httpx @@ -788,7 +788,7 @@ def test_link_headers(headers, expected): def test_decode_error_with_request(header_value): headers = [(b"Content-Encoding", header_value)] body = b"test 123" - compressed_body = brotli.compress(body)[3:] + compressed_body = brotlicffi.compress(body)[3:] with pytest.raises(httpx.DecodingError): httpx.Response( 200, @@ -809,7 +809,7 @@ def test_decode_error_with_request(header_value): def test_value_error_without_request(header_value): headers = [(b"Content-Encoding", header_value)] body = b"test 123" - compressed_body = brotli.compress(body)[3:] + compressed_body = brotlicffi.compress(body)[3:] with pytest.raises(httpx.DecodingError): httpx.Response(200, headers=headers, content=compressed_body)