numcodecs 0.13.1__cp313-cp313-macosx_10_13_x86_64.whl → 0.14.0__cp313-cp313-macosx_10_13_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of numcodecs might be problematic. Click here for more details.

Files changed (45) hide show
  1. numcodecs/__init__.py +9 -7
  2. numcodecs/_shuffle.cpython-313-darwin.so +0 -0
  3. numcodecs/abc.py +2 -1
  4. numcodecs/bitround.py +2 -1
  5. numcodecs/blosc.cpython-313-darwin.so +0 -0
  6. numcodecs/checksum32.py +86 -10
  7. numcodecs/compat.py +2 -4
  8. numcodecs/compat_ext.cpython-313-darwin.so +0 -0
  9. numcodecs/delta.py +5 -1
  10. numcodecs/fletcher32.cpython-313-darwin.so +0 -0
  11. numcodecs/jenkins.cpython-313-darwin.so +0 -0
  12. numcodecs/lz4.cpython-313-darwin.so +0 -0
  13. numcodecs/lzma.py +5 -2
  14. numcodecs/ndarray_like.py +1 -1
  15. numcodecs/packbits.py +0 -3
  16. numcodecs/registry.py +9 -8
  17. numcodecs/tests/test_bitround.py +3 -3
  18. numcodecs/tests/test_blosc.py +2 -2
  19. numcodecs/tests/test_checksum32.py +98 -18
  20. numcodecs/tests/test_compat.py +3 -0
  21. numcodecs/tests/test_delta.py +1 -0
  22. numcodecs/tests/test_entrypoints.py +1 -1
  23. numcodecs/tests/test_entrypoints_backport.py +3 -2
  24. numcodecs/tests/test_fixedscaleoffset.py +13 -5
  25. numcodecs/tests/test_json.py +1 -1
  26. numcodecs/tests/test_lzma.py +4 -0
  27. numcodecs/tests/test_msgpacks.py +4 -1
  28. numcodecs/tests/test_pcodec.py +1 -1
  29. numcodecs/tests/test_registry.py +12 -10
  30. numcodecs/tests/test_shuffle.py +3 -3
  31. numcodecs/tests/test_zarr3.py +248 -0
  32. numcodecs/tests/test_zarr3_import.py +13 -0
  33. numcodecs/tests/test_zfpy.py +6 -0
  34. numcodecs/version.py +2 -2
  35. numcodecs/vlen.cpython-313-darwin.so +0 -0
  36. numcodecs/zarr3.py +379 -0
  37. numcodecs/zfpy.py +4 -2
  38. numcodecs/zstd.cpython-313-darwin.so +0 -0
  39. {numcodecs-0.13.1.dist-info → numcodecs-0.14.0.dist-info}/METADATA +6 -4
  40. numcodecs-0.14.0.dist-info/RECORD +78 -0
  41. {numcodecs-0.13.1.dist-info → numcodecs-0.14.0.dist-info}/WHEEL +1 -1
  42. numcodecs-0.14.0.dist-info/entry_points.txt +22 -0
  43. numcodecs-0.13.1.dist-info/RECORD +0 -74
  44. {numcodecs-0.13.1.dist-info → numcodecs-0.14.0.dist-info}/LICENSE.txt +0 -0
  45. {numcodecs-0.13.1.dist-info → numcodecs-0.14.0.dist-info}/top_level.txt +0 -0
numcodecs/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- # ruff: noqa: E402,F401
1
+ # ruff: noqa: E402
2
2
  """Numcodecs is a Python package providing buffer compression and
3
3
  transformation codecs for use in data storage and communication
4
4
  applications. These include:
@@ -21,8 +21,9 @@ import atexit
21
21
  import multiprocessing
22
22
  from contextlib import suppress
23
23
 
24
- from numcodecs.registry import get_codec, register_codec
25
- from numcodecs.version import version as __version__
24
+ from numcodecs.registry import get_codec as get_codec
25
+ from numcodecs.registry import register_codec
26
+ from numcodecs.version import version as __version__ # noqa: F401
26
27
  from numcodecs.zlib import Zlib
27
28
 
28
29
  register_codec(Zlib)
@@ -55,13 +56,13 @@ with suppress(ImportError):
55
56
  atexit.register(blosc.destroy)
56
57
 
57
58
  with suppress(ImportError):
58
- from numcodecs import zstd
59
+ from numcodecs import zstd as zstd
59
60
  from numcodecs.zstd import Zstd
60
61
 
61
62
  register_codec(Zstd)
62
63
 
63
64
  with suppress(ImportError):
64
- from numcodecs import lz4
65
+ from numcodecs import lz4 as lz4
65
66
  from numcodecs.lz4 import LZ4
66
67
 
67
68
  register_codec(LZ4)
@@ -116,9 +117,10 @@ with suppress(ImportError):
116
117
 
117
118
  register_codec(MsgPack)
118
119
 
119
- from numcodecs.checksum32 import CRC32, Adler32, JenkinsLookup3
120
+ from numcodecs.checksum32 import CRC32, CRC32C, Adler32, JenkinsLookup3
120
121
 
121
122
  register_codec(CRC32)
123
+ register_codec(CRC32C)
122
124
  register_codec(Adler32)
123
125
  register_codec(JenkinsLookup3)
124
126
 
@@ -127,7 +129,7 @@ from numcodecs.json import JSON
127
129
  register_codec(JSON)
128
130
 
129
131
  with suppress(ImportError):
130
- from numcodecs import vlen
132
+ from numcodecs import vlen as vlen
131
133
  from numcodecs.vlen import VLenArray, VLenBytes, VLenUTF8
132
134
 
133
135
  register_codec(VLenUTF8)
Binary file
numcodecs/abc.py CHANGED
@@ -29,13 +29,14 @@ other and vice versa.
29
29
  """
30
30
 
31
31
  from abc import ABC, abstractmethod
32
+ from typing import Optional
32
33
 
33
34
 
34
35
  class Codec(ABC):
35
36
  """Codec abstract base class."""
36
37
 
37
38
  # override in sub-class
38
- codec_id = None
39
+ codec_id: Optional[str] = None
39
40
  """Codec identifier."""
40
41
 
41
42
  @abstractmethod
numcodecs/bitround.py CHANGED
@@ -59,7 +59,8 @@ class BitRound(Codec):
59
59
  return a
60
60
  if self.keepbits > bits:
61
61
  raise ValueError("Keepbits too large for given dtype")
62
- b = a.view(a_int_dtype)
62
+ b = a.copy()
63
+ b = b.view(a_int_dtype)
63
64
  maskbits = bits - self.keepbits
64
65
  mask = (all_set >> maskbits) << maskbits
65
66
  half_quantum1 = (1 << (maskbits - 1)) - 1
Binary file
numcodecs/checksum32.py CHANGED
@@ -1,5 +1,7 @@
1
1
  import struct
2
2
  import zlib
3
+ from collections.abc import Callable
4
+ from typing import TYPE_CHECKING, Literal
3
5
 
4
6
  import numpy as np
5
7
 
@@ -7,36 +9,107 @@ from .abc import Codec
7
9
  from .compat import ensure_contiguous_ndarray, ndarray_copy
8
10
  from .jenkins import jenkins_lookup3
9
11
 
12
+ if TYPE_CHECKING:
13
+ from typing_extensions import Buffer
14
+
15
+ CHECKSUM_LOCATION = Literal['start', 'end']
16
+
10
17
 
11
18
  class Checksum32(Codec):
12
19
  # override in sub-class
13
- checksum = None
20
+ checksum: Callable[["Buffer", int], int] | None = None
21
+ location: CHECKSUM_LOCATION = 'start'
22
+
23
+ def __init__(self, location: CHECKSUM_LOCATION | None = None):
24
+ if location is not None:
25
+ self.location = location
26
+ if self.location not in ['start', 'end']:
27
+ raise ValueError(f"Invalid checksum location: {self.location}")
14
28
 
15
29
  def encode(self, buf):
16
30
  arr = ensure_contiguous_ndarray(buf).view('u1')
17
31
  checksum = self.checksum(arr) & 0xFFFFFFFF
18
32
  enc = np.empty(arr.nbytes + 4, dtype='u1')
19
- enc[:4].view('<u4')[0] = checksum
20
- ndarray_copy(arr, enc[4:])
33
+ if self.location == 'start':
34
+ checksum_view = enc[:4]
35
+ payload_view = enc[4:]
36
+ else:
37
+ checksum_view = enc[-4:]
38
+ payload_view = enc[:-4]
39
+ checksum_view.view('<u4')[0] = checksum
40
+ ndarray_copy(arr, payload_view)
21
41
  return enc
22
42
 
23
43
  def decode(self, buf, out=None):
44
+ if len(buf) < 4:
45
+ raise ValueError("Input buffer is too short to contain a 32-bit checksum.")
46
+ if out is not None:
47
+ ensure_contiguous_ndarray(out) # check that out is a valid ndarray
48
+
24
49
  arr = ensure_contiguous_ndarray(buf).view('u1')
25
- expect = arr[:4].view('<u4')[0]
26
- checksum = self.checksum(arr[4:]) & 0xFFFFFFFF
50
+ if self.location == 'start':
51
+ checksum_view = arr[:4]
52
+ payload_view = arr[4:]
53
+ else:
54
+ checksum_view = arr[-4:]
55
+ payload_view = arr[:-4]
56
+ expect = checksum_view.view('<u4')[0]
57
+ checksum = self.checksum(payload_view) & 0xFFFFFFFF
27
58
  if expect != checksum:
28
- raise RuntimeError('checksum failed')
29
- return ndarray_copy(arr[4:], out)
59
+ raise RuntimeError(
60
+ f"Stored and computed {self.codec_id} checksum do not match. Stored: {expect}. Computed: {checksum}."
61
+ )
62
+ return ndarray_copy(payload_view, out)
30
63
 
31
64
 
32
65
  class CRC32(Checksum32):
66
+ """Codec add a crc32 checksum to the buffer.
67
+
68
+ Parameters
69
+ ----------
70
+ location : 'start' or 'end'
71
+ Where to place the checksum in the buffer.
72
+ """
73
+
33
74
  codec_id = 'crc32'
34
75
  checksum = zlib.crc32
76
+ location = 'start'
77
+
78
+
79
+ class CRC32C(Checksum32):
80
+ """Codec add a crc32c checksum to the buffer.
81
+
82
+ Parameters
83
+ ----------
84
+ location : 'start' or 'end'
85
+ Where to place the checksum in the buffer.
86
+ """
87
+
88
+ codec_id = 'crc32c'
89
+
90
+ def checksum(self, buf):
91
+ try:
92
+ from crc32c import crc32c as crc32c_
93
+
94
+ return crc32c_(buf)
95
+ except ImportError: # pragma: no cover
96
+ raise ImportError("crc32c must be installed to use the CRC32C checksum codec.")
97
+
98
+ location = 'end'
35
99
 
36
100
 
37
101
  class Adler32(Checksum32):
102
+ """Codec add a adler32 checksum to the buffer.
103
+
104
+ Parameters
105
+ ----------
106
+ location : 'start' or 'end'
107
+ Where to place the checksum in the buffer.
108
+ """
109
+
38
110
  codec_id = 'adler32'
39
111
  checksum = zlib.adler32
112
+ location = 'start'
40
113
 
41
114
 
42
115
  class JenkinsLookup3(Checksum32):
@@ -50,9 +123,12 @@ class JenkinsLookup3(Checksum32):
50
123
  the data portion and compared with the four-byte checksum, raising
51
124
  RuntimeError if inconsistent.
52
125
 
53
- Attributes:
54
- initval: initial seed passed to the hash algorithm, default: 0
55
- prefix: bytes prepended to the buffer before evaluating the hash, default: None
126
+ Parameters
127
+ ----------
128
+ initval : int
129
+ initial seed passed to the hash algorithm, default: 0
130
+ prefix : int
131
+ bytes prepended to the buffer before evaluating the hash, default: None
56
132
  """
57
133
 
58
134
  checksum = jenkins_lookup3
numcodecs/compat.py CHANGED
@@ -1,7 +1,5 @@
1
- # ruff: noqa: F401
2
1
  import array
3
2
  import codecs
4
- import functools
5
3
 
6
4
  import numpy as np
7
5
 
@@ -102,7 +100,7 @@ def ensure_contiguous_ndarray_like(buf, max_buffer_size=None, flatten=True) -> N
102
100
 
103
101
  # check for datetime or timedelta ndarray, the buffer interface doesn't support those
104
102
  if arr.dtype.kind in "Mm":
105
- arr = arr.view(np.int64)
103
+ arr = arr.view(np.int64) # type: ignore[arg-type]
106
104
 
107
105
  # check memory is contiguous, if so flatten
108
106
  if arr.flags.c_contiguous or arr.flags.f_contiguous:
@@ -119,7 +117,7 @@ def ensure_contiguous_ndarray_like(buf, max_buffer_size=None, flatten=True) -> N
119
117
  return arr
120
118
 
121
119
 
122
- def ensure_contiguous_ndarray(buf, max_buffer_size=None, flatten=True) -> np.array:
120
+ def ensure_contiguous_ndarray(buf, max_buffer_size=None, flatten=True) -> np.ndarray:
123
121
  """Convenience function to coerce `buf` to a numpy array, if it is not already a
124
122
  numpy array. Also ensures that the returned value exports fully contiguous memory,
125
123
  and supports the new-style buffer interface. If the optional max_buffer_size is
Binary file
numcodecs/delta.py CHANGED
@@ -63,7 +63,11 @@ class Delta(Codec):
63
63
  enc[0] = arr[0]
64
64
 
65
65
  # compute differences
66
- enc[1:] = np.diff(arr)
66
+ # using np.subtract for in-place operations
67
+ if arr.dtype == bool:
68
+ np.not_equal(arr[1:], arr[:-1], out=enc[1:])
69
+ else:
70
+ np.subtract(arr[1:], arr[:-1], out=enc[1:])
67
71
 
68
72
  return enc
69
73
 
Binary file
Binary file
Binary file
numcodecs/lzma.py CHANGED
@@ -1,9 +1,12 @@
1
- _lzma = None
1
+ from types import ModuleType
2
+ from typing import Optional
3
+
4
+ _lzma: Optional[ModuleType] = None
2
5
  try:
3
6
  import lzma as _lzma
4
7
  except ImportError: # pragma: no cover
5
8
  try:
6
- from backports import lzma as _lzma
9
+ from backports import lzma as _lzma # type: ignore[no-redef]
7
10
  except ImportError:
8
11
  pass
9
12
 
numcodecs/ndarray_like.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from typing import Any, ClassVar, Optional, Protocol, runtime_checkable
2
2
 
3
3
 
4
- class _CachedProtocolMeta(Protocol.__class__):
4
+ class _CachedProtocolMeta(Protocol.__class__): # type: ignore[name-defined]
5
5
  """Custom implementation of @runtime_checkable
6
6
 
7
7
  The native implementation of @runtime_checkable is slow,
numcodecs/packbits.py CHANGED
@@ -29,9 +29,6 @@ class PackBits(Codec):
29
29
 
30
30
  codec_id = 'packbits'
31
31
 
32
- def __init__(self):
33
- pass
34
-
35
32
  def encode(self, buf):
36
33
  # normalise input
37
34
  arr = ensure_ndarray(buf).view(bool)
numcodecs/registry.py CHANGED
@@ -2,11 +2,13 @@
2
2
  applications to dynamically register and look-up codec classes."""
3
3
 
4
4
  import logging
5
- from importlib.metadata import entry_points
5
+ from importlib.metadata import EntryPoints, entry_points
6
+
7
+ from numcodecs.abc import Codec
6
8
 
7
9
  logger = logging.getLogger("numcodecs")
8
- codec_registry = {}
9
- entries = {}
10
+ codec_registry: dict[str, Codec] = {}
11
+ entries: dict[str, "EntryPoints"] = {}
10
12
 
11
13
 
12
14
  def run_entrypoints():
@@ -42,11 +44,10 @@ def get_codec(config):
42
44
  config = dict(config)
43
45
  codec_id = config.pop('id', None)
44
46
  cls = codec_registry.get(codec_id)
45
- if cls is None:
46
- if codec_id in entries:
47
- logger.debug("Auto loading codec '%s' from entrypoint", codec_id)
48
- cls = entries[codec_id].load()
49
- register_codec(cls, codec_id=codec_id)
47
+ if cls is None and codec_id in entries:
48
+ logger.debug("Auto loading codec '%s' from entrypoint", codec_id)
49
+ cls = entries[codec_id].load()
50
+ register_codec(cls, codec_id=codec_id)
50
51
  if cls:
51
52
  return cls.from_config(config)
52
53
  raise ValueError(f'codec not available: {codec_id!r}')
@@ -24,21 +24,21 @@ def test_round_zero_to_zero(dtype):
24
24
  # Don't understand Milan's original test:
25
25
  # How is it possible to have negative keepbits?
26
26
  # for k in range(-5, 50):
27
- for k in range(0, max_bits[dtype]):
27
+ for k in range(max_bits[dtype]):
28
28
  ar = round(a, k)
29
29
  np.testing.assert_equal(a, ar)
30
30
 
31
31
 
32
32
  def test_round_one_to_one(dtype):
33
33
  a = np.ones((3, 2), dtype=dtype)
34
- for k in range(0, max_bits[dtype]):
34
+ for k in range(max_bits[dtype]):
35
35
  ar = round(a, k)
36
36
  np.testing.assert_equal(a, ar)
37
37
 
38
38
 
39
39
  def test_round_minus_one_to_minus_one(dtype):
40
40
  a = -np.ones((3, 2), dtype=dtype)
41
- for k in range(0, max_bits[dtype]):
41
+ for k in range(max_bits[dtype]):
42
42
  ar = round(a, k)
43
43
  np.testing.assert_equal(a, ar)
44
44
 
@@ -133,7 +133,7 @@ def test_compress_blocksize_default(use_threads):
133
133
  assert blocksize > 0
134
134
 
135
135
 
136
- @pytest.mark.parametrize('bs', (2**7, 2**8))
136
+ @pytest.mark.parametrize('bs', [2**7, 2**8])
137
137
  def test_compress_blocksize(use_threads, bs):
138
138
  arr = np.arange(1000, dtype='i4')
139
139
 
@@ -225,7 +225,7 @@ def _decode_worker(enc):
225
225
  return data
226
226
 
227
227
 
228
- @pytest.mark.parametrize('pool', (Pool, ThreadPool))
228
+ @pytest.mark.parametrize('pool', [Pool, ThreadPool])
229
229
  def test_multiprocessing(use_threads, pool):
230
230
  data = np.arange(1000000)
231
231
  enc = _encode_worker(data)
@@ -3,11 +3,12 @@ import itertools
3
3
  import numpy as np
4
4
  import pytest
5
5
 
6
- from numcodecs.checksum32 import CRC32, Adler32
6
+ from numcodecs.checksum32 import CRC32, CRC32C, Adler32
7
7
  from numcodecs.tests.common import (
8
8
  check_backwards_compatibility,
9
9
  check_config,
10
10
  check_encode_decode,
11
+ check_err_decode_object_buffer,
11
12
  check_err_encode_object_buffer,
12
13
  check_repr,
13
14
  )
@@ -21,38 +22,117 @@ arrays = [
21
22
  np.random.normal(loc=1000, scale=1, size=(100, 10)),
22
23
  np.random.randint(0, 2, size=1000, dtype=bool).reshape(100, 10, order='F'),
23
24
  np.random.choice([b'a', b'bb', b'ccc'], size=1000).reshape(10, 10, 10),
25
+ np.random.randint(0, 2**60, size=1000, dtype='u8').view('M8[ns]'),
26
+ np.random.randint(0, 2**60, size=1000, dtype='u8').view('m8[ns]'),
27
+ np.random.randint(0, 2**25, size=1000, dtype='u8').view('M8[m]'),
28
+ np.random.randint(0, 2**25, size=1000, dtype='u8').view('m8[m]'),
29
+ np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('M8[ns]'),
30
+ np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('m8[ns]'),
31
+ np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('M8[m]'),
32
+ np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype='i8').view('m8[m]'),
24
33
  ]
25
34
 
26
- codecs = [CRC32(), Adler32()]
35
+ codecs = [
36
+ CRC32(),
37
+ CRC32(location="end"),
38
+ CRC32C(location="start"),
39
+ CRC32C(),
40
+ Adler32(),
41
+ Adler32(location="end"),
42
+ ]
43
+
44
+
45
+ @pytest.mark.parametrize(("codec", "arr"), itertools.product(codecs, arrays))
46
+ def test_encode_decode(codec, arr):
47
+ check_encode_decode(arr, codec)
48
+
49
+
50
+ @pytest.mark.parametrize(("codec", "arr"), itertools.product(codecs, arrays))
51
+ def test_errors(codec, arr):
52
+ enc = codec.encode(arr)
53
+ with pytest.raises(RuntimeError):
54
+ codec.decode(enc[:-1])
55
+
56
+
57
+ @pytest.mark.parametrize("codec", codecs)
58
+ def test_config(codec):
59
+ check_config(codec)
60
+
61
+
62
+ @pytest.mark.parametrize("codec", codecs)
63
+ def test_err_input_too_small(codec):
64
+ buf = b'000' # 3 bytes are too little for a 32-bit checksum
65
+ with pytest.raises(ValueError):
66
+ codec.decode(buf)
27
67
 
28
68
 
29
- def test_encode_decode():
30
- for codec, arr in itertools.product(codecs, arrays):
31
- check_encode_decode(arr, codec)
69
+ @pytest.mark.parametrize("codec", codecs)
70
+ def test_err_encode_non_contiguous(codec):
71
+ # non-contiguous memory
72
+ arr = np.arange(1000, dtype='i4')[::2]
73
+ with pytest.raises(ValueError):
74
+ codec.encode(arr)
32
75
 
33
76
 
34
- def test_errors():
35
- for codec, arr in itertools.product(codecs, arrays):
36
- enc = codec.encode(arr)
37
- with pytest.raises(RuntimeError):
38
- codec.decode(enc[:-1])
77
+ @pytest.mark.parametrize("codec", codecs)
78
+ def test_err_encode_list(codec):
79
+ data = ['foo', 'bar', 'baz']
80
+ with pytest.raises(TypeError):
81
+ codec.encode(data)
39
82
 
40
83
 
41
- def test_config():
42
- for codec in codecs:
43
- check_config(codec)
84
+ def test_err_location():
85
+ with pytest.raises(ValueError):
86
+ CRC32(location="foo")
87
+ with pytest.raises(ValueError):
88
+ CRC32C(location="foo")
89
+ with pytest.raises(ValueError):
90
+ Adler32(location="foo")
44
91
 
45
92
 
46
93
  def test_repr():
47
- check_repr("CRC32()")
48
- check_repr("Adler32()")
94
+ check_repr("CRC32(location='start')")
95
+ check_repr("CRC32C(location='start')")
96
+ check_repr("Adler32(location='start')")
97
+ check_repr("CRC32(location='end')")
98
+ check_repr("CRC32C(location='end')")
99
+ check_repr("Adler32(location='end')")
49
100
 
50
101
 
51
102
  def test_backwards_compatibility():
52
103
  check_backwards_compatibility(CRC32.codec_id, arrays, [CRC32()])
53
104
  check_backwards_compatibility(Adler32.codec_id, arrays, [Adler32()])
105
+ check_backwards_compatibility(CRC32C.codec_id, arrays, [CRC32C()])
106
+
107
+
108
+ @pytest.mark.parametrize("codec", codecs)
109
+ def test_err_encode_object_buffer(codec):
110
+ check_err_encode_object_buffer(codec)
111
+
112
+
113
+ @pytest.mark.parametrize("codec", codecs)
114
+ def test_err_decode_object_buffer(codec):
115
+ check_err_decode_object_buffer(codec)
116
+
117
+
118
+ @pytest.mark.parametrize("codec", codecs)
119
+ def test_err_out_too_small(codec):
120
+ arr = np.arange(10, dtype='i4')
121
+ out = np.empty_like(arr)[:-1]
122
+ with pytest.raises(ValueError):
123
+ codec.decode(codec.encode(arr), out)
124
+
125
+
126
+ def test_crc32c_checksum():
127
+ arr = np.arange(0, 64, dtype="uint8")
128
+ buf = CRC32C(location="end").encode(arr)
129
+ assert np.frombuffer(buf, dtype="<u4", offset=(len(buf) - 4))[0] == np.uint32(4218238699)
54
130
 
55
131
 
56
- def test_err_encode_object_buffer():
57
- check_err_encode_object_buffer(CRC32())
58
- check_err_encode_object_buffer(Adler32())
132
+ @pytest.mark.parametrize("codec", codecs)
133
+ def test_err_checksum(codec):
134
+ arr = np.arange(0, 64, dtype="uint8")
135
+ buf = bytearray(codec.encode(arr))
136
+ buf[-1] = 0 # corrupt the checksum
137
+ with pytest.raises(RuntimeError):
138
+ codec.decode(buf)
@@ -64,6 +64,9 @@ def test_ensure_bytes_invalid_inputs():
64
64
  ensure_bytes(e)
65
65
 
66
66
 
67
+ @pytest.mark.filterwarnings(
68
+ "ignore:The 'u' type code is deprecated and will be removed in Python 3.16"
69
+ )
67
70
  def test_ensure_contiguous_ndarray_invalid_inputs():
68
71
  # object array not allowed
69
72
  a = np.array(['Xin chào thế giới'], dtype=object)
@@ -14,6 +14,7 @@ from numcodecs.tests.common import (
14
14
  # mix of shapes: 1D, 2D, 3D
15
15
  # mix of orders: C, F
16
16
  arrays = [
17
+ np.random.randint(0, 1, size=110, dtype='?').reshape(10, 11),
17
18
  np.arange(1000, dtype='<i4'),
18
19
  np.linspace(1000, 1001, 1000, dtype='<f4').reshape(100, 10),
19
20
  np.random.normal(loc=1000, scale=1, size=(10, 10, 10)).astype('<f8'),
@@ -8,7 +8,7 @@ import numcodecs.registry
8
8
  here = os.path.abspath(os.path.dirname(__file__))
9
9
 
10
10
 
11
- @pytest.fixture()
11
+ @pytest.fixture
12
12
  def set_path():
13
13
  sys.path.append(here)
14
14
  numcodecs.registry.run_entrypoints()
@@ -1,4 +1,4 @@
1
- import importlib
1
+ import importlib.util
2
2
  import os.path
3
3
  import sys
4
4
  from multiprocessing import Process
@@ -7,7 +7,8 @@ import pytest
7
7
 
8
8
  import numcodecs.registry
9
9
 
10
- if not importlib.util.find_spec("importlib_metadata").loader: # pragma: no cover
10
+ importlib_spec = importlib.util.find_spec("importlib_metadata")
11
+ if importlib_spec is None or importlib_spec.loader is None: # pragma: no cover
11
12
  pytest.skip(
12
13
  "This test module requires importlib_metadata to be installed",
13
14
  allow_module_level=True,
@@ -36,12 +36,20 @@ def test_encode_decode():
36
36
  check_encode_decode(arr, codec, precision=precision)
37
37
 
38
38
 
39
- def test_encode():
39
+ @pytest.mark.parametrize(
40
+ ("offset", "scale", "expected"),
41
+ [
42
+ (1000, 10, [0, 6, 11, 17, 22, 28, 33, 39, 44, 50]),
43
+ (1002.5, 10, [-25, -19, -14, -8, -3, 3, 8, 14, 19, 25]),
44
+ (1000, 0.5, [0, 0, 1, 1, 1, 1, 2, 2, 2, 2]),
45
+ ],
46
+ )
47
+ def test_encode(offset: float, scale: float, expected: list[int]):
40
48
  dtype = '<f8'
41
- astype = '|u1'
42
- codec = FixedScaleOffset(scale=10, offset=1000, dtype=dtype, astype=astype)
43
- arr = np.linspace(1000, 1001, 10, dtype=dtype)
44
- expect = np.array([0, 1, 2, 3, 4, 6, 7, 8, 9, 10], dtype=astype)
49
+ astype = np.int16
50
+ codec = FixedScaleOffset(scale=scale, offset=offset, dtype=dtype, astype=astype)
51
+ arr = np.linspace(1000, 1005, 10, dtype=dtype)
52
+ expect = np.array(expected, dtype=astype)
45
53
  actual = codec.encode(arr)
46
54
  assert_array_equal(expect, actual)
47
55
  assert np.dtype(astype) == actual.dtype
@@ -59,7 +59,7 @@ def test_backwards_compatibility():
59
59
 
60
60
 
61
61
  @pytest.mark.parametrize(
62
- "input_data, dtype",
62
+ ('input_data', 'dtype'),
63
63
  [
64
64
  ([0, 1], None),
65
65
  ([[0, 1], [2, 3]], None),
@@ -1,5 +1,7 @@
1
1
  import itertools
2
2
  import unittest
3
+ from types import ModuleType
4
+ from typing import cast
3
5
 
4
6
  import numpy as np
5
7
  import pytest
@@ -20,6 +22,8 @@ from numcodecs.tests.common import (
20
22
  check_repr,
21
23
  )
22
24
 
25
+ _lzma = cast(ModuleType, _lzma)
26
+
23
27
  codecs = [
24
28
  LZMA(),
25
29
  LZMA(preset=1),
@@ -55,8 +55,11 @@ def test_backwards_compatibility():
55
55
  check_backwards_compatibility(codec.codec_id, arrays, [codec])
56
56
 
57
57
 
58
+ @pytest.mark.filterwarnings(
59
+ "ignore:Creating an ndarray from ragged nested sequences .* is deprecated.*"
60
+ )
58
61
  @pytest.mark.parametrize(
59
- "input_data, dtype",
62
+ ("input_data", "dtype"),
60
63
  [
61
64
  ([0, 1], None),
62
65
  ([[0, 1], [2, 3]], None),
@@ -57,8 +57,8 @@ def test_config():
57
57
 
58
58
 
59
59
  def test_invalid_config_error():
60
+ codec = PCodec(mode_spec='bogus')
60
61
  with pytest.raises(ValueError):
61
- codec = PCodec(mode_spec='bogus')
62
62
  check_encode_decode_array_to_bytes(arrays[0], codec)
63
63
 
64
64