Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,21 @@ CHANGELOG
NEXT
~~~~~~~~~~~~~~~~~

- Drop support for Python 3.8
- **Breaking change**: Drop support for Python 3.8, require Python >= 3.9
- **Breaking change**: Remove deprecated ``xxhash.VERSION_TUPLE``
- Upgrade xxHash from v0.8.2 to v0.8.3. Note: on GCC/Clang source builds
that target AVX2 (e.g. ``-march=x86-64-v3``), upstream v0.8.3
autovectorizes ``XXH64_update()`` and makes the xxh64 streaming path
about 2x slower. The shipped wheels are built for baseline x86-64 and
are unaffected. Source builds can work around it by adding
``-fno-tree-vectorize`` to the compiler flags.
- Add per-object locking for thread safety, with sub-interpreter and
free-threaded (no-GIL) Python support
- Build pyodide wasm32 wheels
- Add s390x big-endian test job
- Add Python 3.15 classifier
- CI: shard the PyPI upload into parallel groups and create the GitHub
Release automatically

v3.8.1 2026-07-06
~~~~~~~~~~~~~~~~~
Expand Down
25 changes: 23 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ the module properties ``VERSION`` AND ``XXHASH_VERSION`` respectively.

>>> import xxhash
>>> xxhash.VERSION
'2.0.0'
'4.0.0'
>>> xxhash.XXHASH_VERSION
'0.8.0'
'0.8.3'

This module is hashlib-compliant, which means you can use it in the same way as ``hashlib.md5``.

Expand Down Expand Up @@ -251,6 +251,27 @@ And aliases:
| xxh128_intdigest = xxh3_128_intdigest
| xxh128_hexdigest = xxh3_128_hexdigest

Thread safety
-------------

Streaming hash objects (``xxh32``, ``xxh64``, ``xxh3_64``, ``xxh3_128`` /
``xxh128``) are thread-safe: each object carries a per-object lock that
serializes access to its internal xxHash state, so concurrent ``update()``,
``digest()``, ``copy()``, and ``reset()`` calls on the same object never
corrupt state or crash.

One-shot functions (``xxh32_digest``, ``xxh64_hexdigest``, ``xxh3_128_digest``,
etc.) are stateless and always safe to call concurrently.

On Python 3.13+ the lock is always active. On Python 3.9-3.12 the lock is
created on the first ``update()`` of 64KB or more; smaller operations never
release the GIL, so they are serialized by the GIL itself.

Sharing a streaming hash object across threads is still discouraged: even
with locking, the order in which concurrent updates are applied (and hence
the final digest) is nondeterministic. Prefer one-shot functions or one hash
object per thread.

Caveats
-------

Expand Down
3 changes: 1 addition & 2 deletions xxhash/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
XXHASH_VERSION,
)

from .version import VERSION, VERSION_TUPLE
from .version import VERSION


xxh128 = xxh3_128
Expand Down Expand Up @@ -59,7 +59,6 @@
"xxh128_intdigest",
"xxh128_hexdigest",
"VERSION",
"VERSION_TUPLE",
"XXHASH_VERSION",
"algorithms_available",
"algorithms_guaranteed",
Expand Down
3 changes: 0 additions & 3 deletions xxhash/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ _DataType = _Buffer

VERSION: str
XXHASH_VERSION: str
#: Deprecated, will be removed in the next major release
VERSION_TUPLE: tuple[int, ...]

algorithms_available: set[str]
algorithms_guaranteed: set[str]
Expand All @@ -36,7 +34,6 @@ __all__: list[str] = [
"xxh128_intdigest",
"xxh128_hexdigest",
"VERSION",
"VERSION_TUPLE",
"XXHASH_VERSION",
"algorithms_available",
"algorithms_guaranteed",
Expand Down
4 changes: 1 addition & 3 deletions xxhash/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
VERSION = "3.8.0.dev9"
#: Deprecated, will be removed in the next major release
VERSION_TUPLE = (3, 8, 0)
VERSION = "4.0.0.dev0"
Loading