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 dtype.descr
11+ FieldDescr = Union [Tuple [str , str ], Tuple [str , str , Tuple [int , ...]]]
12+ NumpyDescr = List [FieldDescr ]
13+
914
1015class Endianness (str , enum .Enum ):
1116 """
@@ -57,7 +62,7 @@ class Kind(str, enum.Enum):
5762 object = "O" # Object (i.e. the memory contains a pointer to PyObject)
5863
5964 @classmethod
60- def _missing_ (cls , key ):
65+ def _missing_ (cls , key : str ):
6166 if key == "O" :
6267 raise ObjectArrayTypeDisabled (
6368 "Numpy 'object'-type arrays are not enabled by default "
@@ -78,17 +83,19 @@ class BuiltinDtype:
7883 itemsize : int
7984 dt_units : Optional [str ] = None
8085
81- __endianness_map = {
86+ __endianness_map : ClassVar [ Mapping [ str , str ]] = {
8287 ">" : "big" ,
8388 "<" : "little" ,
8489 "=" : sys .byteorder ,
8590 "|" : "not_applicable" ,
8691 }
8792
88- __endianness_reverse_map = {"big" : ">" , "little" : "<" , "not_applicable" : "|" }
93+ __endianness_reverse_map : ClassVar [Mapping [str , str ]] = {
94+ v : k for k , v in __endianness_map .items () if k != "="
95+ }
8996
9097 @classmethod
91- def from_numpy_dtype (cls , dtype ) -> "BuiltinDtype" :
98+ def from_numpy_dtype (cls , dtype : numpy . dtype ) -> "BuiltinDtype" :
9299 # Extract datetime units from the dtype string representation,
93100 # e.g. `'<M8[ns]'` has `dt_units = '[ns]'`. Count determines the number of base units in a step.
94101 dt_units = None
@@ -106,7 +113,7 @@ def from_numpy_dtype(cls, dtype) -> "BuiltinDtype":
106113 def to_numpy_dtype (self ) -> numpy .dtype :
107114 return numpy .dtype (self .to_numpy_str ())
108115
109- def to_numpy_str (self ):
116+ def to_numpy_str (self ) -> str :
110117 endianness = self .__endianness_reverse_map [self .endianness ]
111118 # dtype.itemsize always reports bytes. The format string from the
112119 # numeric types the string format is: {type_code}{byte_count} so we can
@@ -125,7 +132,7 @@ def to_numpy_descr(self):
125132 return self .to_numpy_str ()
126133
127134 @classmethod
128- def from_json (cls , structure ) :
135+ def from_json (cls , structure : Mapping [ str , Any ]) -> "BuiltinDtype" :
129136 return cls (
130137 kind = Kind (structure ["kind" ]),
131138 itemsize = structure ["itemsize" ],
@@ -141,7 +148,7 @@ class Field:
141148 shape : Optional [Tuple [int , ...]]
142149
143150 @classmethod
144- def from_numpy_descr (cls , field ) :
151+ def from_numpy_descr (cls , field : FieldDescr ) -> "Field" :
145152 name , * rest = field
146153 if name == "" :
147154 raise ValueError (
@@ -159,7 +166,7 @@ def from_numpy_descr(cls, field):
159166 FType = StructDtype .from_numpy_dtype (numpy .dtype (f_type ))
160167 return cls (name = name , dtype = FType , shape = shape )
161168
162- def to_numpy_descr (self ):
169+ def to_numpy_descr (self ) -> FieldDescr :
163170 if isinstance (self .dtype , BuiltinDtype ):
164171 base = [self .name , self .dtype .to_numpy_str ()]
165172 else :
@@ -170,7 +177,7 @@ def to_numpy_descr(self):
170177 return tuple (base + [self .shape ])
171178
172179 @classmethod
173- def from_json (cls , structure ) :
180+ def from_json (cls , structure : Mapping [ str , Any ]) -> "Field" :
174181 name = structure ["name" ]
175182 if "fields" in structure ["dtype" ]:
176183 ftype = StructDtype .from_json (structure ["dtype" ])
@@ -185,7 +192,7 @@ class StructDtype:
185192 fields : List [Field ]
186193
187194 @classmethod
188- def from_numpy_dtype (cls , dtype ) :
195+ def from_numpy_dtype (cls , dtype : numpy . dtype ) -> "StructDtype" :
189196 # subdtypes push extra dimensions into arrays, we should handle these
190197 # a layer up and report an array with bigger dimensions.
191198 if dtype .subdtype is not None :
@@ -198,20 +205,20 @@ def from_numpy_dtype(cls, dtype):
198205 fields = [Field .from_numpy_descr (f ) for f in dtype .descr ],
199206 )
200207
201- def to_numpy_dtype (self ):
208+ def to_numpy_dtype (self ) -> numpy . dtype :
202209 return numpy .dtype (self .to_numpy_descr ())
203210
204- def to_numpy_descr (self ):
211+ def to_numpy_descr (self ) -> NumpyDescr :
205212 return [f .to_numpy_descr () for f in self .fields ]
206213
207- def max_depth (self ):
214+ def max_depth (self ) -> int :
208215 return max (
209216 1 if isinstance (f .dtype , BuiltinDtype ) else 1 + f .dtype .max_depth ()
210217 for f in self .fields
211218 )
212219
213220 @classmethod
214- def from_json (cls , structure ) :
221+ def from_json (cls , structure : Mapping [ str , Any ]) -> "StructDtype" :
215222 return cls (
216223 itemsize = structure ["itemsize" ],
217224 fields = [Field .from_json (f ) for f in structure ["fields" ]],
@@ -227,7 +234,7 @@ class ArrayStructure:
227234 resizable : Union [bool , Tuple [bool , ...]] = False
228235
229236 @classmethod
230- def from_json (cls , structure ) :
237+ def from_json (cls , structure : Mapping [ str , Any ]) -> "ArrayStructure" :
231238 if "fields" in structure ["data_type" ]:
232239 data_type = StructDtype .from_json (structure ["data_type" ])
233240 else :
@@ -273,7 +280,7 @@ def from_array(cls, array, shape=None, chunks=None, dims=None) -> "ArrayStructur
273280 data_type = StructDtype .from_numpy_dtype (array .dtype )
274281 else :
275282 data_type = BuiltinDtype .from_numpy_dtype (array .dtype )
276- return ArrayStructure (
283+ return cls (
277284 data_type = data_type ,
278285 shape = shape ,
279286 chunks = normalized_chunks ,
0 commit comments