brotlicffi

Python CFFI bindings for Google's Brotli compression library, providing an API-compatible fallback for PyPy and other non-CPython runtimes.

Library
PyPI
v1.2.0.2
154stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
58/100Fair
Development Activity60
Maintenance16
Community76
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture75
Code Quality78
Innovation58
Learning Curve85

brotlicffi provides Python bindings to Google’s reference Brotli encoder and decoder using CFFI instead of the CPython C API, making it usable on PyPy and other non-CPython implementations where the standard brotli package’s C extension won’t build. It bundles the reference C implementation of Brotli as a git submodule and statically compiles it by default, so no separate system Brotli library needs to be installed unless USE_SHARED_BROTLI=1 is set.

The library exposes a small, drop-in-compatible API — module-level compress()/decompress() functions plus streaming Compressor/Decompressor classes — that mirrors the CPython C-extension Brotli package closely enough that projects typically install both and fall back to brotlicffi conditionally based on platform_python_implementation.

What You Get

  • One-shot compress()/decompress() functions for single-call compression of complete byte strings
  • Streaming Compressor/Decompressor classes for incremental compression of data that arrives in chunks
  • A statically bundled copy of the reference Brotli C library (via git submodule) so no system-level Brotli install is required
  • An API-compatible drop-in replacement for the CPython Brotli C-extension package, letting projects support PyPy and other non-CPython runtimes

Common Use Cases

  • Adding Brotli compression support to an HTTP client or server running on PyPy, where the C-extension brotli package cannot be installed
  • Decompressing Brotli-encoded HTTP response bodies (Content-Encoding: br) in an HTTP library
  • Building cross-implementation Python packages that need Brotli support on both CPython and non-CPython interpreters
  • Streaming compression of large payloads where data arrives incrementally and cannot be buffered in memory all at once

Under The Hood

Architecture brotlicffi is architected as a thin single-module wrapper (src/brotlicffi/_api.py, roughly 600 lines) sitting directly atop a build-time-generated CFFI extension. src/brotlicffi/_build.py declares the C signatures via ffi.cdef() and set_source(), and setup.py’s custom BuildClibBeforeExt subclass of build_ext forces the build_clib step to run first so the vendored libbrotli C sources (a git submodule under libbrotli/) get statically compiled and linked into the resulting _brotlicffi extension module. _api.py then imports that generated ffi/lib pair and exposes two layers: high-level, one-shot compress()/decompress() convenience functions, and lower-level Compressor/Decompressor classes that each own a single native encoder/decoder instance guarded by a threading.Lock/RLock (raising error() if a concurrent caller tries to reuse the same instance). init.py does nothing more than re-export the public names and version. There is essentially no additional layering — no plugin system, no dependency injection — which is appropriate for a binding library whose only job is to move bytes between Python and a native compression routine.

Tech Stack The project’s only runtime dependency is cffi, used for the FFI binding instead of the CPython C-API so the same extension can build on PyPy. By default (unless the USE_SHARED_BROTLI=1 environment variable is set) it statically compiles the vendored reference Brotli C sources from the libbrotli git submodule rather than requiring a system-installed libbrotli; when USE_SHARED_BROTLI=1 it links against system brotlienc/brotlidec (plus stdc++ on non-Windows) instead. Testing runs through pytest and pytest-cov, orchestrated by tox across a matrix from py37 through py314(t) plus PyPy, and linting runs via flake8 with a max-complexity-10 gate. CI (GitHub Actions) runs the lint job plus the full test matrix across ubuntu-latest, macos-latest, and windows-latest. Documentation is built with Sphinx from docs/source/, and an example/ directory demonstrates the CPython/CFFI fallback pattern end-to-end.

Code Quality Test coverage comes from four dedicated files (test_simple_compression.py, test_simple_decompression.py, test_compatibility.py, test_multithreaded_sharing.py) totalling seventeen test functions plus a shared conftest.py, run under pytest with coverage instrumentation and gated by flake8 in CI across three operating systems and a wide Python version/implementation matrix. Error handling is explicit around a single custom error/Error exception class, with dedicated _validate_mode/_validate_quality/_validate_lgwin/_validate_lgblock helpers that raise clear, parameter-specific messages rather than letting invalid values reach the native layer silently. The codebase has no static type hints or mypy configuration, relying instead on Sphinx-style docstrings with :param:/:type:/:versionadded: annotations for documentation; naming is consistent and the module is small enough that this is a minor gap rather than a real risk.

API Design The public API is deliberately designed for drop-in compatibility with the CPython brotli C-extension package: the same compress()/decompress() function signatures, the same Compressor/Decompressor class names and methods, and the same MODE_GENERIC/MODE_TEXT/MODE_FONT constants, so calling code can try/except ImportError between import brotli and import brotlicffi as brotli without any branching logic. This isn’t algorithmic innovation — the compression algorithm itself is Google’s unmodified reference Brotli implementation — but it is a deliberate, low-boilerplate developer-experience choice: a single conditional import lets existing brotli-based code work unchanged on PyPy and other non-CPython runtimes where the C extension can’t be built.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search