Update brotli support to use the brotlicffi package (#1605)

* Update brotli support to use the brotlicffi package
This commit is contained in:
Tom Christie 2021-04-28 10:09:29 +01:00 committed by GitHub
parent 0c2cb240df
commit 760af43b4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 20 additions and 23 deletions

View File

@ -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

View File

@ -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

View File

@ -11,9 +11,9 @@ import zlib
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 @@ class BrotliDecoder(ContentDecoder):
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 @@ class BrotliDecoder(ContentDecoder):
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 @@ SUPPORTED_DECODERS = {
}
if brotli is None:
if brotlicffi is None:
SUPPORTED_DECODERS.pop("br") # pragma: nocover

View File

@ -1,7 +1,4 @@
-e .[http2]
# Optional
brotlipy==0.7.*
-e .[http2,brotli]
# Documentation
mkdocs

View File

@ -64,7 +64,7 @@ setup(
],
extras_require={
"http2": "h2==3.*",
"brotli": "brotlipy==0.7.*",
"brotli": "brotlicffi==1.*",
},
classifiers=[
"Development Status :: 4 - Beta",

View File

@ -2,7 +2,7 @@ import json
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)

View File

@ -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)