Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 17 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,20 @@ jobs:
run: exit 1
- name: Success
run: echo Success!

pylint:
name: Pylint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.*'
- name: Install Pylint
run: |
python -m pip install --upgrade pip
pip install pylint
- name: Analyse the code with Pylint
run: |
pylint .
54 changes: 54 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -452,3 +452,57 @@ ignore-words-list = "astroid"

[project.entry-points.pytest11]
zarr = "zarr.testing"

[tool.pylint]
disable = [
"E0401", # import-error
"E0606", # possibly-used-before-assignment # FIXME
"E1123", # unexpected-keyword-arg # FIXME
"E1125", # missing-kwoa # FIXME
"E1136", # unsubscriptable-object
"W0104", # pointless-statement
"W0105", # pointless-string-statement
"W0106", # expression-not-assigned
"W0212", # protected-access
"W0223", # abstract-method # FIXME
"W0246", # useless-parent-delegation # FIXME
"W0511", # fixme
"W0602", # global-variable-not-assigned
"W0603", # global-statement
"W0611", # unused-import # FIXME
"W0613", # unused-argument
"W0621", # redefined-outer-name
"W0622", # redefined-builtin
"W0718", # broad-exception-caught
"W1510", # subprocess-run-check
"C0103", # invalid-name
"C0104", # disallowed-name
"C0105", # typevar-name-incorrect-variance
"C0114", # missing-module-docstring
"C0115", # missing-class-docstring
"C0116", # missing-function-docstring
"C0123", # unidiomatic-typecheck
"C0301", # line-too-long
"C0302", # too-many-lines
"C0411", # wrong-import-order
"C0412", # ungrouped-imports
"C0413", # wrong-import-position
"C0415", # import-outside-toplevel
"C1803", # use-implicit-booleaness-not-comparison
"R0124", # comparison-with-itself
"R0801", # duplicate-code
"R0902", # too-many-instance-attributes
"R0903", # too-few-public-methods
"R0904", # too-many-public-methods
"R0911", # too-many-return-statements
"R0912", # too-many-branches
"R0913", # too-many-arguments
"R0914", # too-many-locals
"R0915", # too-many-statements
"R0917", # too-many-positional-arguments
"R1702", # too-many-nested-blocks
"R1705", # no-else-return
"R1720", # no-else-raise
"R1728", # consider-using-generator
"R1732", # consider-using-with # FIXME
]
9 changes: 0 additions & 9 deletions src/zarr/abc/codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ def compute_encoded_size(self, input_byte_length: int, chunk_spec: ArraySpec) ->
-------
int
"""
...

def resolve_metadata(self, chunk_spec: ArraySpec) -> ArraySpec:
"""Computed the spec of the chunk after it has been encoded by the codec.
Expand Down Expand Up @@ -289,7 +288,6 @@ def evolve_from_array_spec(self, array_spec: ArraySpec) -> Self:
-------
Self
"""
...

@classmethod
@abstractmethod
Expand All @@ -304,7 +302,6 @@ def from_codecs(cls, codecs: Iterable[Codec]) -> Self:
-------
Self
"""
...

@classmethod
def from_array_metadata_and_store(cls, array_metadata: ArrayMetadata, store: Store) -> Self:
Expand Down Expand Up @@ -353,7 +350,6 @@ def validate(
chunk_grid : ChunkGrid
The array chunk grid
"""
...

@abstractmethod
def compute_encoded_size(self, byte_length: int, array_spec: ArraySpec) -> int:
Expand All @@ -369,7 +365,6 @@ def compute_encoded_size(self, byte_length: int, array_spec: ArraySpec) -> int:
-------
int
"""
...

@abstractmethod
async def decode(
Expand All @@ -388,7 +383,6 @@ async def decode(
-------
Iterable[NDBuffer | None]
"""
...

@abstractmethod
async def encode(
Expand All @@ -407,7 +401,6 @@ async def encode(
-------
Iterable[Buffer | None]
"""
...

@abstractmethod
async def read(
Expand All @@ -434,7 +427,6 @@ async def read(

out : NDBuffer
"""
...

@abstractmethod
async def write(
Expand All @@ -457,7 +449,6 @@ async def write(
The chunk spec contains information about the chunk.
value : NDBuffer
"""
...


async def _batching_helper(
Expand Down
4 changes: 0 additions & 4 deletions src/zarr/abc/numcodec.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ def encode(self, buf: Any) -> Any:
enc: Any
Encoded data.
"""
...

def decode(self, buf: Any, out: Any | None = None) -> Any:
"""
Expand All @@ -45,14 +44,12 @@ def decode(self, buf: Any, out: Any | None = None) -> Any:
dec : Any
Decoded data.
"""
...

def get_config(self) -> Any:
"""
Return a JSON-serializable configuration dictionary for this
codec. Must include an ``'id'`` field with the codec identifier.
"""
...

@classmethod
def from_config(cls, config: Any) -> Self:
Expand All @@ -64,7 +61,6 @@ def from_config(cls, config: Any) -> Self:
config : Any
A configuration dictionary for this codec.
"""
...


def _is_numcodec_cls(obj: object) -> TypeGuard[type[Numcodec]]:
Expand Down
9 changes: 0 additions & 9 deletions src/zarr/abc/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ def _check_writable(self) -> None:
@abstractmethod
def __eq__(self, value: object) -> bool:
"""Equality comparison."""
...

@abstractmethod
async def get(
Expand All @@ -204,7 +203,6 @@ async def get(
-------
Buffer
"""
...

@abstractmethod
async def get_partial_values(
Expand All @@ -225,7 +223,6 @@ async def get_partial_values(
-------
list of values, in the order of the key_ranges, may contain null/none for missing keys
"""
...

@abstractmethod
async def exists(self, key: str) -> bool:
Expand All @@ -239,13 +236,11 @@ async def exists(self, key: str) -> bool:
-------
bool
"""
...

@property
@abstractmethod
def supports_writes(self) -> bool:
"""Does the store support writes?"""
...

@abstractmethod
async def set(self, key: str, value: Buffer) -> None:
Expand All @@ -256,7 +251,6 @@ async def set(self, key: str, value: Buffer) -> None:
key : str
value : Buffer
"""
...

async def set_if_not_exists(self, key: str, value: Buffer) -> None:
"""
Expand Down Expand Up @@ -296,7 +290,6 @@ def supports_consolidated_metadata(self) -> bool:
@abstractmethod
def supports_deletes(self) -> bool:
"""Does the store support deletes?"""
...

@abstractmethod
async def delete(self, key: str) -> None:
Expand All @@ -306,7 +299,6 @@ async def delete(self, key: str) -> None:
----------
key : str
"""
...

@property
def supports_partial_writes(self) -> Literal[False]:
Expand All @@ -320,7 +312,6 @@ def supports_partial_writes(self) -> Literal[False]:
@abstractmethod
def supports_listing(self) -> bool:
"""Does the store support listing?"""
...

@abstractmethod
def list(self) -> AsyncIterator[str]:
Expand Down
12 changes: 0 additions & 12 deletions src/zarr/codecs/numcodecs/_codecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,6 @@ def __repr__(self) -> str:


class _NumcodecsBytesBytesCodec(_NumcodecsCodec, BytesBytesCodec):
def __init__(self, **codec_config: JSON) -> None:
super().__init__(**codec_config)

async def _decode_single(self, chunk_data: Buffer, chunk_spec: ArraySpec) -> Buffer:
return await asyncio.to_thread(
as_numpy_array_wrapper,
Expand All @@ -159,9 +156,6 @@ async def _encode_single(self, chunk_data: Buffer, chunk_spec: ArraySpec) -> Buf


class _NumcodecsArrayArrayCodec(_NumcodecsCodec, ArrayArrayCodec):
def __init__(self, **codec_config: JSON) -> None:
super().__init__(**codec_config)

async def _decode_single(self, chunk_data: NDBuffer, chunk_spec: ArraySpec) -> NDBuffer:
chunk_ndarray = chunk_data.as_ndarray_like()
out = await asyncio.to_thread(self._codec.decode, chunk_ndarray)
Expand All @@ -174,9 +168,6 @@ async def _encode_single(self, chunk_data: NDBuffer, chunk_spec: ArraySpec) -> N


class _NumcodecsArrayBytesCodec(_NumcodecsCodec, ArrayBytesCodec):
def __init__(self, **codec_config: JSON) -> None:
super().__init__(**codec_config)

async def _decode_single(self, chunk_data: Buffer, chunk_spec: ArraySpec) -> NDBuffer:
chunk_bytes = chunk_data.to_bytes()
out = await asyncio.to_thread(self._codec.decode, chunk_bytes)
Expand Down Expand Up @@ -253,9 +244,6 @@ def evolve_from_array_spec(self, array_spec: ArraySpec) -> FixedScaleOffset:


class Quantize(_NumcodecsArrayArrayCodec, codec_name="quantize"):
def __init__(self, **codec_config: JSON) -> None:
super().__init__(**codec_config)

def evolve_from_array_spec(self, array_spec: ArraySpec) -> Quantize:
if self.codec_config.get("dtype") is None:
dtype = array_spec.dtype.to_native_dtype()
Expand Down
3 changes: 0 additions & 3 deletions src/zarr/core/buffer/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ def as_numpy_array(self) -> npt.NDArray[Any]:
-------
NumPy array of this buffer (might be a data copy)
"""
...

def as_buffer_like(self) -> BytesLike:
"""Returns the buffer as an object that implements the Python buffer protocol.
Expand Down Expand Up @@ -296,7 +295,6 @@ def __len__(self) -> int:
@abstractmethod
def __add__(self, other: Buffer) -> Self:
"""Concatenate two buffers"""
...

def __eq__(self, other: object) -> bool:
# Another Buffer class can override this to choose a more efficient path
Expand Down Expand Up @@ -469,7 +467,6 @@ def as_numpy_array(self) -> npt.NDArray[Any]:
-------
NumPy array of this buffer (might be a data copy)
"""
...

def as_scalar(self) -> ScalarType:
"""Returns the buffer as a scalar value"""
Expand Down
2 changes: 1 addition & 1 deletion src/zarr/core/dtype/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def check_structured_dtype_v2_inner(data: object) -> TypeGuard[StructuredName_V2
return False
if len(data) != 2:
return False
if not (isinstance(data[0], str)):
if not isinstance(data[0], str):
return False
if isinstance(data[-1], str):
return True
Expand Down
8 changes: 5 additions & 3 deletions src/zarr/core/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -3208,11 +3208,13 @@ async def create_hierarchy(
nodes_parsed = _parse_hierarchy_dict(data=nodes_normed_keys)
redundant_implicit_groups = []

# empty hierarchies should be a no-op
if len(nodes_parsed) > 0:
try:
# figure out which zarr format we are using
zarr_format = next(iter(nodes_parsed.values())).zarr_format

except StopIteration:
# empty hierarchies should be a no-op
pass
else:
# check which implicit groups will require materialization
implicit_group_keys = tuple(
filter(lambda k: isinstance(nodes_parsed[k], ImplicitGroupMarker), nodes_parsed)
Expand Down
3 changes: 1 addition & 2 deletions src/zarr/core/metadata/v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,10 @@ def parse_filters(data: object) -> tuple[Numcodec, ...] | None:
"""
Parse a potential tuple of filters
"""
out: list[Numcodec] = []

if data is None:
return data
if isinstance(data, Iterable):
out: list[Numcodec] = []
for idx, val in enumerate(data):
if _is_numcodec(val):
out.append(val)
Expand Down
2 changes: 2 additions & 0 deletions src/zarr/storage/_zip.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def __init__(
assert isinstance(path, Path)
self.path = path # root?

self._is_open = False
self._zmode = mode
self.compression = compression
self.allowZip64 = allowZip64
Expand Down Expand Up @@ -123,6 +124,7 @@ def close(self) -> None:
super().close()
with self._lock:
self._zf.close()
self._is_open = False

async def clear(self) -> None:
# docstring inherited
Expand Down
2 changes: 1 addition & 1 deletion src/zarr/testing/stateful.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def add_array(
@with_frequency(0.25)
def clear(self) -> None:
note("clearing")
import zarr
import zarr # pylint: disable=reimported

self._sync(self.store.clear())
self._sync(self.model.clear())
Expand Down
Loading