diff --git a/.mypy.ini b/.mypy.ini index 6803a4f3c6d..86b5c86f345 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -35,6 +35,9 @@ ignore_missing_imports = True [mypy-brotli] ignore_missing_imports = True +[mypy-brotlicffi] +ignore_missing_imports = True + [mypy-gunicorn.*] ignore_missing_imports = True diff --git a/CHANGES/7611.feature b/CHANGES/7611.feature new file mode 100644 index 00000000000..ce1b4b2ac1a --- /dev/null +++ b/CHANGES/7611.feature @@ -0,0 +1 @@ +Support using ``brotlicffi`` Python package alternatively to ``brotli``, as the latter does not work on PyPy. diff --git a/aiohttp/compression_utils.py b/aiohttp/compression_utils.py index 8abc4fa7c3c..52791fe5015 100644 --- a/aiohttp/compression_utils.py +++ b/aiohttp/compression_utils.py @@ -4,7 +4,10 @@ from typing import Optional, cast try: - import brotli + try: + import brotlicffi as brotli + except ImportError: + import brotli HAS_BROTLI = True except ImportError: # pragma: no cover diff --git a/docs/client_quickstart.rst b/docs/client_quickstart.rst index d5915dddbe6..47ba40023c5 100644 --- a/docs/client_quickstart.rst +++ b/docs/client_quickstart.rst @@ -184,7 +184,8 @@ The ``gzip`` and ``deflate`` transfer-encodings are automatically decoded for you. You can enable ``brotli`` transfer-encodings support, -just install `brotli `_. +just install `Brotli `_ +or `brotlicffi `_. JSON Request ============ diff --git a/docs/glossary.rst b/docs/glossary.rst index 4bfe7c55126..392ef740cd1 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -40,6 +40,13 @@ https://pypi.org/project/Brotli/ + brotlicffi + + An alternative implementation of :term:`Brotli` built using the CFFI + library. This implementation supports PyPy correctly. + + https://pypi.org/project/brotlicffi/ + callable Any object that can be called. Use :func:`callable` to check diff --git a/docs/index.rst b/docs/index.rst index f7f913c7152..881654429cc 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -159,7 +159,8 @@ Dependencies $ pip install aiodns -- *Optional* :term:`Brotli` for brotli (:rfc:`7932`) client compression support. +- *Optional* :term:`Brotli` or :term:`brotlicffi` for brotli (:rfc:`7932`) + client compression support. .. code-block:: bash diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index 7346fd0b8c2..d3ee117d475 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -39,6 +39,7 @@ boolean botocore brotli Brotli +brotlicffi brotlipy bugfix Bugfixes diff --git a/requirements/runtime-deps.in b/requirements/runtime-deps.in index 2d782c551e7..2bfb21ecd18 100644 --- a/requirements/runtime-deps.in +++ b/requirements/runtime-deps.in @@ -7,4 +7,5 @@ yarl >= 1.0, < 2.0 frozenlist >= 1.1.1 aiosignal >= 1.1.2 aiodns; sys_platform=="linux" or sys_platform=="darwin" -Brotli +Brotli; platform_python_implementation == 'CPython' +brotlicffi; platform_python_implementation != 'CPython' diff --git a/setup.cfg b/setup.cfg index 054ee7e9008..18b29652f9a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -63,7 +63,8 @@ install_requires = speedups = # required c-ares (aiodns' backend) will not build on windows aiodns; sys_platform=="linux" or sys_platform=="darwin" - Brotli + Brotli; platform_python_implementation == 'CPython' + brotlicffi; platform_python_implementation != 'CPython' [options.packages.find] exclude = diff --git a/tests/test_http_parser.py b/tests/test_http_parser.py index 0227c2a847c..7f3992604f8 100644 --- a/tests/test_http_parser.py +++ b/tests/test_http_parser.py @@ -21,7 +21,10 @@ ) try: - import brotli + try: + import brotlicffi as brotli + except ImportError: + import brotli except ImportError: brotli = None diff --git a/tests/test_web_functional.py b/tests/test_web_functional.py index b1c7268793d..1f81aa7bffe 100644 --- a/tests/test_web_functional.py +++ b/tests/test_web_functional.py @@ -7,7 +7,6 @@ from typing import Optional from unittest import mock -import brotli import pytest from multidict import CIMultiDictProxy, MultiDict from yarl import URL @@ -18,6 +17,11 @@ from aiohttp.test_utils import make_mocked_coro from aiohttp.typedefs import Handler +try: + import brotlicffi as brotli +except ImportError: + import brotli + try: import ssl except ImportError: