Skip to content

Commit

Permalink
Merge branch 'main' into ruff_0.9.1
Browse files Browse the repository at this point in the history
  • Loading branch information
dcherian authored Feb 7, 2025
2 parents 93d0c56 + b8e40f7 commit 41fdb1f
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 30 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ repos:
- id: debug-statements

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.1
rev: v0.9.4
hooks:
- id: ruff
args: ["--fix", "--show-fixes"]
- id: ruff-format

- repo: https://github.com/scientific-python/cookie
rev: 2024.08.19
rev: 2025.01.22
hooks:
- id: sp-repo-review

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.14.0
rev: v1.14.1
hooks:
- id: mypy
args: [--config-file, pyproject.toml]
Expand Down
22 changes: 22 additions & 0 deletions docs/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,27 @@ Release notes
Unreleased
----------


.. _unreleased:

Unreleased
----------

Improvements
~~~~~~~~~~~~
* Raise a custom `UnknownCodecError` when trying to retrieve an unavailable codec.
By :user:`Cas Wognum <cwognum>`.

Fixes
~~~~~
* Remove redundant ``id`` from codec metadata serialization in Zarr3 codecs.
By :user:`Norman Rzepka <normanrz>`, :issue:`685`

.. _release_0.15.0:

0.15.0
------

Breaking changes
~~~~~~~~~~~~~~~~
* All arguments to the ``PCodec`` constructor except for ``level``
Expand All @@ -36,11 +52,16 @@ This is because they are not intended to be public API.
In addition, ``numcodecs.blosc.decompress_partial`` is deprecated as
has always been experimental and there is no equivalent in the official
blsoc Python package.
By :user:`David Stansby <dstansby>`, :issue`619`

Fixes
~~~~~
* Fixes issue with ``Delta`` Zarr 3 codec not working with ``astype``.
By :user:`Norman Rzepka <normanrz>`, :issue:`664`
* Cleanup ``PCodec`` soft dependency.
Previously importing ``numcodecs.pcodec`` would work if ``pcodec`` is not installed,
but now it will fail to import. This mirrors the behaviour of other optional dependencies.
By :user:`John Kirkham <jakirkham>`, :issue:`647`
* Fixes issues with the upcoming ``zarr`` 3.0.0 release.
By :user:`Norman Rzepka <normanrz>`, :issue:`675`

Expand All @@ -64,6 +85,7 @@ Improvements
are still silently caught.
By :user:`David Stansby <dstansby>`, :issue:`550`.

.. _release_0.14.1:

0.14.1
------
Expand Down
2 changes: 1 addition & 1 deletion numcodecs/checksum32.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

_crc32c: Optional[ModuleType] = None
with suppress(ImportError):
import crc32c as _crc32c # type: ignore[no-redef]
import crc32c as _crc32c # type: ignore[no-redef, unused-ignore]

if TYPE_CHECKING: # pragma: no cover
from typing_extensions import Buffer
Expand Down
7 changes: 1 addition & 6 deletions numcodecs/delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,7 @@ def encode(self, buf):
enc[0] = arr[0]

# compute differences
# using np.subtract for in-place operations
if arr.dtype == bool:
np.not_equal(arr[1:], arr[:-1], out=enc[1:])
else:
np.subtract(arr[1:], arr[:-1], out=enc[1:])

enc[1:] = np.diff(arr)
return enc

def decode(self, buf, out=None):
Expand Down
26 changes: 26 additions & 0 deletions numcodecs/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
This module defines custom exceptions that are raised in the `numcodecs` codebase.
"""


class UnknownCodecError(ValueError):
"""
An exception that is raised when trying to receive a codec that has not been registered.
Parameters
----------
codec_id : str
Codec identifier.
Examples
----------
>>> import numcodecs
>>> numcodecs.get_codec({"codec_id": "unknown"})
Traceback (most recent call last):
...
UnknownCodecError: codec not available: 'unknown'
"""

def __init__(self, codec_id: str):
self.codec_id = codec_id
super().__init__(f"codec not available: '{codec_id}'")
2 changes: 1 addition & 1 deletion numcodecs/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def __init__(
def encode(self, buf):
try:
buf = np.asarray(buf)
except ValueError:
except ValueError: # pragma: no cover
buf = np.asarray(buf, dtype=object)
items = np.atleast_1d(buf).tolist()
items.append(buf.dtype.str)
Expand Down
10 changes: 1 addition & 9 deletions numcodecs/pcodec.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@

from numcodecs.abc import Codec
from numcodecs.compat import ensure_contiguous_ndarray

try:
from pcodec import ChunkConfig, DeltaSpec, ModeSpec, PagingSpec, standalone
except ImportError: # pragma: no cover
standalone = None

from pcodec import ChunkConfig, DeltaSpec, ModeSpec, PagingSpec, standalone

DEFAULT_MAX_PAGE_N = 262144

Expand Down Expand Up @@ -58,9 +53,6 @@ def __init__(
delta_encoding_order: int | None = None,
equal_pages_up_to: int = DEFAULT_MAX_PAGE_N,
):
if standalone is None: # pragma: no cover
raise ImportError("pcodec must be installed to use the PCodec codec.")

# note that we use `level` instead of `compression_level` to
# match other codecs
self.level = level
Expand Down
4 changes: 2 additions & 2 deletions numcodecs/quantize.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ def encode(self, buf):
precision = 10.0**-self.digits
exp = math.log10(precision)
if exp < 0:
exp = int(math.floor(exp))
exp = math.floor(exp)
else:
exp = int(math.ceil(exp))
exp = math.ceil(exp)
bits = math.ceil(math.log2(10.0**-exp))
scale = 2.0**bits
enc = np.around(scale * arr) / scale
Expand Down
3 changes: 2 additions & 1 deletion numcodecs/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from importlib.metadata import EntryPoints, entry_points

from numcodecs.abc import Codec
from numcodecs.errors import UnknownCodecError

logger = logging.getLogger("numcodecs")
codec_registry: dict[str, Codec] = {}
Expand Down Expand Up @@ -50,7 +51,7 @@ def get_codec(config):
register_codec(cls, codec_id=codec_id)
if cls:
return cls.from_config(config)
raise ValueError(f'codec not available: {codec_id!r}')
raise UnknownCodecError(f"{codec_id!r}")


def register_codec(cls, codec_id=None):
Expand Down
5 changes: 1 addition & 4 deletions numcodecs/tests/test_pcodec.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import numpy as np
import pytest

from numcodecs.pcodec import PCodec

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

Expand Down
3 changes: 2 additions & 1 deletion numcodecs/tests/test_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import pytest

import numcodecs
from numcodecs.errors import UnknownCodecError
from numcodecs.registry import get_codec


def test_registry_errors():
with pytest.raises(ValueError):
with pytest.raises(UnknownCodecError, match='foo'):
get_codec({'id': 'foo'})


Expand Down
3 changes: 3 additions & 0 deletions numcodecs/tests/test_vlen_bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ def test_decode_errors():
codec.decode(enc, out=np.zeros(10, dtype='i4'))


# TODO: fix this test on GitHub actions somehow...
# See https://github.com/zarr-developers/numcodecs/issues/683
@pytest.mark.skip("Test is failing on GitHub actions.")
def test_encode_none():
a = np.array([b'foo', None, b'bar'], dtype=object)
codec = VLenBytes()
Expand Down
9 changes: 7 additions & 2 deletions numcodecs/tests/test_zarr3.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,11 @@ def test_generic_bytes_codec(
):
try:
codec_class()._codec # noqa: B018
except ValueError as e:
except ValueError as e: # pragma: no cover
if "codec not available" in str(e):
pytest.xfail(f"{codec_class.codec_name} is not available: {e}")
else:
raise # pragma: no cover
raise
except ImportError as e: # pragma: no cover
pytest.xfail(f"{codec_class.codec_name} is not available: {e}")

Expand Down Expand Up @@ -272,3 +272,8 @@ def test_delta_astype(store: StorePath):
def test_repr():
codec = numcodecs.zarr3.LZ4(level=5)
assert repr(codec) == "LZ4(codec_name='numcodecs.lz4', codec_config={'level': 5})"


def test_to_dict():
codec = numcodecs.zarr3.LZ4(level=5)
assert codec.to_dict() == {"name": "numcodecs.lz4", "configuration": {"level": 5}}
1 change: 1 addition & 0 deletions numcodecs/zarr3.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def from_dict(cls, data: dict[str, JSON]) -> Self:

def to_dict(self) -> dict[str, JSON]:
codec_config = self.codec_config.copy()
codec_config.pop("id", None)
return {
"name": self.codec_name,
"configuration": codec_config,
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,6 @@ enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
# TODO: set options below to true
strict = false
warn_unreachable = false
warn_redundant_casts = true
warn_unused_ignores = true
warn_unused_configs = true

0 comments on commit 41fdb1f

Please sign in to comment.