Skip to content

Commit f046322

Browse files
dstansbyd-v-b
andauthored
Disallow generic Any typing (#1794)
Co-authored-by: Davis Bennett <[email protected]>
1 parent 368b170 commit f046322

File tree

9 files changed

+42
-23
lines changed

9 files changed

+42
-23
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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
DEFAULT_ZARR_VERSION = 2
1515

1616

17-
class BaseStore(MutableMapping):
17+
class BaseStore(MutableMapping[str, Any]):
1818
"""Abstract base class for store implementations.
1919
2020
This is a thin wrapper over MutableMapping that provides methods to check
@@ -165,7 +165,7 @@ def rmdir(self, path: str = "") -> None:
165165

166166

167167
# allow MutableMapping for backwards compatibility
168-
StoreLike = Union[BaseStore, MutableMapping]
168+
StoreLike = Union[BaseStore, MutableMapping[str, Any]]
169169

170170

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

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
@@ -20,9 +20,9 @@
2020
)
2121
from zarr.util import TreeViewer, buffer_size, normalize_storage_path
2222

23-
from typing import Union
23+
from typing import Any, Union
2424

25-
StoreLike = Union[BaseStore, MutableMapping, str, None]
25+
StoreLike = Union[BaseStore, MutableMapping[str, Any], str, None]
2626

2727
_builtin_open = open # builtin open is later shadowed by a local open function
2828

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

@@ -48,7 +49,7 @@
4849
)
4950

5051

51-
class Group(MutableMapping):
52+
class Group(MutableMapping[str, Any]):
5253
"""Instantiate a group from an initialized store.
5354
5455
Parameters

src/zarr/storage.py

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

100100
Path = Union[str, bytes, None]
101101
# allow MutableMapping for backwards compatibility
102-
StoreLike = Union[BaseStore, MutableMapping]
102+
StoreLike = Union[BaseStore, MutableMapping[str, Any]]
103103

104104

105105
def contains_array(store: StoreLike, path: Path = None) -> bool:
@@ -202,7 +202,7 @@ def listdir(store: BaseStore, path: Path = None):
202202

203203
def _getsize(store: BaseStore, path: Path = None) -> int:
204204
# compute from size of values
205-
if path and path in store:
205+
if isinstance(path, str) and path in store:
206206
v = store[path]
207207
size = buffer_size(v)
208208
else:
@@ -584,7 +584,7 @@ def _init_group_metadata(
584584
store[key] = encode_group_metadata(meta)
585585

586586

587-
def _dict_store_keys(d: Dict, prefix="", cls=dict):
587+
def _dict_store_keys(d: dict[str, Any], prefix="", cls=dict):
588588
for k in d.keys():
589589
v = d[k]
590590
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)