@@ -21,18 +21,23 @@ _NoDefault = object()
2121
2222cdef class HashTableNT:
2323 def __init__ (self , items = None , *,
24- key_size: int = 0 , value_format: str = " " , value_type : Any = None ,
24+ key_size: int , value_type: Any , value_format : Any ,
2525 capacity: int = MIN_CAPACITY) -> None:
26- if not key_size:
27- raise ValueError("key_size must be specified and must be > 0.")
28- if not value_format:
29- raise ValueError("value_format must be specified and must be non-empty.")
30- if value_type is None:
31- raise ValueError("value_type must be specified (a namedtuple type corresponding to value_format ).")
26+ if not isinstance(key_size , int ) or not key_size > 0:
27+ raise ValueError("key_size must be an integer and > 0.")
28+ if type(value_type ) is not type:
29+ raise TypeError("value_type must be a namedtuple type.")
30+ if not isinstance(value_format , tuple ):
31+ raise TypeError (" value_format must be a namedtuple instance." )
32+ if value_format._fields != value_type._fields:
33+ raise TypeError (" value_format's and value_type's element names must correspond." )
34+ if not all (isinstance (fmt, str ) and len (fmt) > 0 for fmt in value_format):
35+ raise ValueError (" value_format's elements must be str and non-empty." )
3236 self .key_size = key_size
33- self.value_struct = struct .Struct(value_format)
34- self.value_size = self .value_struct.size
3537 self .value_type = value_type
38+ self .value_format = value_format
39+ self .value_struct = struct .Struct(" " .join(value_format))
40+ self .value_size = self .value_struct.size
3641 self .inner = HashTable(key_size = self .key_size, value_size = self .value_size, capacity = capacity)
3742 _fill(self , items)
3843
@@ -159,9 +164,11 @@ cdef class HashTableNT:
159164 meta = {
160165 ' key_size' : self .key_size,
161166 ' value_size' : self .value_size,
162- ' value_format' : self .value_struct.format,
163167 ' value_type_name' : self .value_type.__name__ ,
164168 ' value_type_fields' : self .value_type._fields,
169+ ' value_format_name' : self .value_format.__class__ .__name__ ,
170+ ' value_format_fields' : self .value_format._fields,
171+ ' value_format' : self .value_format,
165172 ' capacity' : self .inner.capacity,
166173 ' used' : self .inner.used, # count of keys / values
167174 }
@@ -201,7 +208,9 @@ cdef class HashTableNT:
201208 raise ValueError (f" Invalid file, file is too short." )
202209 meta = json.loads(meta_bytes.decode(" utf-8" ))
203210 value_type = namedtuple(meta[' value_type_name' ], meta[' value_type_fields' ])
204- ht = cls (key_size = meta[' key_size' ], value_format = meta[' value_format' ], value_type = value_type, capacity = meta[' capacity' ])
211+ value_format_t = namedtuple(meta[' value_format_name' ], meta[' value_format_fields' ])
212+ value_format = value_format_t(* meta[' value_format' ])
213+ ht = cls (key_size = meta[' key_size' ], value_format = value_format, value_type = value_type, capacity = meta[' capacity' ])
205214 count = 0
206215 ksize, vsize = meta[' key_size' ], meta[' value_size' ]
207216 for i in range (meta[' used' ]):
0 commit comments