forked from zarr-developers/zarr-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patharray_spec.py
More file actions
140 lines (115 loc) · 4.37 KB
/
array_spec.py
File metadata and controls
140 lines (115 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
from __future__ import annotations
from dataclasses import dataclass, fields
from typing import TYPE_CHECKING, Any, Literal, Self, TypedDict, cast
from zarr.core.common import (
MemoryOrder,
parse_bool,
parse_fill_value,
parse_order,
parse_shapelike,
)
from zarr.core.config import config as zarr_config
if TYPE_CHECKING:
from typing import NotRequired
from zarr.core.buffer import BufferPrototype
from zarr.core.dtype.wrapper import TBaseDType, TBaseScalar, ZDType
class ArrayConfigParams(TypedDict):
"""
A TypedDict model of the attributes of an ArrayConfig class, but with no required fields.
This allows for partial construction of an ArrayConfig, with the assumption that the unset
keys will be taken from a global configuration.
"""
order: NotRequired[MemoryOrder]
write_empty_chunks: NotRequired[bool]
read_missing_chunks: NotRequired[bool]
@dataclass(frozen=True)
class ArrayConfig:
"""
A model of the runtime configuration of an array.
Parameters
----------
order : MemoryOrder
The memory layout of the arrays returned when reading data from the store.
write_empty_chunks : bool
If True, empty chunks will be written to the store.
read_missing_chunks : bool
If True, missing chunks will be filled with the array's fill value on read.
If False, reading missing chunks will raise a ``ChunkNotFoundError``.
"""
order: MemoryOrder
write_empty_chunks: bool
read_missing_chunks: bool
def __init__(
self, order: MemoryOrder, write_empty_chunks: bool, *, read_missing_chunks: bool = True
) -> None:
order_parsed = parse_order(order)
write_empty_chunks_parsed = parse_bool(write_empty_chunks)
read_missing_chunks_parsed = parse_bool(read_missing_chunks)
object.__setattr__(self, "order", order_parsed)
object.__setattr__(self, "write_empty_chunks", write_empty_chunks_parsed)
object.__setattr__(self, "read_missing_chunks", read_missing_chunks_parsed)
@classmethod
def from_dict(cls, data: ArrayConfigParams) -> Self:
"""
Create an ArrayConfig from a dict. The keys of that dict are a subset of the
attributes of the ArrayConfig class. Any keys missing from that dict will be set to the
the values in the ``array`` namespace of ``zarr.config``.
"""
kwargs_out: ArrayConfigParams = {}
for f in fields(ArrayConfig):
field_name = cast(
"Literal['order', 'write_empty_chunks', 'read_missing_chunks']", f.name
)
if field_name not in data:
kwargs_out[field_name] = zarr_config.get(f"array.{field_name}")
else:
kwargs_out[field_name] = data[field_name]
return cls(**kwargs_out)
def to_dict(self) -> ArrayConfigParams:
"""
Serialize an instance of this class to a dict.
"""
return {
"order": self.order,
"write_empty_chunks": self.write_empty_chunks,
"read_missing_chunks": self.read_missing_chunks,
}
ArrayConfigLike = ArrayConfig | ArrayConfigParams
def parse_array_config(data: ArrayConfigLike | None) -> ArrayConfig:
"""
Convert various types of data to an ArrayConfig.
"""
if data is None:
return ArrayConfig.from_dict({})
elif isinstance(data, ArrayConfig):
return data
else:
return ArrayConfig.from_dict(data)
@dataclass(frozen=True)
class ArraySpec:
shape: tuple[int, ...]
dtype: ZDType[TBaseDType, TBaseScalar]
fill_value: Any
config: ArrayConfig
prototype: BufferPrototype
def __init__(
self,
shape: tuple[int, ...],
dtype: ZDType[TBaseDType, TBaseScalar],
fill_value: Any,
config: ArrayConfig,
prototype: BufferPrototype,
) -> None:
shape_parsed = parse_shapelike(shape)
fill_value_parsed = parse_fill_value(fill_value)
object.__setattr__(self, "shape", shape_parsed)
object.__setattr__(self, "dtype", dtype)
object.__setattr__(self, "fill_value", fill_value_parsed)
object.__setattr__(self, "config", config)
object.__setattr__(self, "prototype", prototype)
@property
def ndim(self) -> int:
return len(self.shape)
@property
def order(self) -> MemoryOrder:
return self.config.order