1
1
from __future__ import annotations
2
2
3
3
import logging
4
- from typing import TYPE_CHECKING
4
+ from typing import TYPE_CHECKING , TypedDict
5
5
6
6
import pytest
7
7
11
11
from zarr .testing .store import StoreTests
12
12
13
13
if TYPE_CHECKING :
14
- from _pytest . compat import LEGACY_PATH
14
+ from pathlib import Path
15
15
16
16
from zarr .abc .store import Store
17
17
18
18
19
- class TestLoggingStore (StoreTests [LoggingStore , cpu .Buffer ]):
20
- store_cls = LoggingStore
19
+ class StoreKwargs (TypedDict ):
20
+ store : LocalStore
21
+ log_level : str
22
+
23
+
24
+ class TestLoggingStore (StoreTests [LoggingStore [LocalStore ], cpu .Buffer ]):
25
+ store_cls = LoggingStore [LocalStore ]
21
26
buffer_cls = cpu .Buffer
22
27
23
- async def get (self , store : LoggingStore , key : str ) -> Buffer :
28
+ async def get (self , store : LoggingStore [ LocalStore ] , key : str ) -> Buffer :
24
29
return self .buffer_cls .from_bytes ((store ._store .root / key ).read_bytes ())
25
30
26
- async def set (self , store : LoggingStore , key : str , value : Buffer ) -> None :
31
+ async def set (self , store : LoggingStore [ LocalStore ] , key : str , value : Buffer ) -> None :
27
32
parent = (store ._store .root / key ).parent
28
33
if not parent .exists ():
29
34
parent .mkdir (parents = True )
30
35
(store ._store .root / key ).write_bytes (value .to_bytes ())
31
36
32
37
@pytest .fixture
33
- def store_kwargs (self , tmpdir : LEGACY_PATH ) -> dict [ str , str ] :
34
- return {"store" : LocalStore (str (tmpdir )), "log_level" : "DEBUG" }
38
+ def store_kwargs (self , tmp_path : Path ) -> StoreKwargs :
39
+ return {"store" : LocalStore (str (tmp_path )), "log_level" : "DEBUG" }
35
40
36
41
@pytest .fixture
37
- def open_kwargs (self , tmpdir ) -> dict [str , str ]:
38
- return {"store_cls" : LocalStore , "root" : str (tmpdir ), "log_level" : "DEBUG" }
42
+ def open_kwargs (self , tmp_path : Path ) -> dict [str , type [ LocalStore ] | str ]:
43
+ return {"store_cls" : LocalStore , "root" : str (tmp_path ), "log_level" : "DEBUG" }
39
44
40
45
@pytest .fixture
41
- def store (self , store_kwargs : str | dict [ str , Buffer ] | None ) -> LoggingStore :
46
+ def store (self , store_kwargs : StoreKwargs ) -> LoggingStore [ LocalStore ] :
42
47
return self .store_cls (** store_kwargs )
43
48
44
- def test_store_supports_writes (self , store : LoggingStore ) -> None :
49
+ def test_store_supports_writes (self , store : LoggingStore [ LocalStore ] ) -> None :
45
50
assert store .supports_writes
46
51
47
- def test_store_supports_partial_writes (self , store : LoggingStore ) -> None :
52
+ def test_store_supports_partial_writes (self , store : LoggingStore [ LocalStore ] ) -> None :
48
53
assert store .supports_partial_writes
49
54
50
- def test_store_supports_listing (self , store : LoggingStore ) -> None :
55
+ def test_store_supports_listing (self , store : LoggingStore [ LocalStore ] ) -> None :
51
56
assert store .supports_listing
52
57
53
- def test_store_repr (self , store : LoggingStore ) -> None :
58
+ def test_store_repr (self , store : LoggingStore [ LocalStore ] ) -> None :
54
59
assert f"{ store !r} " == f"LoggingStore(LocalStore, 'file://{ store ._store .root .as_posix ()} ')"
55
60
56
- def test_store_str (self , store : LoggingStore ) -> None :
61
+ def test_store_str (self , store : LoggingStore [ LocalStore ] ) -> None :
57
62
assert str (store ) == f"logging-file://{ store ._store .root .as_posix ()} "
58
63
59
- async def test_default_handler (self , local_store , capsys ) -> None :
64
+ async def test_default_handler (
65
+ self , local_store : LocalStore , capsys : pytest .CaptureFixture [str ]
66
+ ) -> None :
60
67
# Store and then remove existing handlers to enter default handler code path
61
68
handlers = logging .getLogger ().handlers [:]
62
69
for h in handlers :
63
70
logging .getLogger ().removeHandler (h )
64
71
# Test logs are sent to stdout
65
72
wrapped = LoggingStore (store = local_store )
66
73
buffer = default_buffer_prototype ().buffer
67
- res = await wrapped .set ("foo/bar/c/0" , buffer .from_bytes (b"\x01 \x02 \x03 \x04 " ))
74
+ res = await wrapped .set ("foo/bar/c/0" , buffer .from_bytes (b"\x01 \x02 \x03 \x04 " )) # type: ignore[func-returns-value]
68
75
assert res is None
69
76
captured = capsys .readouterr ()
70
77
assert len (captured ) == 2
@@ -74,7 +81,7 @@ async def test_default_handler(self, local_store, capsys) -> None:
74
81
for h in handlers :
75
82
logging .getLogger ().addHandler (h )
76
83
77
- def test_is_open_setter_raises (self , store : LoggingStore ) -> None :
84
+ def test_is_open_setter_raises (self , store : LoggingStore [ LocalStore ] ) -> None :
78
85
"Test that a user cannot change `_is_open` without opening the underlying store."
79
86
with pytest .raises (
80
87
NotImplementedError , match = "LoggingStore must be opened via the `_open` method"
@@ -83,12 +90,12 @@ def test_is_open_setter_raises(self, store: LoggingStore) -> None:
83
90
84
91
85
92
@pytest .mark .parametrize ("store" , ["local" , "memory" , "zip" ], indirect = ["store" ])
86
- async def test_logging_store (store : Store , caplog ) -> None :
93
+ async def test_logging_store (store : Store , caplog : pytest . LogCaptureFixture ) -> None :
87
94
wrapped = LoggingStore (store = store , log_level = "DEBUG" )
88
95
buffer = default_buffer_prototype ().buffer
89
96
90
97
caplog .clear ()
91
- res = await wrapped .set ("foo/bar/c/0" , buffer .from_bytes (b"\x01 \x02 \x03 \x04 " ))
98
+ res = await wrapped .set ("foo/bar/c/0" , buffer .from_bytes (b"\x01 \x02 \x03 \x04 " )) # type: ignore[func-returns-value]
92
99
assert res is None
93
100
assert len (caplog .record_tuples ) == 2
94
101
for tup in caplog .record_tuples :
0 commit comments