Skip to content

Commit f3bee41

Browse files
committed
Disallow generic Any typing
1 parent a33ebf2 commit f3bee41

11 files changed

+46
-26
lines changed

pyproject.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ strict_concatenate = true
160160

161161
check_untyped_defs = true
162162
disallow_untyped_decorators = true
163+
disallow_any_generics = true
163164

164165
[[tool.mypy.overrides]]
165166
module = [
@@ -176,6 +177,21 @@ module = [
176177
]
177178
check_untyped_defs = false
178179

180+
[[tool.mypy.overrides]]
181+
module = [
182+
"zarr.v3.abc.codec",
183+
"zarr.v3.codecs.bytes",
184+
"zarr.v3.codecs.pipeline",
185+
"zarr.v3.codecs.sharding",
186+
"zarr.v3.codecs.transpose",
187+
"zarr.v3.array_v2",
188+
"zarr.v3.array",
189+
"zarr.v3.sync",
190+
"zarr.convenience",
191+
"zarr.meta",
192+
]
193+
disallow_any_generics = false
194+
179195

180196
[tool.pytest.ini_options]
181197
doctest_optionflags = [

src/zarr/_storage/store.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def assert_zarr_v3_api_available():
3232
) # pragma: no cover
3333

3434

35-
class BaseStore(MutableMapping):
35+
class BaseStore(MutableMapping[str, Any]):
3636
"""Abstract base class for store implementations.
3737
3838
This is a thin wrapper over MutableMapping that provides methods to check
@@ -405,7 +405,7 @@ def _ensure_store(store):
405405
)
406406

407407

408-
class StorageTransformer(MutableMapping, abc.ABC):
408+
class StorageTransformer(MutableMapping[str, Any], abc.ABC):
409409
"""Base class for storage transformers. The methods simply pass on the data as-is
410410
and should be overwritten by sub-classes."""
411411

@@ -548,7 +548,7 @@ def set_partial_values(self, key_start_values):
548548

549549

550550
# allow MutableMapping for backwards compatibility
551-
StoreLike = Union[BaseStore, MutableMapping]
551+
StoreLike = Union[BaseStore, MutableMapping[str, Any]]
552552

553553

554554
def _path_to_prefix(path: Optional[str]) -> str:

src/zarr/_storage/v3.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868

6969
Path = Union[str, bytes, None]
7070
# allow MutableMapping for backwards compatibility
71-
StoreLike = Union[BaseStore, MutableMapping]
71+
StoreLike = Union[BaseStore, MutableMapping[str, Any]]
7272

7373

7474
class RmdirV3:

src/zarr/_storage/v3_storage_transformers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from numcodecs.compat import ensure_bytes
77
import numpy as np
8+
import numpy.typing as npt
89

910
from zarr._storage.store import StorageTransformer, StoreV3, _rmdir_from_keys_v3
1011
from zarr.util import normalize_storage_path
@@ -27,7 +28,7 @@ def assert_zarr_v3_sharding_available():
2728
class _ShardIndex(NamedTuple):
2829
store: "ShardingStorageTransformer"
2930
# dtype uint64, shape (chunks_per_shard_0, chunks_per_shard_1, ..., 2)
30-
offsets_and_lengths: np.ndarray
31+
offsets_and_lengths: npt.NDArray[np.uint64]
3132

3233
def __localize_chunk__(self, chunk: Tuple[int, ...]) -> Tuple[int, ...]:
3334
return tuple(

src/zarr/attrs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from zarr.util import json_dumps
77

88

9-
class Attributes(MutableMapping):
9+
class Attributes(MutableMapping[str, Any]):
1010
"""Class providing access to user attributes on an array or group. Should not be
1111
instantiated directly, will be available via the `.attrs` property of an array or
1212
group.

src/zarr/convenience.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
from zarr._storage.v3 import ConsolidatedMetadataStoreV3
2525
from zarr.util import TreeViewer, buffer_size, normalize_storage_path
2626

27-
from typing import Union
27+
from typing import Any, Union
2828

29-
StoreLike = Union[BaseStore, MutableMapping, str, None]
29+
StoreLike = Union[BaseStore, MutableMapping[str, Any], str, None]
3030

3131
_builtin_open = open # builtin open is later shadowed by a local open function
3232

src/zarr/hierarchy.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from collections.abc import MutableMapping
22
from itertools import islice
3+
from typing import Any
34

45
import numpy as np
56

@@ -56,7 +57,7 @@
5657
)
5758

5859

59-
class Group(MutableMapping):
60+
class Group(MutableMapping[str, Any]):
6061
"""Instantiate a group from an initialized store.
6162
6263
Parameters

src/zarr/storage.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106

107107
Path = Union[str, bytes, None]
108108
# allow MutableMapping for backwards compatibility
109-
StoreLike = Union[BaseStore, MutableMapping]
109+
StoreLike = Union[BaseStore, MutableMapping[str, Any]]
110110

111111

112112
def contains_array(store: StoreLike, path: Path = None) -> bool:
@@ -248,7 +248,7 @@ def listdir(store: BaseStore, path: Path = None):
248248

249249
def _getsize(store: BaseStore, path: Path = None) -> int:
250250
# compute from size of values
251-
if path and path in store:
251+
if isinstance(path, str) and path in store:
252252
v = store[path]
253253
size = buffer_size(v)
254254
else:
@@ -737,7 +737,7 @@ def _init_group_metadata(
737737
store[key] = encode_group_metadata(meta)
738738

739739

740-
def _dict_store_keys(d: Dict, prefix="", cls=dict):
740+
def _dict_store_keys(d: dict[str, Any], prefix="", cls=dict):
741741
for k in d.keys():
742742
v = d[k]
743743
if isinstance(v, cls):

src/zarr/util.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
)
2121

2222
import numpy as np
23+
import numpy.typing as npt
2324
from asciitree import BoxStyle, LeftAligned
2425
from asciitree.traversal import Traversal
2526
from numcodecs.compat import (
@@ -36,7 +37,7 @@
3637
ValueType = TypeVar("ValueType")
3738

3839

39-
def flatten(arg: Iterable) -> Iterable:
40+
def flatten(arg: Iterable[Any]) -> Iterable[Any]:
4041
for element in arg:
4142
if isinstance(element, Iterable) and not isinstance(element, (str, bytes)):
4243
yield from flatten(element)
@@ -179,7 +180,7 @@ def normalize_chunks(chunks: Any, shape: Tuple[int, ...], typesize: int) -> Tupl
179180
return chunks
180181

181182

182-
def normalize_dtype(dtype: Union[str, np.dtype], object_codec) -> Tuple[np.dtype, Any]:
183+
def normalize_dtype(dtype: Union[str, npt.DTypeLike], object_codec) -> Tuple[np.dtype[Any], Any]:
183184
# convenience API for object arrays
184185
if inspect.isclass(dtype):
185186
dtype = dtype.__name__
@@ -291,7 +292,7 @@ def normalize_dimension_separator(sep: Optional[str]) -> Optional[str]:
291292
raise ValueError("dimension_separator must be either '.' or '/', found: %r" % sep)
292293

293294

294-
def normalize_fill_value(fill_value, dtype: np.dtype):
295+
def normalize_fill_value(fill_value, dtype: np.dtype[Any]):
295296
if fill_value is None or dtype.hasobject:
296297
# no fill value
297298
pass
@@ -668,7 +669,7 @@ def read_full(self):
668669

669670

670671
def retry_call(
671-
callabl: Callable,
672+
callabl: Callable[..., Any],
672673
args=None,
673674
kwargs=None,
674675
exceptions: Tuple[Any, ...] = (),

src/zarr/v3/common.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from __future__ import annotations
2-
from typing import TYPE_CHECKING, Union, Tuple, Iterable, Dict, List, TypeVar, overload
2+
from typing import TYPE_CHECKING, Union, Tuple, Iterable, Dict, List, TypeVar, overload, Any
33
import asyncio
44
import contextvars
55
from dataclasses import dataclass
@@ -28,7 +28,7 @@ def product(tup: ChunkCoords) -> int:
2828
return functools.reduce(lambda x, y: x * y, tup, 1)
2929

3030

31-
T = TypeVar("T", bound=Tuple)
31+
T = TypeVar("T", bound=Tuple[Any, ...])
3232
V = TypeVar("V")
3333

3434

@@ -76,7 +76,7 @@ def parse_enum(data: JSON, cls: Type[E]) -> E:
7676
@dataclass(frozen=True)
7777
class ArraySpec:
7878
shape: ChunkCoords
79-
dtype: np.dtype
79+
dtype: np.dtype[Any]
8080
fill_value: Any
8181

8282
def __init__(self, shape, dtype, fill_value):
@@ -102,7 +102,7 @@ def parse_name(data: JSON, expected: Optional[str] = None) -> str:
102102
raise TypeError(f"Expected a string, got an instance of {type(data)}.")
103103

104104

105-
def parse_configuration(data: JSON) -> dict:
105+
def parse_configuration(data: JSON) -> JSON:
106106
if not isinstance(data, dict):
107107
raise TypeError(f"Expected dict, got {type(data)}")
108108
return data
@@ -153,7 +153,7 @@ def parse_shapelike(data: Any) -> Tuple[int, ...]:
153153
return data_tuple
154154

155155

156-
def parse_dtype(data: Any) -> np.dtype:
156+
def parse_dtype(data: Any) -> np.dtype[Any]:
157157
# todo: real validation
158158
return np.dtype(data)
159159

src/zarr/v3/metadata.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from dataclasses import dataclass, field
55
import json
66
import numpy as np
7+
import numpy.typing as npt
78

89
from zarr.v3.chunk_grids import ChunkGrid, RegularChunkGrid
910
from zarr.v3.chunk_key_encodings import ChunkKeyEncoding, parse_separator
@@ -90,7 +91,7 @@ def to_numpy_shortname(self) -> str:
9091
return data_type_to_numpy[self]
9192

9293
@classmethod
93-
def from_dtype(cls, dtype: np.dtype) -> DataType:
94+
def from_dtype(cls, dtype: np.dtype[Any]) -> DataType:
9495
dtype_to_data_type = {
9596
"|b1": "bool",
9697
"bool": "bool",
@@ -111,7 +112,7 @@ def from_dtype(cls, dtype: np.dtype) -> DataType:
111112
@dataclass(frozen=True)
112113
class ArrayMetadata(Metadata):
113114
shape: ChunkCoords
114-
data_type: np.dtype
115+
data_type: np.dtype[Any]
115116
chunk_grid: ChunkGrid
116117
chunk_key_encoding: ChunkKeyEncoding
117118
fill_value: Any
@@ -176,7 +177,7 @@ def _validate_metadata(self) -> None:
176177
self.codecs.validate(self)
177178

178179
@property
179-
def dtype(self) -> np.dtype:
180+
def dtype(self) -> np.dtype[Any]:
180181
return self.data_type
181182

182183
@property
@@ -238,7 +239,7 @@ def to_dict(self) -> Dict[str, Any]:
238239
class ArrayV2Metadata(Metadata):
239240
shape: ChunkCoords
240241
chunks: ChunkCoords
241-
dtype: np.dtype
242+
dtype: np.dtype[Any]
242243
fill_value: Union[None, int, float] = 0
243244
order: Literal["C", "F"] = "C"
244245
filters: Optional[List[Dict[str, Any]]] = None
@@ -251,7 +252,7 @@ def __init__(
251252
self,
252253
*,
253254
shape: ChunkCoords,
254-
dtype: np.dtype,
255+
dtype: npt.DTypeLike,
255256
chunks: ChunkCoords,
256257
fill_value: Any,
257258
order: Literal["C", "F"],

0 commit comments

Comments
 (0)