Skip to content

Commit dbb53f5

Browse files
authored
Merge branch 'main' into 014-rel-notes
2 parents 774fad5 + 23223dc commit dbb53f5

15 files changed

+101
-52
lines changed

.pre-commit-config.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ repos:
1515
- id: debug-statements
1616

1717
- repo: https://github.com/astral-sh/ruff-pre-commit
18-
rev: v0.7.2
18+
rev: v0.7.3
1919
hooks:
2020
- id: ruff
2121
args: ["--fix", "--show-fixes"]
@@ -25,3 +25,10 @@ repos:
2525
rev: 2024.08.19
2626
hooks:
2727
- id: sp-repo-review
28+
29+
- repo: https://github.com/pre-commit/mirrors-mypy
30+
rev: 'v1.4.0'
31+
hooks:
32+
- id: mypy
33+
args: [--config-file, pyproject.toml]
34+
additional_dependencies: [numpy, pytest, zfpy, 'zarr==3.0.0b1']

docs/conf.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# All configuration values have a default; values that are commented out
1313
# serve to show the default.
1414

15-
1615
import os
1716
import sys
1817
from unittest.mock import Mock as MagicMock
@@ -232,7 +231,7 @@ def __getattr__(cls, name):
232231

233232
# -- Options for LaTeX output ---------------------------------------------
234233

235-
latex_elements = {
234+
latex_elements: dict[str, str] = {
236235
# The paper size ('letterpaper' or 'a4paper').
237236
#'papersize': 'letterpaper',
238237
# The font size ('10pt', '11pt' or '12pt').

docs/release.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ Enhancements
2323
By :user:`Norman Rzepka <normanrz>`, :issue:`613`.
2424
* Add codec wrappers for Zarr 3.
2525
By :user:`Norman Rzepka <normanrz>`, :issue:`524`
26+
* Added mypy type checking to continuous integration.
27+
By :user:`David Stansby <dstansby>`, :issue:`460`.
2628

2729
Fixes
2830
~~~~~

numcodecs/abc.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@
2929
"""
3030

3131
from abc import ABC, abstractmethod
32+
from typing import Optional
3233

3334

3435
class Codec(ABC):
3536
"""Codec abstract base class."""
3637

3738
# override in sub-class
38-
codec_id = None
39+
codec_id: Optional[str] = None
3940
"""Codec identifier."""
4041

4142
@abstractmethod

numcodecs/checksum32.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import struct
22
import zlib
3-
from typing import Literal
3+
from collections.abc import Callable
4+
from typing import TYPE_CHECKING, Literal
45

56
import numpy as np
67

78
from .abc import Codec
89
from .compat import ensure_contiguous_ndarray, ndarray_copy
910
from .jenkins import jenkins_lookup3
1011

12+
if TYPE_CHECKING:
13+
from typing_extensions import Buffer
14+
1115
CHECKSUM_LOCATION = Literal['start', 'end']
1216

1317

1418
class Checksum32(Codec):
1519
# override in sub-class
16-
checksum = None
20+
checksum: Callable[["Buffer", int], int] | None = None
1721
location: CHECKSUM_LOCATION = 'start'
1822

1923
def __init__(self, location: CHECKSUM_LOCATION | None = None):

numcodecs/compat.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def ensure_contiguous_ndarray_like(buf, max_buffer_size=None, flatten=True) -> N
100100

101101
# check for datetime or timedelta ndarray, the buffer interface doesn't support those
102102
if arr.dtype.kind in "Mm":
103-
arr = arr.view(np.int64)
103+
arr = arr.view(np.int64) # type: ignore[arg-type]
104104

105105
# check memory is contiguous, if so flatten
106106
if arr.flags.c_contiguous or arr.flags.f_contiguous:
@@ -117,7 +117,7 @@ def ensure_contiguous_ndarray_like(buf, max_buffer_size=None, flatten=True) -> N
117117
return arr
118118

119119

120-
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:
121121
"""Convenience function to coerce `buf` to a numpy array, if it is not already a
122122
numpy array. Also ensures that the returned value exports fully contiguous memory,
123123
and supports the new-style buffer interface. If the optional max_buffer_size is

numcodecs/lzma.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
import contextlib
1+
from types import ModuleType
2+
from typing import Optional
23

3-
_lzma = None
4+
_lzma: Optional[ModuleType] = None
45
try:
56
import lzma as _lzma
67
except ImportError: # pragma: no cover
7-
with contextlib.suppress(ImportError):
8-
from backports import lzma as _lzma
8+
try:
9+
from backports import lzma as _lzma # type: ignore[no-redef]
10+
except ImportError:
11+
pass
912

1013

1114
if _lzma:

numcodecs/ndarray_like.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Any, ClassVar, Optional, Protocol, runtime_checkable
22

33

4-
class _CachedProtocolMeta(Protocol.__class__):
4+
class _CachedProtocolMeta(Protocol.__class__): # type: ignore[name-defined]
55
"""Custom implementation of @runtime_checkable
66
77
The native implementation of @runtime_checkable is slow,

numcodecs/registry.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
applications to dynamically register and look-up codec classes."""
33

44
import logging
5-
from importlib.metadata import entry_points
5+
from importlib.metadata import EntryPoints, entry_points
6+
7+
from numcodecs.abc import Codec
68

79
logger = logging.getLogger("numcodecs")
8-
codec_registry = {}
9-
entries = {}
10+
codec_registry: dict[str, Codec] = {}
11+
entries: dict[str, "EntryPoints"] = {}
1012

1113

1214
def run_entrypoints():

numcodecs/tests/test_lzma.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import itertools
22
import unittest
3+
from types import ModuleType
4+
from typing import cast
35

46
import numpy as np
57
import pytest
@@ -20,6 +22,8 @@
2022
check_repr,
2123
)
2224

25+
_lzma = cast(ModuleType, _lzma)
26+
2327
codecs = [
2428
LZMA(),
2529
LZMA(preset=1),

numcodecs/tests/test_zarr3.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
from __future__ import annotations
22

3+
from typing import TYPE_CHECKING
4+
35
import numpy as np
46
import pytest
57

6-
zarr = pytest.importorskip("zarr")
8+
if not TYPE_CHECKING:
9+
zarr = pytest.importorskip("zarr")
10+
else:
11+
import zarr
12+
13+
import zarr.storage
14+
from zarr.core.common import JSON
715

8-
import numcodecs.zarr3 # noqa: E402
16+
import numcodecs.zarr3
917

1018
pytestmark = [
1119
pytest.mark.skipif(zarr.__version__ < "3.0.0", reason="zarr 3.0.0 or later is required"),
@@ -17,7 +25,6 @@
1725

1826
get_codec_class = zarr.registry.get_codec_class
1927
Array = zarr.Array
20-
JSON = zarr.core.common.JSON
2128
BytesCodec = zarr.codecs.BytesCodec
2229
Store = zarr.abc.store.Store
2330
MemoryStore = zarr.storage.MemoryStore
@@ -28,7 +35,7 @@
2835

2936

3037
@pytest.fixture
31-
def store() -> Store:
38+
def store() -> StorePath:
3239
return StorePath(MemoryStore(mode="w"))
3340

3441

@@ -43,6 +50,8 @@ def test_entry_points(codec_class: type[numcodecs.zarr3._NumcodecsCodec]):
4350

4451
@pytest.mark.parametrize("codec_class", ALL_CODECS)
4552
def test_docstring(codec_class: type[numcodecs.zarr3._NumcodecsCodec]):
53+
if codec_class.__doc__ is None:
54+
pytest.skip()
4655
assert "See :class:`numcodecs." in codec_class.__doc__
4756

4857

@@ -59,7 +68,7 @@ def test_docstring(codec_class: type[numcodecs.zarr3._NumcodecsCodec]):
5968
numcodecs.zarr3.Shuffle,
6069
],
6170
)
62-
def test_generic_codec_class(store: Store, codec_class: type[numcodecs.zarr3._NumcodecsCodec]):
71+
def test_generic_codec_class(store: StorePath, codec_class: type[numcodecs.zarr3._NumcodecsCodec]):
6372
data = np.arange(0, 256, dtype="uint16").reshape((16, 16))
6473

6574
with pytest.warns(UserWarning, match=EXPECTED_WARNING_STR):
@@ -92,7 +101,9 @@ def test_generic_codec_class(store: Store, codec_class: type[numcodecs.zarr3._Nu
92101
],
93102
)
94103
def test_generic_filter(
95-
store: Store, codec_class: type[numcodecs.zarr3._NumcodecsCodec], codec_config: dict[str, JSON]
104+
store: StorePath,
105+
codec_class: type[numcodecs.zarr3._NumcodecsCodec],
106+
codec_config: dict[str, JSON],
96107
):
97108
data = np.linspace(0, 10, 256, dtype="float32").reshape((16, 16))
98109

@@ -114,7 +125,7 @@ def test_generic_filter(
114125
np.testing.assert_array_equal(data, a[:, :])
115126

116127

117-
def test_generic_filter_bitround(store: Store):
128+
def test_generic_filter_bitround(store: StorePath):
118129
data = np.linspace(0, 1, 256, dtype="float32").reshape((16, 16))
119130

120131
with pytest.warns(UserWarning, match=EXPECTED_WARNING_STR):
@@ -132,7 +143,7 @@ def test_generic_filter_bitround(store: Store):
132143
assert np.allclose(data, a[:, :], atol=0.1)
133144

134145

135-
def test_generic_filter_quantize(store: Store):
146+
def test_generic_filter_quantize(store: StorePath):
136147
data = np.linspace(0, 10, 256, dtype="float32").reshape((16, 16))
137148

138149
with pytest.warns(UserWarning, match=EXPECTED_WARNING_STR):
@@ -150,7 +161,7 @@ def test_generic_filter_quantize(store: Store):
150161
assert np.allclose(data, a[:, :], atol=0.001)
151162

152163

153-
def test_generic_filter_packbits(store: Store):
164+
def test_generic_filter_packbits(store: StorePath):
154165
data = np.zeros((16, 16), dtype="bool")
155166
data[0:4, :] = True
156167

@@ -189,7 +200,7 @@ def test_generic_filter_packbits(store: Store):
189200
numcodecs.zarr3.JenkinsLookup3,
190201
],
191202
)
192-
def test_generic_checksum(store: Store, codec_class: type[numcodecs.zarr3._NumcodecsCodec]):
203+
def test_generic_checksum(store: StorePath, codec_class: type[numcodecs.zarr3._NumcodecsCodec]):
193204
data = np.linspace(0, 10, 256, dtype="float32").reshape((16, 16))
194205

195206
with pytest.warns(UserWarning, match=EXPECTED_WARNING_STR):
@@ -208,7 +219,7 @@ def test_generic_checksum(store: Store, codec_class: type[numcodecs.zarr3._Numco
208219

209220

210221
@pytest.mark.parametrize("codec_class", [numcodecs.zarr3.PCodec, numcodecs.zarr3.ZFPY])
211-
def test_generic_bytes_codec(store: Store, codec_class: type[numcodecs.zarr3._NumcodecsCodec]):
222+
def test_generic_bytes_codec(store: StorePath, codec_class: type[numcodecs.zarr3._NumcodecsCodec]):
212223
try:
213224
codec_class()._codec # noqa: B018
214225
except ValueError as e:

numcodecs/tests/test_zfpy.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from types import ModuleType
2+
from typing import cast
3+
14
import numpy as np
25
import pytest
36

@@ -17,6 +20,9 @@
1720
check_repr,
1821
)
1922

23+
_zfpy = cast(ModuleType, _zfpy)
24+
25+
2026
codecs = [
2127
ZFPY(mode=_zfpy.mode_fixed_rate, rate=-1),
2228
ZFPY(),

0 commit comments

Comments
 (0)