11import enum
22import os
33import sys
4+ from collections .abc import Mapping
45from dataclasses import dataclass
5- from typing import List , Optional , Tuple , Union
6+ from typing import Any , ClassVar , List , Optional , Tuple , Union
67
78import numpy
89
10+ from tiled .structures .root import Structure
11+
12+ # from dtype.descr
13+ FieldDescr = Union [Tuple [str , str ], Tuple [str , str , Tuple [int , ...]]]
14+ NumpyDescr = List [FieldDescr ]
15+
916
1017class Endianness (str , enum .Enum ):
1118 """
@@ -57,7 +64,7 @@ class Kind(str, enum.Enum):
5764 object = "O" # Object (i.e. the memory contains a pointer to PyObject)
5865
5966 @classmethod
60- def _missing_ (cls , key ):
67+ def _missing_ (cls , key : str ):
6168 if key == "O" :
6269 raise ObjectArrayTypeDisabled (
6370 "Numpy 'object'-type arrays are not enabled by default "
@@ -78,17 +85,19 @@ class BuiltinDtype:
7885 itemsize : int
7986 dt_units : Optional [str ] = None
8087
81- __endianness_map = {
88+ __endianness_map : ClassVar [ Mapping [ str , str ]] = {
8289 ">" : "big" ,
8390 "<" : "little" ,
8491 "=" : sys .byteorder ,
8592 "|" : "not_applicable" ,
8693 }
8794
88- __endianness_reverse_map = {"big" : ">" , "little" : "<" , "not_applicable" : "|" }
95+ __endianness_reverse_map : ClassVar [Mapping [str , str ]] = {
96+ v : k for k , v in __endianness_map .items () if k != "="
97+ }
8998
9099 @classmethod
91- def from_numpy_dtype (cls , dtype ) -> "BuiltinDtype" :
100+ def from_numpy_dtype (cls , dtype : numpy . dtype ) -> "BuiltinDtype" :
92101 # Extract datetime units from the dtype string representation,
93102 # e.g. `'<M8[ns]'` has `dt_units = '[ns]'`. Count determines the number of base units in a step.
94103 dt_units = None
@@ -106,7 +115,7 @@ def from_numpy_dtype(cls, dtype) -> "BuiltinDtype":
106115 def to_numpy_dtype (self ) -> numpy .dtype :
107116 return numpy .dtype (self .to_numpy_str ())
108117
109- def to_numpy_str (self ):
118+ def to_numpy_str (self ) -> str :
110119 endianness = self .__endianness_reverse_map [self .endianness ]
111120 # dtype.itemsize always reports bytes. The format string from the
112121 # numeric types the string format is: {type_code}{byte_count} so we can
@@ -125,7 +134,7 @@ def to_numpy_descr(self):
125134 return self .to_numpy_str ()
126135
127136 @classmethod
128- def from_json (cls , structure ) :
137+ def from_json (cls , structure : Mapping [ str , Any ]) -> "BuiltinDtype" :
129138 return cls (
130139 kind = Kind (structure ["kind" ]),
131140 itemsize = structure ["itemsize" ],
@@ -141,7 +150,7 @@ class Field:
141150 shape : Optional [Tuple [int , ...]]
142151
143152 @classmethod
144- def from_numpy_descr (cls , field ) :
153+ def from_numpy_descr (cls , field : FieldDescr ) -> "Field" :
145154 name , * rest = field
146155 if name == "" :
147156 raise ValueError (
@@ -159,7 +168,7 @@ def from_numpy_descr(cls, field):
159168 FType = StructDtype .from_numpy_dtype (numpy .dtype (f_type ))
160169 return cls (name = name , dtype = FType , shape = shape )
161170
162- def to_numpy_descr (self ):
171+ def to_numpy_descr (self ) -> FieldDescr :
163172 if isinstance (self .dtype , BuiltinDtype ):
164173 base = [self .name , self .dtype .to_numpy_str ()]
165174 else :
@@ -170,7 +179,7 @@ def to_numpy_descr(self):
170179 return tuple (base + [self .shape ])
171180
172181 @classmethod
173- def from_json (cls , structure ) :
182+ def from_json (cls , structure : Mapping [ str , Any ]) -> "Field" :
174183 name = structure ["name" ]
175184 if "fields" in structure ["dtype" ]:
176185 ftype = StructDtype .from_json (structure ["dtype" ])
@@ -185,7 +194,7 @@ class StructDtype:
185194 fields : List [Field ]
186195
187196 @classmethod
188- def from_numpy_dtype (cls , dtype ) :
197+ def from_numpy_dtype (cls , dtype : numpy . dtype ) -> "StructDtype" :
189198 # subdtypes push extra dimensions into arrays, we should handle these
190199 # a layer up and report an array with bigger dimensions.
191200 if dtype .subdtype is not None :
@@ -198,36 +207,36 @@ def from_numpy_dtype(cls, dtype):
198207 fields = [Field .from_numpy_descr (f ) for f in dtype .descr ],
199208 )
200209
201- def to_numpy_dtype (self ):
210+ def to_numpy_dtype (self ) -> numpy . dtype :
202211 return numpy .dtype (self .to_numpy_descr ())
203212
204- def to_numpy_descr (self ):
213+ def to_numpy_descr (self ) -> NumpyDescr :
205214 return [f .to_numpy_descr () for f in self .fields ]
206215
207- def max_depth (self ):
216+ def max_depth (self ) -> int :
208217 return max (
209218 1 if isinstance (f .dtype , BuiltinDtype ) else 1 + f .dtype .max_depth ()
210219 for f in self .fields
211220 )
212221
213222 @classmethod
214- def from_json (cls , structure ) :
223+ def from_json (cls , structure : Mapping [ str , Any ]) -> "StructDtype" :
215224 return cls (
216225 itemsize = structure ["itemsize" ],
217226 fields = [Field .from_json (f ) for f in structure ["fields" ]],
218227 )
219228
220229
221230@dataclass
222- class ArrayStructure :
231+ class ArrayStructure ( Structure ) :
223232 data_type : Union [BuiltinDtype , StructDtype ]
224233 chunks : Tuple [Tuple [int , ...], ...] # tuple-of-tuples-of-ints like ((3,), (3,))
225234 shape : Tuple [int , ...] # tuple of ints like (3, 3)
226235 dims : Optional [Tuple [str , ...]] = None # None or tuple of names like ("x", "y")
227236 resizable : Union [bool , Tuple [bool , ...]] = False
228237
229238 @classmethod
230- def from_json (cls , structure ) :
239+ def from_json (cls , structure : Mapping [ str , Any ]) -> "ArrayStructure" :
231240 if "fields" in structure ["data_type" ]:
232241 data_type = StructDtype .from_json (structure ["data_type" ])
233242 else :
@@ -273,7 +282,7 @@ def from_array(cls, array, shape=None, chunks=None, dims=None) -> "ArrayStructur
273282 data_type = StructDtype .from_numpy_dtype (array .dtype )
274283 else :
275284 data_type = BuiltinDtype .from_numpy_dtype (array .dtype )
276- return ArrayStructure (
285+ return cls (
277286 data_type = data_type ,
278287 shape = shape ,
279288 chunks = normalized_chunks ,
0 commit comments