Skip to content

Commit 726fdfb

Browse files
authored
Simplify mypy config for tests (#2156)
* Simplify mypy config for tests * Add a list of test modules to expliclty ignore typing * More test mypy fixes * Remove old test_metadata file * Fix ignoring v2 tests * Fix name test
1 parent 67819a1 commit 726fdfb

18 files changed

+75
-57
lines changed

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ repos:
2525
rev: v1.11.2
2626
hooks:
2727
- id: mypy
28-
files: src|tests/v3/test_(api|array|buffer).py
28+
files: src|tests
2929
additional_dependencies:
3030
# Package dependencies
3131
- asciitree

pyproject.toml

+18-1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ python_version = "3.10"
225225
ignore_missing_imports = true
226226
namespace_packages = false
227227

228+
228229
strict = true
229230
warn_unreachable = true
230231

@@ -236,6 +237,22 @@ module = [
236237
]
237238
ignore_errors = true
238239

240+
[[tool.mypy.overrides]]
241+
module = [
242+
"tests.v2.*",
243+
"tests.v3.package_with_entrypoint.*",
244+
"tests.v3.test_codecs.*",
245+
"tests.v3.test_metadata.*",
246+
"tests.v3.test_store.*",
247+
"tests.v3.test_config",
248+
"tests.v3.test_group",
249+
"tests.v3.test_indexing",
250+
"tests.v3.test_properties",
251+
"tests.v3.test_sync",
252+
"tests.v3.test_v2",
253+
]
254+
ignore_errors = true
255+
239256
[tool.pytest.ini_options]
240257
minversion = "7"
241258
testpaths = ["tests"]
@@ -262,6 +279,6 @@ markers = [
262279

263280
[tool.repo-review]
264281
ignore = [
265-
"PC111", # fix Python code in documentation - enable later
282+
"PC111", # fix Python code in documentation - enable later
266283
"PC180", # for JavaScript - not interested
267284
]
File renamed without changes.

tests/v3/conftest.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
from __future__ import annotations
22

3+
import pathlib
4+
from dataclasses import dataclass, field
35
from typing import TYPE_CHECKING
46

7+
import numpy as np
8+
import numpy.typing as npt
9+
import pytest
10+
from hypothesis import HealthCheck, Verbosity, settings
11+
512
from zarr import AsyncGroup, config
13+
from zarr.store import LocalStore, MemoryStore, StorePath
14+
from zarr.store.remote import RemoteStore
615

716
if TYPE_CHECKING:
8-
from collections.abc import Iterator
17+
from collections.abc import Generator, Iterator
918
from types import ModuleType
1019
from typing import Any, Literal
1120

1221
from _pytest.compat import LEGACY_PATH
1322

1423
from zarr.abc.store import Store
1524
from zarr.core.common import ChunkCoords, MemoryOrder, ZarrFormat
16-
import pathlib
17-
from dataclasses import dataclass, field
18-
19-
import numpy as np
20-
import pytest
21-
from hypothesis import HealthCheck, Verbosity, settings
22-
23-
from zarr.store import LocalStore, MemoryStore, StorePath
24-
from zarr.store.remote import RemoteStore
2525

2626

2727
async def parse_store(
@@ -102,7 +102,7 @@ def xp(request: pytest.FixtureRequest) -> Iterator[ModuleType]:
102102

103103

104104
@pytest.fixture(autouse=True)
105-
def reset_config():
105+
def reset_config() -> Generator[None, None, None]:
106106
config.reset()
107107
yield
108108
config.reset()
@@ -116,7 +116,7 @@ class ArrayRequest:
116116

117117

118118
@pytest.fixture
119-
def array_fixture(request: pytest.FixtureRequest) -> np.ndarray:
119+
def array_fixture(request: pytest.FixtureRequest) -> npt.NDArray[Any]:
120120
array_request: ArrayRequest = request.param
121121
return (
122122
np.arange(np.prod(array_request.shape))

tests/v3/test_codec_entrypoints.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os.path
22
import sys
3+
from collections.abc import Generator
34

45
import pytest
56

@@ -10,7 +11,7 @@
1011

1112

1213
@pytest.fixture()
13-
def set_path():
14+
def set_path() -> Generator[None, None, None]:
1415
sys.path.append(here)
1516
zarr.registry._collect_entrypoints()
1617
yield
@@ -23,22 +24,22 @@ def set_path():
2324

2425
@pytest.mark.usefixtures("set_path")
2526
@pytest.mark.parametrize("codec_name", ["TestEntrypointCodec", "TestEntrypointGroup.Codec"])
26-
def test_entrypoint_codec(codec_name):
27+
def test_entrypoint_codec(codec_name: str) -> None:
2728
config.set({"codecs.test": "package_with_entrypoint." + codec_name})
2829
cls_test = zarr.registry.get_codec_class("test")
2930
assert cls_test.__qualname__ == codec_name
3031

3132

3233
@pytest.mark.usefixtures("set_path")
33-
def test_entrypoint_pipeline():
34+
def test_entrypoint_pipeline() -> None:
3435
config.set({"codec_pipeline.path": "package_with_entrypoint.TestEntrypointCodecPipeline"})
3536
cls = zarr.registry.get_pipeline_class()
3637
assert cls.__name__ == "TestEntrypointCodecPipeline"
3738

3839

3940
@pytest.mark.usefixtures("set_path")
4041
@pytest.mark.parametrize("buffer_name", ["TestEntrypointBuffer", "TestEntrypointGroup.Buffer"])
41-
def test_entrypoint_buffer(buffer_name):
42+
def test_entrypoint_buffer(buffer_name: str) -> None:
4243
config.set(
4344
{
4445
"buffer": "package_with_entrypoint." + buffer_name,

tests/v3/test_common.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def test_parse_shapelike_valid(data: Iterable[int]) -> None:
109109

110110
# todo: more dtypes
111111
@pytest.mark.parametrize("data", [("uint8", np.uint8), ("float64", np.float64)])
112-
def parse_dtype(data: tuple[str, np.dtype]) -> None:
112+
def parse_dtype(data: tuple[str, np.dtype[Any]]) -> None:
113113
unparsed, parsed = data
114114
assert parse_dtype(unparsed) == parsed
115115

tests/v3/test_config.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import zarr
1111
from zarr import Array, zeros
1212
from zarr.abc.codec import CodecInput, CodecOutput, CodecPipeline
13-
from zarr.abc.store import ByteSetter
13+
from zarr.abc.store import ByteSetter, Store
1414
from zarr.codecs import BatchedCodecPipeline, BloscCodec, BytesCodec, Crc32cCodec, ShardingCodec
1515
from zarr.core.array_spec import ArraySpec
1616
from zarr.core.buffer import NDBuffer
@@ -77,17 +77,18 @@ def test_config_defaults_can_be_overridden(key: str, old_val: Any, new_val: Any)
7777
assert config.get(key) == new_val
7878

7979

80-
def test_fully_qualified_name():
80+
def test_fully_qualified_name() -> None:
8181
class MockClass:
8282
pass
8383

84-
assert "v3.test_config.test_fully_qualified_name.<locals>.MockClass" == fully_qualified_name(
85-
MockClass
84+
assert (
85+
fully_qualified_name(MockClass)
86+
== "tests.v3.test_config.test_fully_qualified_name.<locals>.MockClass"
8687
)
8788

8889

8990
@pytest.mark.parametrize("store", ("local", "memory"), indirect=["store"])
90-
def test_config_codec_pipeline_class(store):
91+
def test_config_codec_pipeline_class(store: Store) -> None:
9192
# has default value
9293
assert get_pipeline_class().__name__ != ""
9394

@@ -138,7 +139,7 @@ class MockEnvCodecPipeline(CodecPipeline):
138139

139140

140141
@pytest.mark.parametrize("store", ("local", "memory"), indirect=["store"])
141-
def test_config_codec_implementation(store):
142+
def test_config_codec_implementation(store: Store) -> None:
142143
# has default value
143144
assert fully_qualified_name(get_codec_class("blosc")) == config.defaults[0]["codecs"]["blosc"]
144145

@@ -171,7 +172,7 @@ async def _encode_single(
171172

172173

173174
@pytest.mark.parametrize("store", ("local", "memory"), indirect=["store"])
174-
def test_config_ndbuffer_implementation(store):
175+
def test_config_ndbuffer_implementation(store: Store) -> None:
175176
# has default value
176177
assert fully_qualified_name(get_ndbuffer_class()) == config.defaults[0]["ndbuffer"]
177178

@@ -191,7 +192,7 @@ def test_config_ndbuffer_implementation(store):
191192
assert isinstance(got, TestNDArrayLike)
192193

193194

194-
def test_config_buffer_implementation():
195+
def test_config_buffer_implementation() -> None:
195196
# has default value
196197
assert fully_qualified_name(get_buffer_class()) == config.defaults[0]["buffer"]
197198

tests/v3/test_group.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,7 @@ async def test_asyncgroup_update_attributes(
681681
assert agroup_new_attributes.attrs == attributes_new
682682

683683

684-
async def test_group_members_async(store: LocalStore | MemoryStore):
684+
async def test_group_members_async(store: LocalStore | MemoryStore) -> None:
685685
group = AsyncGroup(
686686
GroupMetadata(),
687687
store_path=StorePath(store=store, path="root"),

tests/v3/test_indexing.py

+7-8
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,11 @@
2525
if TYPE_CHECKING:
2626
from collections.abc import Iterator
2727

28-
from zarr.abc.store import Store
2928
from zarr.core.common import ChunkCoords
3029

3130

3231
@pytest.fixture
33-
async def store() -> Iterator[Store]:
32+
async def store() -> Iterator[StorePath]:
3433
yield StorePath(await MemoryStore.open(mode="w"))
3534

3635

@@ -52,7 +51,7 @@ def zarr_array_from_numpy_array(
5251

5352
class CountingDict(MemoryStore):
5453
@classmethod
55-
async def open(cls):
54+
async def open(cls) -> CountingDict:
5655
store = await super().open(mode="w")
5756
store.counter = Counter()
5857
return store
@@ -68,7 +67,7 @@ async def set(self, key, value, byte_range=None):
6867
return await super().set(key, value, byte_range)
6968

7069

71-
def test_normalize_integer_selection():
70+
def test_normalize_integer_selection() -> None:
7271
assert 1 == normalize_integer_selection(1, 100)
7372
assert 99 == normalize_integer_selection(-1, 100)
7473
with pytest.raises(IndexError):
@@ -79,7 +78,7 @@ def test_normalize_integer_selection():
7978
normalize_integer_selection(-1000, 100)
8079

8180

82-
def test_replace_ellipsis():
81+
def test_replace_ellipsis() -> None:
8382
# 1D, single item
8483
assert (0,) == replace_ellipsis(0, (100,))
8584

@@ -258,7 +257,7 @@ def _test_get_basic_selection(a, z, selection):
258257

259258

260259
# noinspection PyStatementEffect
261-
def test_get_basic_selection_1d(store: StorePath):
260+
def test_get_basic_selection_1d(store: StorePath) -> None:
262261
# setup
263262
a = np.arange(1050, dtype=int)
264263
z = zarr_array_from_numpy_array(store, a, chunk_shape=(100,))
@@ -328,7 +327,7 @@ def test_get_basic_selection_1d(store: StorePath):
328327

329328

330329
# noinspection PyStatementEffect
331-
def test_get_basic_selection_2d(store: StorePath):
330+
def test_get_basic_selection_2d(store: StorePath) -> None:
332331
# setup
333332
a = np.arange(10000, dtype=int).reshape(1000, 10)
334333
z = zarr_array_from_numpy_array(store, a, chunk_shape=(300, 3))
@@ -349,7 +348,7 @@ def test_get_basic_selection_2d(store: StorePath):
349348
np.testing.assert_array_equal(z[fancy_selection], [0, 11])
350349

351350

352-
def test_fancy_indexing_fallback_on_get_setitem(store: StorePath):
351+
def test_fancy_indexing_fallback_on_get_setitem(store: StorePath) -> None:
353352
z = zarr_array_from_numpy_array(store, np.zeros((20, 20)))
354353
z[[1, 2, 3], [1, 2, 3]] = 1
355354
np.testing.assert_array_equal(

tests/v3/test_metadata/__init__.py

Whitespace-only changes.

tests/v3/test_metadata/test_v3.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ def test_metadata_to_dict(
237237

238238
@pytest.mark.parametrize("fill_value", [-1, 0, 1, 2932897])
239239
@pytest.mark.parametrize("precision", ["ns", "D"])
240-
async def test_datetime_metadata(fill_value: int, precision: str):
240+
async def test_datetime_metadata(fill_value: int, precision: str) -> None:
241241
metadata_dict = {
242242
"zarr_format": 3,
243243
"node_type": "array",

tests/v3/test_properties.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
@given(st.data())
14-
def test_roundtrip(data):
14+
def test_roundtrip(data: st.DataObject) -> None:
1515
nparray = data.draw(np_arrays)
1616
zarray = data.draw(arrays(arrays=st.just(nparray)))
1717
assert_array_equal(nparray, zarray[:])
@@ -23,7 +23,7 @@ def test_roundtrip(data):
2323
# Uncomment the next line to reproduce the original failure.
2424
# @reproduce_failure('6.111.2', b'AXicY2FgZGRAB/8/ndR2z7nkDZEDADWpBL4=')
2525
@pytest.mark.filterwarnings("ignore::RuntimeWarning")
26-
def test_basic_indexing(data):
26+
def test_basic_indexing(data: st.DataObject) -> None:
2727
zarray = data.draw(arrays())
2828
nparray = zarray[:]
2929
indexer = data.draw(basic_indices(shape=nparray.shape))
@@ -42,7 +42,7 @@ def test_basic_indexing(data):
4242
# Uncomment the next line to reproduce the original failure.
4343
# @reproduce_failure('6.111.2', b'AXicY2FgZGRAB/8/eLmF7qr/C5EDADZUBRM=')
4444
@pytest.mark.filterwarnings("ignore::RuntimeWarning")
45-
def test_vindex(data):
45+
def test_vindex(data: st.DataObject) -> None:
4646
zarray = data.draw(arrays())
4747
nparray = zarray[:]
4848

tests/v3/test_store/__init__.py

Whitespace-only changes.

tests/v3/test_store/test_core.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from zarr.store.memory import MemoryStore
88

99

10-
async def test_make_store_path(tmpdir) -> None:
10+
async def test_make_store_path(tmpdir: str) -> None:
1111
# None
1212
store_path = await make_store_path(None)
1313
assert isinstance(store_path.store, MemoryStore)
@@ -33,4 +33,4 @@ async def test_make_store_path(tmpdir) -> None:
3333
assert Path(store_path.store.root) == Path(tmpdir)
3434

3535
with pytest.raises(TypeError):
36-
await make_store_path(1)
36+
await make_store_path(1) # type: ignore[arg-type]

tests/v3/test_store/test_remote.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import os
2+
from collections.abc import Generator
23

4+
import botocore.client
35
import fsspec
46
import pytest
57
from upath import UPath
@@ -22,7 +24,7 @@
2224

2325

2426
@pytest.fixture(scope="module")
25-
def s3_base():
27+
def s3_base() -> Generator[None, None, None]:
2628
# writable local S3 system
2729

2830
# This fixture is module-scoped, meaning that we can reuse the MotoServer across all tests
@@ -37,7 +39,7 @@ def s3_base():
3739
server.stop()
3840

3941

40-
def get_boto3_client():
42+
def get_boto3_client() -> botocore.client.BaseClient:
4143
from botocore.session import Session
4244

4345
# NB: we use the sync botocore client for setup
@@ -46,7 +48,7 @@ def get_boto3_client():
4648

4749

4850
@pytest.fixture(autouse=True, scope="function")
49-
def s3(s3_base):
51+
def s3(s3_base) -> Generator[s3fs.S3FileSystem, None, None]:
5052
"""
5153
Quoting Martin Durant:
5254
pytest-asyncio creates a new event loop for each async test.
@@ -81,7 +83,7 @@ async def alist(it):
8183
return out
8284

8385

84-
async def test_basic():
86+
async def test_basic() -> None:
8587
store = await RemoteStore.open(
8688
f"s3://{test_bucket_name}", mode="w", endpoint_url=endpoint_url, anon=False
8789
)

0 commit comments

Comments
 (0)