Skip to content
Closed
Show file tree
Hide file tree
Changes from 15 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
22 changes: 18 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
- '3.11'
- '3.12'
- '3.13'
- '3.13t'
arch:
- 'arm64'
- 'x86'
Expand Down Expand Up @@ -59,34 +60,45 @@ jobs:
PYTHONDEVMODE: '1'
steps:
- name: Set up Python
uses: actions/setup-python@v5
uses: astral-sh/setup-uv@v5
with:
python-version: ${{ matrix.py }}
architecture: ${{ matrix.arch }}

- name: install pip
run: |
uv pip install pip

- name: Install Rust
if: matrix.arch == 'x64'
if: matrix.arch == 'x64' && !startsWith(matrix.py, '3.13')
uses: dtolnay/rust-toolchain@v1
with:
toolchain: stable

- uses: actions/checkout@v4

- name: Install Dependencies
if: "!endsWith(matrix.py, 't')"
shell: bash
run: |
python -m pip install --require-hashes -r ci/requirements.txt

- name: Install Dependencies (free-threading)
if: "endsWith(matrix.py, 't')"
shell: bash
run: |
python -m pip install --require-hashes -r ci/requirements.freethreading.txt

# TODO enable once PyO3 supports 3.13.
- name: Build (Rust)
if: matrix.arch == 'x64' && matrix.py != '3.13'
if: matrix.arch == 'x64' && !startsWith(matrix.py, '3.13')
Comment on lines 81 to +83
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing this is supported now. But scope bloat to resolve it in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened a followup issue to track this #251

env:
PIP_CONSTRAINT: 'ci/constraints.txt'
run: |
python -m pip install --config-settings='--build-option=--rust-backend' -e .

- name: Build (No Rust)
if: matrix.arch != 'x64' || matrix.py == '3.13'
if: matrix.arch != 'x64' || startsWith(matrix.py, '3.13')
run: |
python -m pip install -e .

Expand All @@ -95,6 +107,8 @@ jobs:
pytest --numprocesses=auto --hypothesis-profile=${HYPOTHESIS_PROFILE} -v tests/

- name: Test CFFI Backend
# CFFI doesn't yet support the free-threaded build of CPython
if: matrix.py != '3.13t'
env:
PYTHON_ZSTANDARD_IMPORT_POLICY: 'cffi'
run: |
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ version = "2.0.10+zstd.1.5.6"
features = ["experimental", "legacy", "zstdmt"]

[dependencies.pyo3]
version = "0.21.2"
version = "0.22.2"
features = ["extension-module"]
6 changes: 5 additions & 1 deletion c-ext/backend_c.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ void zstd_module_init(PyObject *m) {
Py_DECREF(feature);
#endif

#ifdef Py_GIL_DISABLED
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
#endif

if (PyObject_SetAttrString(m, "backend_features", features) == -1) {
return;
}
Expand Down Expand Up @@ -313,7 +317,7 @@ size_t roundpow2(size_t i) {
int safe_pybytes_resize(PyObject **obj, Py_ssize_t size) {
PyObject *tmp;

if ((*obj)->ob_refcnt == 1) {
if (Py_REFCNT(*obj) == 1) {
return _PyBytes_Resize(obj, size);
}

Expand Down
11 changes: 11 additions & 0 deletions ci/requirements.freethreading.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This is a dependency of pytest on Windows but isn't picked up by pip-compile.
atomicwrites
cibuildwheel
#cffi
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that we're disabling cffi with setup.py maybe it makes sense to uncomment this line.
probably less headaches in the future.

IIRC this was the only difference, so these special requirements files for free threading can be removed.
(I'm on my phone, sorry I can't check this right now.)

colorama
hypothesis
mypy
pycparser
pytest-xdist
pytest
wheel
127 changes: 127 additions & 0 deletions ci/requirements.freethreading.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#
# This file is autogenerated by pip-compile with Python 3.13
# by the following command:
#
# pip-compile --generate-hashes --output-file=ci/requirements.freethreading.txt --pre ci/requirements.freethreading.in
#
atomicwrites==1.4.1 \
--hash=sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11
# via -r ci/requirements.freethreading.in
attrs==24.2.0 \
--hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \
--hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2
# via hypothesis
bashlex==0.18 \
--hash=sha256:5bb03a01c6d5676338c36fd1028009c8ad07e7d61d8a1ce3f513b7fff52796ee \
--hash=sha256:91d73a23a3e51711919c1c899083890cdecffc91d8c088942725ac13e9dcfffa
# via cibuildwheel
bracex==2.5.post1 \
--hash=sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6 \
--hash=sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6
# via cibuildwheel
certifi==2024.8.30 \
--hash=sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8 \
--hash=sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9
# via cibuildwheel
cibuildwheel==2.21.3 \
--hash=sha256:3ce23a9e5406b3eeb80039d7a6fdb218a2450932a8037c0bf76511cd88dfb74e \
--hash=sha256:f1d036a13603a6ce4019d8b1bd52c296cf32461a3b3be8441434b60b8b378b80
# via -r ci/requirements.freethreading.in
colorama==0.4.6 \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
# via -r ci/requirements.freethreading.in
execnet==2.1.1 \
--hash=sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc \
--hash=sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3
# via pytest-xdist
filelock==3.16.1 \
--hash=sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0 \
--hash=sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435
# via cibuildwheel
hypothesis==6.116.0 \
--hash=sha256:9c1ac9a2edb77aacae1950d8ded6b3f40dbf8483097c88336265c348d2132c71 \
--hash=sha256:d30271214eae0d4758b72b408e9777405c7c7f687e14e8a42853adea887b2891
# via -r ci/requirements.freethreading.in
iniconfig==2.0.0 \
--hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \
--hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374
# via pytest
mypy==1.13.0 \
--hash=sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc \
--hash=sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e \
--hash=sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f \
--hash=sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74 \
--hash=sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a \
--hash=sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2 \
--hash=sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b \
--hash=sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73 \
--hash=sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e \
--hash=sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d \
--hash=sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d \
--hash=sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6 \
--hash=sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca \
--hash=sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d \
--hash=sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5 \
--hash=sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62 \
--hash=sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a \
--hash=sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc \
--hash=sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7 \
--hash=sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb \
--hash=sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7 \
--hash=sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732 \
--hash=sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80 \
--hash=sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a \
--hash=sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc \
--hash=sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2 \
--hash=sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0 \
--hash=sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24 \
--hash=sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7 \
--hash=sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b \
--hash=sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372 \
--hash=sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8
# via -r ci/requirements.freethreading.in
mypy-extensions==1.0.0 \
--hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
--hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
# via mypy
packaging==24.1 \
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
# via
# cibuildwheel
# pytest
platformdirs==4.3.6 \
--hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \
--hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb
# via cibuildwheel
pluggy==1.5.0 \
--hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \
--hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669
# via pytest
pycparser==2.22 \
--hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \
--hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc
# via -r ci/requirements.freethreading.in
pytest==8.3.3 \
--hash=sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181 \
--hash=sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2
# via
# -r ci/requirements.freethreading.in
# pytest-xdist
pytest-xdist==3.6.1 \
--hash=sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7 \
--hash=sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d
# via -r ci/requirements.freethreading.in
sortedcontainers==2.4.0 \
--hash=sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88 \
--hash=sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0
# via hypothesis
typing-extensions==4.12.2 \
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
# via mypy
wheel==0.44.0 \
--hash=sha256:2376a90c98cc337d18623527a97c31797bd02bad0033d41547043a1cbfbe448f \
--hash=sha256:a29c3f2817e95ab89aa4660681ad547c0e9547f20e75b0562fe7723c9a2a9d49
# via -r ci/requirements.freethreading.in
7 changes: 6 additions & 1 deletion docs/installing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ One way to do this is to depend on the ``zstandard[cffi]`` dependency.
e.g. ``pip install 'zstandard[cffi]'`` or add ``zstandard[cffi]`` to your
pip requirements file.

CFFI does not yet support the free-threaded build of CPython so the CFFI
backend is disabled at build time for free-threaded Python regardless of
whether or not the ``cffi`` is specified.

Legacy Format Support
=====================

Expand Down Expand Up @@ -84,7 +88,8 @@ All Install Arguments
Do not compile the CFFI-based backend.

``--rust-backend``
Compile the Rust backend (not yet feature complete).
Compile the Rust backend (not yet feature complete and not supported
on the free-threaded build or Python 3.13).

If you invoke ``setup.py``, simply pass the aforementioned arguments. e.g.
``python3.9 setup.py --no-cffi-backend``. If using ``pip``, use the
Expand Down
37 changes: 21 additions & 16 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import os
import platform
import sys
import sysconfig

from setuptools import setup

Expand All @@ -36,7 +37,6 @@

ext_suffix = os.environ.get("SETUPTOOLS_EXT_SUFFIX")
if ext_suffix:
import sysconfig
# setuptools._distutils.command.build_ext doesn't use
# SETUPTOOLS_EXT_SUFFIX like setuptools.command.build_ext does.
# Work around the issue so that cross-compilation can work
Expand All @@ -55,22 +55,27 @@
if py39compat:
py39compat.add_ext_suffix = lambda vars: None

try:
import cffi

# PyPy (and possibly other distros) have CFFI distributed as part of
# them.
cffi_version = LooseVersion(cffi.__version__)
if cffi_version < LooseVersion(MINIMUM_CFFI_VERSION):
print(
"CFFI %s or newer required (%s found); "
"not building CFFI backend" % (MINIMUM_CFFI_VERSION, cffi_version),
file=sys.stderr,
)
cffi = None

except ImportError:
if bool(sysconfig.get_config_var("Py_GIL_DISABLED")):
# cffi does not yet support the free-threaded build so we
# disable the cffi backend
cffi = None
else:
try:
import cffi

# PyPy (and possibly other distros) have CFFI distributed as part of
# them.
cffi_version = LooseVersion(cffi.__version__)
if cffi_version < LooseVersion(MINIMUM_CFFI_VERSION):
print(
"CFFI %s or newer required (%s found); "
"not building CFFI backend" % (MINIMUM_CFFI_VERSION, cffi_version),
file=sys.stderr,
)
cffi = None

except ImportError:
cffi = None

sys.path.insert(0, ".")

Expand Down
3 changes: 3 additions & 0 deletions tests/test_compressor_fuzzing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import os
import unittest

import pytest
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these imports and the comment can probably be reverted as well @ngoldbaum



try:
import hypothesis
import hypothesis.strategies as strategies
Expand Down
3 changes: 3 additions & 0 deletions tests/test_data_structures_fuzzing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import os
import unittest

import pytest


try:
import hypothesis
import hypothesis.strategies as strategies
Expand Down
3 changes: 2 additions & 1 deletion tests/test_decompressor_fuzzing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import io
import os
import unittest
import pytest

try:
import hypothesis
Expand Down Expand Up @@ -531,7 +532,7 @@ def test_random_output_sizes(
),
read_sizes=strategies.data(),
)
def test_read_across_frames_false(
def test_read_across_frames_false( # fails
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, how does this fail in free-threaded mode?

self, chunks, level, write_size, read_sizes
):
cctx = zstd.ZstdCompressor(level=level)
Expand Down