diff --git a/adhoc/blosc_memleak_check.py b/adhoc/blosc_memleak_check.py index 427c3e153..a6409ed19 100644 --- a/adhoc/blosc_memleak_check.py +++ b/adhoc/blosc_memleak_check.py @@ -1,10 +1,9 @@ import sys +import numcodecs import numpy as np from numpy.testing import assert_array_equal -import numcodecs - codec = numcodecs.Blosc() data = np.arange(int(sys.argv[1])) for _ in range(int(sys.argv[2])): diff --git a/notebooks/benchmark_vlen.ipynb b/notebooks/benchmark_vlen.ipynb index c627cac95..cb971278e 100644 --- a/notebooks/benchmark_vlen.ipynb +++ b/notebooks/benchmark_vlen.ipynb @@ -24,9 +24,8 @@ } ], "source": [ - "import numpy as np\n", - "\n", "import numcodecs\n", + "import numpy as np\n", "\n", "numcodecs.__version__" ] diff --git a/numcodecs/astype.py b/numcodecs/astype.py index b5c5abc97..4947d53c9 100644 --- a/numcodecs/astype.py +++ b/numcodecs/astype.py @@ -49,9 +49,7 @@ def encode(self, buf): arr = ensure_ndarray(buf).view(self.decode_dtype) # convert and copy - enc = arr.astype(self.encode_dtype) - - return enc + return arr.astype(self.encode_dtype) def decode(self, buf, out=None): # normalise input @@ -61,9 +59,7 @@ def decode(self, buf, out=None): dec = enc.astype(self.decode_dtype) # handle output - out = ndarray_copy(dec, out) - - return out + return ndarray_copy(dec, out) def get_config(self): return { diff --git a/numcodecs/base64.py b/numcodecs/base64.py index 74f42161c..307c6d52b 100644 --- a/numcodecs/base64.py +++ b/numcodecs/base64.py @@ -13,8 +13,7 @@ def encode(self, buf): # normalise inputs buf = ensure_contiguous_ndarray(buf) # do compression - compressed = _base64.standard_b64encode(buf) - return compressed + return _base64.standard_b64encode(buf) def decode(self, buf, out=None): # normalise inputs diff --git a/numcodecs/categorize.py b/numcodecs/categorize.py index ed20ad61b..c81994937 100644 --- a/numcodecs/categorize.py +++ b/numcodecs/categorize.py @@ -80,18 +80,15 @@ def decode(self, buf, out=None): dec[enc == (i + 1)] = label # handle output - dec = ndarray_copy(dec, out) - - return dec + return ndarray_copy(dec, out) def get_config(self): - config = { + return { 'id': self.codec_id, 'labels': self.labels, 'dtype': self.dtype.str, 'astype': self.astype.str, } - return config def __repr__(self): # make sure labels part is not too long diff --git a/numcodecs/delta.py b/numcodecs/delta.py index ee4abbc76..32da2e04b 100644 --- a/numcodecs/delta.py +++ b/numcodecs/delta.py @@ -85,9 +85,7 @@ def decode(self, buf, out=None): np.cumsum(enc, out=dec) # handle output - out = ndarray_copy(dec, out) - - return out + return ndarray_copy(dec, out) def get_config(self): # override to handle encoding dtypes diff --git a/numcodecs/fixedscaleoffset.py b/numcodecs/fixedscaleoffset.py index 636e439ee..b1db52050 100644 --- a/numcodecs/fixedscaleoffset.py +++ b/numcodecs/fixedscaleoffset.py @@ -94,9 +94,7 @@ def encode(self, buf): enc = np.around(enc) # convert dtype - enc = enc.astype(self.astype, copy=False) - - return enc + return enc.astype(self.astype, copy=False) def decode(self, buf, out=None): # interpret buffer as numpy array diff --git a/numcodecs/gzip.py b/numcodecs/gzip.py index 12e9c011e..4269bad93 100644 --- a/numcodecs/gzip.py +++ b/numcodecs/gzip.py @@ -28,9 +28,7 @@ def encode(self, buf): compressed = io.BytesIO() with _gzip.GzipFile(fileobj=compressed, mode='wb', compresslevel=self.level) as compressor: compressor.write(buf) - compressed = compressed.getvalue() - - return compressed + return compressed.getvalue() # noinspection PyMethodMayBeStatic def decode(self, buf, out=None): diff --git a/numcodecs/lzma.py b/numcodecs/lzma.py index 32fb528b2..5c1a57caf 100644 --- a/numcodecs/lzma.py +++ b/numcodecs/lzma.py @@ -5,7 +5,7 @@ try: import lzma as _lzma except ImportError: # pragma: no cover - try: + try: # noqa: SIM105 from backports import lzma as _lzma # type: ignore[no-redef] except ImportError: pass diff --git a/numcodecs/ndarray_like.py b/numcodecs/ndarray_like.py index f70d7b450..06e15ea97 100644 --- a/numcodecs/ndarray_like.py +++ b/numcodecs/ndarray_like.py @@ -1,4 +1,4 @@ -from typing import Any, ClassVar, Optional, Protocol, runtime_checkable +from typing import Any, ClassVar, Protocol, runtime_checkable class _CachedProtocolMeta(Protocol.__class__): # type: ignore[name-defined] @@ -53,7 +53,7 @@ def __getitem__(self, key) -> Any: ... # pragma: no cover def __setitem__(self, key, value): ... # pragma: no cover - def tobytes(self, order: Optional[str] = ...) -> bytes: ... # pragma: no cover + def tobytes(self, order: str | None = ...) -> bytes: ... # pragma: no cover def reshape(self, *shape: int, order: str = ...) -> "NDArrayLike": ... # pragma: no cover diff --git a/numcodecs/pcodec.py b/numcodecs/pcodec.py index 1739ff0bd..da063ae53 100644 --- a/numcodecs/pcodec.py +++ b/numcodecs/pcodec.py @@ -1,4 +1,4 @@ -from typing import Literal, Optional +from typing import Literal from numcodecs.abc import Codec from numcodecs.compat import ensure_contiguous_ndarray @@ -55,7 +55,7 @@ def __init__( mode_spec: Literal["auto", "classic"] = "auto", delta_spec: Literal["auto", "none", "try_consecutive", "try_lookback"] = "auto", paging_spec: Literal["equal_pages_up_to"] = "equal_pages_up_to", - delta_encoding_order: Optional[int] = None, + delta_encoding_order: int | None = None, equal_pages_up_to: int = DEFAULT_MAX_PAGE_N, ): if standalone is None: # pragma: no cover @@ -105,13 +105,12 @@ def _get_chunk_config(self): case _: raise ValueError(f"paging_spec {self.paging_spec} is not supported") - config = ChunkConfig( + return ChunkConfig( compression_level=self.level, delta_spec=delta_spec, mode_spec=mode_spec, paging_spec=paging_spec, ) - return config def encode(self, buf): buf = ensure_contiguous_ndarray(buf) diff --git a/numcodecs/quantize.py b/numcodecs/quantize.py index b9a8a3113..b5b6cc3cc 100644 --- a/numcodecs/quantize.py +++ b/numcodecs/quantize.py @@ -73,9 +73,7 @@ def encode(self, buf): enc = np.around(scale * arr) / scale # cast dtype - enc = enc.astype(self.astype, copy=False) - - return enc + return enc.astype(self.astype, copy=False) def decode(self, buf, out=None): # filter is lossy, decoding is no-op diff --git a/numcodecs/tests/common.py b/numcodecs/tests/common.py index 2de810522..bb7c4780b 100644 --- a/numcodecs/tests/common.py +++ b/numcodecs/tests/common.py @@ -7,8 +7,7 @@ import pytest from numpy.testing import assert_array_almost_equal, assert_array_equal -# star import needed for repr tests so eval finds names -from numcodecs import * # noqa: F403 +from numcodecs import * # noqa: F403 # for eval to find names in repr tests from numcodecs.compat import ensure_bytes, ensure_ndarray from numcodecs.registry import get_codec @@ -19,9 +18,9 @@ 'Hei maailma!', 'Xin chào thế giới', 'Njatjeta Botë!', - 'Γεια σου κόσμε!', + 'Γεια σου κόσμε!', # noqa: RUF001 'こんにちは世界', - '世界,你好!', + '世界,你好!', # noqa: RUF001 'Helló, világ!', 'Zdravo svete!', 'เฮลโลเวิลด์', diff --git a/numcodecs/tests/test_blosc.py b/numcodecs/tests/test_blosc.py index 17b291388..8c1872014 100644 --- a/numcodecs/tests/test_blosc.py +++ b/numcodecs/tests/test_blosc.py @@ -215,14 +215,12 @@ def test_backwards_compatibility(): def _encode_worker(data): compressor = Blosc(cname='zlib', clevel=9, shuffle=Blosc.SHUFFLE) - enc = compressor.encode(data) - return enc + return compressor.encode(data) def _decode_worker(enc): compressor = Blosc() - data = compressor.decode(enc) - return data + return compressor.decode(enc) @pytest.mark.parametrize('pool', [Pool, ThreadPool]) diff --git a/numcodecs/tests/test_shuffle.py b/numcodecs/tests/test_shuffle.py index 1194e5982..6e6d744a1 100644 --- a/numcodecs/tests/test_shuffle.py +++ b/numcodecs/tests/test_shuffle.py @@ -79,14 +79,12 @@ def test_eq(): def _encode_worker(data): compressor = Shuffle() - enc = compressor.encode(data) - return enc + return compressor.encode(data) def _decode_worker(enc): compressor = Shuffle() - data = compressor.decode(enc) - return data + return compressor.decode(enc) @pytest.mark.parametrize('pool', [Pool, ThreadPool]) diff --git a/numcodecs/zarr3.py b/numcodecs/zarr3.py index 0fc0acee8..d297b39e1 100644 --- a/numcodecs/zarr3.py +++ b/numcodecs/zarr3.py @@ -40,8 +40,10 @@ if zarr.__version__ < "3.0.0": # pragma: no cover raise ImportError("zarr 3.0.0 or later is required to use the numcodecs zarr integration.") -except ImportError: # pragma: no cover - raise ImportError("zarr 3.0.0 or later is required to use the numcodecs zarr integration.") +except ImportError as e: # pragma: no cover + raise ImportError( + "zarr 3.0.0 or later is required to use the numcodecs zarr integration." + ) from e from zarr.abc.codec import ArrayArrayCodec, ArrayBytesCodec, BytesBytesCodec from zarr.abc.metadata import Metadata @@ -95,6 +97,7 @@ def __init__(self, **codec_config: JSON) -> None: "Numcodecs codecs are not in the Zarr version 3 specification and " "may not be supported by other zarr implementations.", category=UserWarning, + stacklevel=2, ) @cached_property diff --git a/pyproject.toml b/pyproject.toml index 52ab34c39..7dfadb5d4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -164,39 +164,68 @@ environment = { DISABLE_NUMCODECS_AVX2=1, DISABLE_NUMCODECS_SSE2=1 } [tool.ruff] line-length = 100 +extend-exclude = ["c-blosc"] +src = ["numcodecs"] [tool.ruff.lint] extend-select = [ "B", "C4", + "EXE", + "FA", "FLY", "FURB", "G", "I", + "ISC", + "LOG", "PERF", "PGH", "PIE", "PT", "PYI", + "RET", "RSE", "RUF", + "SIM", + "SLOT", + "TID", + "TRY", "UP", - # "W", https://github.com/astral-sh/ruff/issues/13763 ] ignore = [ - "B028", - "B904", "FURB101", "FURB103", "PT001", - "PT004", # deprecated - "PT005", # deprecated "PT011", - "RUF001", + "PT012", + "RET505", + "RET506", + "SIM108", + "TRY003", + "TRY301", "UP007", - "UP027", # deprecated "UP038", # https://github.com/astral-sh/ruff/issues/7871 -] + # https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules + "W191", + "E111", + "E114", + "E117", + "D206", + "D300", + "Q000", + "Q001", + "Q002", + "Q003", + "COM812", + "COM819", + "ISC001", + "ISC002", +] + +[tool.ruff.lint.extend-per-file-ignores] +"numcodecs/tests/**" = ["SIM201", "SIM202", "SIM300", "TRY002"] +"notebooks/**" = ["W391"] # https://github.com/astral-sh/ruff/issues/13763 [tool.ruff.format] quote-style = "preserve" diff --git a/setup.py b/setup.py index 0f5ec481d..6cbddf4a5 100644 --- a/setup.py +++ b/setup.py @@ -111,7 +111,7 @@ def blosc_extension(): sources = ['numcodecs/blosc.pyx'] # define extension module - extensions = [ + return [ Extension( 'numcodecs.blosc', sources=sources + blosc_sources, @@ -122,8 +122,6 @@ def blosc_extension(): ), ] - return extensions - def zstd_extension(): info('setting up Zstandard extension') @@ -153,7 +151,7 @@ def zstd_extension(): extra_objects = [] # define extension module - extensions = [ + return [ Extension( 'numcodecs.zstd', sources=sources + zstd_sources, @@ -164,8 +162,6 @@ def zstd_extension(): ), ] - return extensions - def lz4_extension(): info('setting up LZ4 extension') @@ -182,7 +178,7 @@ def lz4_extension(): sources = ['numcodecs/lz4.pyx'] # define extension module - extensions = [ + return [ Extension( 'numcodecs.lz4', sources=sources + lz4_sources, @@ -192,8 +188,6 @@ def lz4_extension(): ), ] - return extensions - def vlen_extension(): info('setting up vlen extension') @@ -209,7 +203,7 @@ def vlen_extension(): sources = ['numcodecs/vlen.pyx'] # define extension module - extensions = [ + return [ Extension( 'numcodecs.vlen', sources=sources, @@ -219,8 +213,6 @@ def vlen_extension(): ), ] - return extensions - def fletcher_extension(): info('setting up fletcher32 extension') @@ -235,7 +227,7 @@ def fletcher_extension(): sources = ['numcodecs/fletcher32.pyx'] # define extension module - extensions = [ + return [ Extension( 'numcodecs.fletcher32', sources=sources, @@ -245,8 +237,6 @@ def fletcher_extension(): ), ] - return extensions - def jenkins_extension(): info('setting up jenkins extension') @@ -261,7 +251,7 @@ def jenkins_extension(): sources = ['numcodecs/jenkins.pyx'] # define extension module - extensions = [ + return [ Extension( 'numcodecs.jenkins', sources=sources, @@ -271,8 +261,6 @@ def jenkins_extension(): ), ] - return extensions - def compat_extension(): info('setting up compat extension') @@ -282,7 +270,7 @@ def compat_extension(): sources = ['numcodecs/compat_ext.pyx'] # define extension module - extensions = [ + return [ Extension( 'numcodecs.compat_ext', sources=sources, @@ -290,8 +278,6 @@ def compat_extension(): ), ] - return extensions - def shuffle_extension(): info('setting up shuffle extension') @@ -301,12 +287,10 @@ def shuffle_extension(): sources = ['numcodecs/_shuffle.pyx'] # define extension module - extensions = [ + return [ Extension('numcodecs._shuffle', sources=sources, extra_compile_args=extra_compile_args), ] - return extensions - if sys.platform == 'win32': ext_errors = (CCompilerError, ExecError, PlatformError, IOError, ValueError)