From d9375fda489f3e34536e739e232d7958cde39d4f Mon Sep 17 00:00:00 2001 From: Yue Du Date: Wed, 12 Aug 2026 05:22:10 +0000 Subject: [PATCH 1/5] Remove deprecated VERSION_TUPLE VERSION_TUPLE was deprecated in v3.6.0 and scheduled for removal in the next major release. --- xxhash/__init__.py | 3 +-- xxhash/__init__.pyi | 3 --- xxhash/version.py | 2 -- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/xxhash/__init__.py b/xxhash/__init__.py index 5fe0087..4825901 100644 --- a/xxhash/__init__.py +++ b/xxhash/__init__.py @@ -18,7 +18,7 @@ XXHASH_VERSION, ) -from .version import VERSION, VERSION_TUPLE +from .version import VERSION xxh128 = xxh3_128 @@ -59,7 +59,6 @@ "xxh128_intdigest", "xxh128_hexdigest", "VERSION", - "VERSION_TUPLE", "XXHASH_VERSION", "algorithms_available", "algorithms_guaranteed", diff --git a/xxhash/__init__.pyi b/xxhash/__init__.pyi index 09177fd..e90bffe 100644 --- a/xxhash/__init__.pyi +++ b/xxhash/__init__.pyi @@ -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] @@ -36,7 +34,6 @@ __all__: list[str] = [ "xxh128_intdigest", "xxh128_hexdigest", "VERSION", - "VERSION_TUPLE", "XXHASH_VERSION", "algorithms_available", "algorithms_guaranteed", diff --git a/xxhash/version.py b/xxhash/version.py index 17952b8..375d268 100644 --- a/xxhash/version.py +++ b/xxhash/version.py @@ -1,3 +1 @@ VERSION = "3.8.0.dev9" -#: Deprecated, will be removed in the next major release -VERSION_TUPLE = (3, 8, 0) From 9e07034974f2e38c725068e7dab09e010d30c247 Mon Sep 17 00:00:00 2001 From: Yue Du Date: Wed, 12 Aug 2026 05:22:18 +0000 Subject: [PATCH 2/5] Bump version to 4.0.0.dev0 --- xxhash/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xxhash/version.py b/xxhash/version.py index 375d268..1f5645f 100644 --- a/xxhash/version.py +++ b/xxhash/version.py @@ -1 +1 @@ -VERSION = "3.8.0.dev9" +VERSION = "4.0.0.dev0" From f908b543de2924488eb9ee0221a073431f586f69 Mon Sep 17 00:00:00 2001 From: Yue Du Date: Wed, 12 Aug 2026 05:22:34 +0000 Subject: [PATCH 3/5] Update README version example --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 15d105b..d33d902 100644 --- a/README.rst +++ b/README.rst @@ -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``. From c90fc54e3eca39e106bd8b6e89c566f4d73df054 Mon Sep 17 00:00:00 2001 From: Yue Du Date: Wed, 12 Aug 2026 05:22:44 +0000 Subject: [PATCH 4/5] Document thread safety in README --- README.rst | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.rst b/README.rst index d33d902..39b7d42 100644 --- a/README.rst +++ b/README.rst @@ -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 ------- From 950ca16c6b710d731ce947a6d3858f8f23f29435 Mon Sep 17 00:00:00 2001 From: Yue Du Date: Wed, 12 Aug 2026 05:22:49 +0000 Subject: [PATCH 5/5] Update changelog for 4.0.0 --- CHANGELOG.rst | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9a97a71..d2642d7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -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 ~~~~~~~~~~~~~~~~~