Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
db77ad5
Git-ignore pytest cache folders
agriyakhetarpal Apr 24, 2024
22cede6
Refine outdated sections for Contributing guide
agriyakhetarpal Apr 24, 2024
3c2b0be
Add patch to disable threading and multiprocessing
agriyakhetarpal Apr 24, 2024
a8c956f
Add patch to embed missing POSIX syscall headers
agriyakhetarpal Apr 24, 2024
8769743
Add initial workflow to run + debug Pyodide builds
agriyakhetarpal Apr 24, 2024
28674c3
Disable AVX2 and SSE2 instructions
agriyakhetarpal Apr 24, 2024
f6df488
Use separate build and test jobs and share wheel
agriyakhetarpal Apr 24, 2024
d678be8
Add patch that allows loading `.npy` files
agriyakhetarpal Apr 24, 2024
6ce4127
Apply patch for Emscripten to load `.npy` files
agriyakhetarpal Apr 24, 2024
199928d
Add a constant to check if platform is WASM
agriyakhetarpal Apr 24, 2024
1f5e7b7
Use `is_wasm` to disable multiprocessing tests
agriyakhetarpal Apr 24, 2024
da909f8
Apply `.npy` files patch again when running tests
agriyakhetarpal Apr 24, 2024
a54c555
Remove patch that is unneeded at build time
agriyakhetarpal May 21, 2024
494dd2f
Merge branch 'main' into setup-emscripten-ci
agriyakhetarpal Nov 7, 2024
a7446c8
Delete patch that's not needed now
agriyakhetarpal Nov 7, 2024
9271054
Ignore Pyodide cross-build environment files
agriyakhetarpal Nov 7, 2024
764f34e
Revamp workflow and clean up changes
agriyakhetarpal Nov 7, 2024
d41f75f
Fix linter errors and style failures
agriyakhetarpal Nov 7, 2024
ee39d1e
Catch and disable `mutex` assignment
agriyakhetarpal Nov 7, 2024
731c6b2
Fix patch that disables multiprocessing, threading
agriyakhetarpal Nov 7, 2024
0616dd5
Don't hardcode `zlib` paths in patch details
agriyakhetarpal Nov 7, 2024
1aa838b
Install test + runtime extras, disable pytest cache
agriyakhetarpal Nov 7, 2024
0638a91
Fix shell expansion in installation command
agriyakhetarpal Nov 7, 2024
53f2096
Temporary: skip tests that require crc32c
agriyakhetarpal Nov 8, 2024
7133abb
Merge branch 'main' into setup-emscripten-ci
agriyakhetarpal Nov 8, 2024
bc9b6dc
Temporary: skip `crc32c` dependency until available
agriyakhetarpal Nov 8, 2024
5a4e234
Update ci-emscripten.yaml
agriyakhetarpal Nov 8, 2024
4ce9e4d
Fix zarr installation order to collect more tests
agriyakhetarpal Nov 8, 2024
d6c43ef
Force install zarr version 3 for CI
agriyakhetarpal Nov 8, 2024
55a2690
Skip a test that requires threads
agriyakhetarpal Nov 8, 2024
9a0482b
Temporary: skip Zarr's async functionality tests
agriyakhetarpal Nov 8, 2024
bf42491
Guard import of `multiprocessing`
agriyakhetarpal Nov 8, 2024
9924e8e
Revert "Guard import of `multiprocessing`"
agriyakhetarpal Nov 8, 2024
0847241
Bump verbosity when running test suite
agriyakhetarpal Nov 8, 2024
b6713ca
Skip codec entrypoint test that requires processes
agriyakhetarpal Nov 8, 2024
a590785
Let `pytest` inherit config for doctests
agriyakhetarpal Nov 8, 2024
3e1a968
Revert "Let `pytest` inherit config for doctests"
agriyakhetarpal Nov 8, 2024
e4f6670
Ignore a doctest that uses threads within the file
agriyakhetarpal Nov 8, 2024
4c348f2
Merge `main`
agriyakhetarpal Jan 1, 2025
dacbd09
Fix skip reason error message for entrypoint test
agriyakhetarpal Jan 1, 2025
6caf076
`crc32c` >=2.7 is now available with Pyodide 0.27.0
agriyakhetarpal Jan 1, 2025
85252f4
Bump to Pyodide version 0.27.0
agriyakhetarpal Jan 1, 2025
6b8d139
Clean up changes
agriyakhetarpal Jan 1, 2025
8aee545
Merge branch 'main' into setup-emscripten-ci
agriyakhetarpal Feb 18, 2025
c3e346a
Bring back code-style quoting
agriyakhetarpal Feb 18, 2025
2e0e759
Update to Pyodide 0.27.3, add `pcodec`
agriyakhetarpal Feb 26, 2025
4e6f2b6
Fix drop in coverage
agriyakhetarpal Feb 27, 2025
1cf2c6b
Fix another drop in coverage
agriyakhetarpal Mar 1, 2025
6d06a8b
Merge branch 'main' into setup-emscripten-ci
agriyakhetarpal Mar 3, 2025
1d92260
Don't add `pthread` for Emscripten
agriyakhetarpal Mar 3, 2025
c807e08
Get version properly using `fetch-tags: true`
agriyakhetarpal Mar 3, 2025
3b82940
Add CHANGELOG entry for Pyodide builds
agriyakhetarpal Mar 3, 2025
9fc8add
Wait for Git 2.48.1 for using `fetch-tags: true`
agriyakhetarpal Mar 3, 2025
d8f70b4
Merge main
agriyakhetarpal Apr 15, 2025
3821a31
Merge main
agriyakhetarpal May 22, 2025
df17500
Ensure reliability of builds and tests
agriyakhetarpal May 22, 2025
902fdf3
`zfpy` is now available in Pyodide
agriyakhetarpal May 22, 2025
89e8b04
`zarr3` should also work now
agriyakhetarpal May 22, 2025
ae74d0b
Ignoring Pyodide xbuildenv is no longer needed
agriyakhetarpal May 22, 2025
34f1fc2
Bump to Pyodide 0.27.6, and Node 22
agriyakhetarpal May 22, 2025
5100f07
Merge main*
agriyakhetarpal May 15, 2026
476b3b6
Modernise Emscripten workflow, build for 2026 ABI
agriyakhetarpal May 15, 2026
4abeba6
Fall back to `numpy.get_include()` for WASM
agriyakhetarpal May 15, 2026
e2e3c0a
Add Pyodide-related config for cibuildwheel
agriyakhetarpal May 15, 2026
3465696
Fix `is_wasm` import
agriyakhetarpal May 15, 2026
fceaf95
Skip pcodec tests
agriyakhetarpal May 15, 2026
fd25497
Use `pytest.importorskip`, more modern test skips
agriyakhetarpal May 15, 2026
6fb3dc4
xfail two tests with size overflows for now
agriyakhetarpal May 15, 2026
c4e72e2
Try to emit zarr3 deprecation warnings
agriyakhetarpal May 15, 2026
a70c8b5
Fix zfpy and lzma skips
agriyakhetarpal May 15, 2026
bb82f26
Wrong tag is getting picked up, fetch-depth needed
agriyakhetarpal May 15, 2026
e6febbe
Remove workaround for deprecation warnings
agriyakhetarpal May 15, 2026
fc55eff
Streaming decompression tests pass now
agriyakhetarpal May 15, 2026
7698453
Discard changes to tests/test_zfpy.py
agriyakhetarpal May 15, 2026
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
31 changes: 31 additions & 0 deletions .github/workflows/ci-emscripten.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Tests on Pyodide

on: [push, pull_request]

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

permissions: {}

jobs:
build:
name: Build numcodecs WASM distribution
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: recursive
fetch-depth: 0
# https://github.com/actions/checkout/issues/2041 isn't released yet
# fetch-tags: true # required for version resolution

# TODO: build for Pyodide 314.0.0 stable when released and added to cibuildwheel
# hopefully this will happen for us in sync with cibuildwheel v4.0.0 stable as well
- name: Build and test numcodecs for Pyodide
uses: pypa/cibuildwheel@54327ab9d35de03b359ac25c97de9417d94639c0 # v4.0.0rc1
env:
CIBW_ENABLE: pyodide-prerelease
with:
only: cp314-pyodide_wasm32
4 changes: 3 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ jobs:
uses: actions/checkout@v5
with:
submodules: recursive
fetch-depth: 0 # required for version resolution
fetch-depth: 0
# https://github.com/actions/checkout/issues/2041 isn't released yet
# fetch-tags: true # required for version resolution

- name: Set up Python
uses: actions/setup-python@v6
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ coverage.xml
*,cover
.hypothesis/
cover/
.pytest_cache/


# Translations
Expand Down Expand Up @@ -99,4 +100,4 @@ ENV/
.pixi/*
*.egg-info
pixi.lock
uv.lock
uv.lock
14 changes: 13 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ py = import('python').find_installation(pure: false)
cc = meson.get_compiler('c')

# NumPy include directory (needed for vlen extension)
numpy_dep = dependency('numpy')
# When cross-compiling for Emscripten/WASM, numpy-config is not available on
# the target because of https://github.com/pyodide/pyodide-build/pull/21, so
# we have tofall back to finding headers.
if host_machine.cpu_family() == 'wasm32'
_numpy_inc = run_command(
find_program('python', native: true),
['-c', 'import numpy; print(numpy.get_include())'],
check: true,
).stdout().strip()
numpy_dep = declare_dependency(include_directories: include_directories(_numpy_inc))
else
numpy_dep = dependency('numpy')
endif

subdir('src/numcodecs')
17 changes: 17 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,23 @@ config-settings = "setup-args=-Davx2=disabled"
select = "*-macosx_arm64"
config-settings = {setup-args = ["-Davx2=disabled", "-Dsse2=disabled"]}

[[tool.cibuildwheel.overrides]]
select = "*-pyodide_wasm32"
before-build = "patch -p1 < tools/ci/patches/0001-disable-multiprocessing-and-pthreads.patch && patch -p1 < tools/ci/patches/0002-add-missing-unistd-headers.patch -d c-blosc/internal-complibs/zlib-1.3.1/"
config-settings = {setup-args = ["-Dsse2=disabled", "-Davx2=disabled"]}
test-requires = [
"pytest",
# "pytest-cov",
# "pyzstd", # TODO: add back once Pyodide 314.0.0 stable includes compression.zstd builtin
"msgpack",
"crc32c",
"zfpy",
"zarr>=3",
"importlib_metadata",
]
# Override addopts over to speed up test suite and not run coverage
test-command = "python -m pytest -p no:cacheprovider --override-ini=addopts= -svra {project}/tests"

[tool.ruff]
line-length = 100
extend-exclude = ["c-blosc"]
Expand Down
2 changes: 2 additions & 0 deletions src/numcodecs/blosc.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ def get_mutex():
mutex = None
except ImportError:
mutex = None
except ModuleNotFoundError:
mutex = None
_MUTEX = mutex
_MUTEX_IS_INIT = True
return _MUTEX
Expand Down
4 changes: 4 additions & 0 deletions tests/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import array
import json as _json
import os
import platform
import sys
import warnings
from glob import glob

Expand All @@ -27,6 +29,8 @@
'เฮลโลเวิลด์',
]

is_wasm = (sys.platform == 'emscripten') or (platform.machine() in ['wasm32', 'wasm64'])


def compare_arrays(arr, res, precision=None):
# ensure numpy array with matching dtype
Expand Down
13 changes: 5 additions & 8 deletions tests/test_blosc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,19 @@
import numpy as np
import pytest

try:
from numcodecs.blosc import Blosc

from numcodecs import blosc
except ImportError: # pragma: no cover
pytest.skip("numcodecs.blosc not available", allow_module_level=True)


from tests.common import (
check_backwards_compatibility,
check_config,
check_encode_decode,
check_err_decode_object_buffer,
check_err_encode_object_buffer,
check_max_buffer_size,
is_wasm,
)

blosc = pytest.importorskip("numcodecs.blosc")
Blosc = blosc.Blosc

codecs = [
Blosc(shuffle=Blosc.SHUFFLE),
Blosc(clevel=0, shuffle=Blosc.SHUFFLE),
Expand Down Expand Up @@ -210,6 +206,7 @@ def _decode_worker(enc):
return compressor.decode(enc)


@pytest.mark.skipif(is_wasm, reason="WASM/Pyodide does not support multiprocessing")
@pytest.mark.parametrize('pool', [Pool, ThreadPool])
def test_multiprocessing(use_threads, pool):
data = np.arange(1000000)
Expand Down
2 changes: 2 additions & 0 deletions tests/test_entrypoints_backport.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest

import numcodecs.registry
from tests.common import is_wasm

importlib_spec = importlib.util.find_spec("importlib_metadata")
if importlib_spec is None or importlib_spec.loader is None: # pragma: no cover
Expand All @@ -29,6 +30,7 @@ def get_entrypoints_with_importlib_metadata_loaded():
assert cls.codec_id == "test"


@pytest.mark.skipif(is_wasm, reason="Spawning processes is not supported in Pyodide/WASM")
def test_entrypoint_codec_with_importlib_metadata():
p = Process(target=get_entrypoints_with_importlib_metadata_loaded)
p.start()
Expand Down
8 changes: 2 additions & 6 deletions tests/test_lz4.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@
import numpy as np
import pytest

try:
from numcodecs.lz4 import LZ4
except ImportError: # pragma: no cover
pytest.skip("numcodecs.lz4 not available", allow_module_level=True)


from tests.common import (
check_backwards_compatibility,
check_config,
Expand All @@ -19,6 +13,8 @@
check_repr,
)

LZ4 = pytest.importorskip("numcodecs.lz4").LZ4

codecs = [
LZ4(),
LZ4(acceleration=-1),
Expand Down
11 changes: 3 additions & 8 deletions tests/test_lzma.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import itertools
import unittest
from types import ModuleType
from typing import cast

import numpy as np
import pytest

try:
# noinspection PyProtectedMember
from numcodecs.lzma import LZMA, _lzma
except ImportError as e: # pragma: no cover
raise unittest.SkipTest("LZMA not available") from e


from tests.common import (
check_backwards_compatibility,
check_config,
Expand All @@ -22,6 +14,9 @@
check_repr,
)

pytest.importorskip("lzma")
from numcodecs.lzma import LZMA, _lzma

_lzma = cast(ModuleType, _lzma)

codecs = [
Expand Down
10 changes: 2 additions & 8 deletions tests/test_msgpacks.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import unittest

import numpy as np
import pytest

try:
from numcodecs.msgpacks import MsgPack
except ImportError as e: # pragma: no cover
raise unittest.SkipTest("msgpack not available") from e


from tests.common import (
check_backwards_compatibility,
check_config,
Expand All @@ -17,6 +9,8 @@
greetings,
)

MsgPack = pytest.importorskip("numcodecs.msgpacks").MsgPack

# object array with strings
# object array with mix strings / nans
# object array with mix of string, int, float
Expand Down
9 changes: 4 additions & 5 deletions tests/test_pcodec.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import numpy as np
import pytest

try:
from numcodecs.pcodec import PCodec
except ImportError: # pragma: no cover
pytest.skip("pcodec not available", allow_module_level=True)

from tests.common import (
check_backwards_compatibility,
check_config,
Expand All @@ -15,6 +10,10 @@
check_repr,
)

# pcodec is not installed in the Pyodide CI environment because Pyodide ships
# pcodec>=1.0, which has an incompatible API with what we require, i.e., <0.4.
PCodec = pytest.importorskip("numcodecs.pcodec").PCodec

codecs = [
PCodec(),
PCodec(level=1),
Expand Down
4 changes: 3 additions & 1 deletion tests/test_pyzstd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import numpy as np
import pytest
import pyzstd
from numcodecs.zstd import Zstd

pyzstd = pytest.importorskip("pyzstd")


test_data = [
b"Hello World!",
np.arange(113).tobytes(),
Expand Down
10 changes: 4 additions & 6 deletions tests/test_shuffle.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,15 @@
import numpy as np
import pytest

try:
from numcodecs.shuffle import Shuffle
except ImportError: # pragma: no cover
pytest.skip("numcodecs.shuffle not available", allow_module_level=True)


from tests.common import (
check_backwards_compatibility,
check_config,
check_encode_decode,
is_wasm,
)

Shuffle = pytest.importorskip("numcodecs.shuffle").Shuffle

codecs = [
Shuffle(),
Shuffle(elementsize=0),
Expand Down Expand Up @@ -87,6 +84,7 @@ def _decode_worker(enc):
return compressor.decode(enc)


@pytest.mark.skipif(is_wasm, reason="WASM/Pyodide does not support multiprocessing")
@pytest.mark.parametrize('pool', [Pool, ThreadPool])
def test_multiprocessing(pool):
data = np.arange(1000000)
Expand Down
8 changes: 2 additions & 6 deletions tests/test_vlen_array.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import unittest

import numpy as np
import pytest

try:
from numcodecs.vlen import VLenArray
except ImportError as e: # pragma: no cover
raise unittest.SkipTest("vlen-array not available") from e
from tests.common import (
assert_array_items_equal,
check_backwards_compatibility,
Expand All @@ -15,6 +9,8 @@
check_repr,
)

VLenArray = pytest.importorskip("numcodecs.vlen").VLenArray

arrays = [
np.array([np.array([1, 2, 3]), np.array([4]), np.array([5, 6])] * 300, dtype=object),
np.array([np.array([1, 2, 3]), np.array([4]), np.array([5, 6])] * 300, dtype=object).reshape(
Expand Down
8 changes: 2 additions & 6 deletions tests/test_vlen_bytes.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import unittest

import numpy as np
import pytest

try:
from numcodecs.vlen import VLenBytes
except ImportError as e: # pragma: no cover
raise unittest.SkipTest("vlen-bytes not available") from e
from tests.common import (
assert_array_items_equal,
check_backwards_compatibility,
Expand All @@ -16,6 +10,8 @@
greetings,
)

VLenBytes = pytest.importorskip("numcodecs.vlen").VLenBytes

greetings_bytes = [g.encode('utf-8') for g in greetings]


Expand Down
8 changes: 2 additions & 6 deletions tests/test_vlen_utf8.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import unittest

import numpy as np
import pytest

try:
from numcodecs.vlen import VLenUTF8
except ImportError as e: # pragma: no cover
raise unittest.SkipTest("vlen-utf8 not available") from e
from tests.common import (
assert_array_items_equal,
check_backwards_compatibility,
Expand All @@ -16,6 +10,8 @@
greetings,
)

VLenUTF8 = pytest.importorskip("numcodecs.vlen").VLenUTF8

arrays = [
np.array(['foo', 'bar', 'baz'] * 300, dtype=object),
np.array(greetings * 100, dtype=object),
Expand Down
Loading
Loading