11"""
2- (De)serialization methods for python datatypes and numpy.ndarrays with provisions for mutual
2+ (De)serialization methods for basic datatypes and numpy.ndarrays with provisions for mutual
33compatibility with Matlab-based serialization implemented by mYm.
44"""
55
@@ -115,21 +115,25 @@ def read_blob(self, n_bytes=None):
115115 "P" : self .read_sparse_array , # matlab sparse array -- not supported yet
116116 "S" : self .read_struct , # matlab struct array
117117 "C" : self .read_cell_array , # matlab cell array
118- # Python-native
119- "\xFF " : self .read_none , # None
120- "\1 " : self .read_tuple , # a Sequence
121- "\2 " : self .read_list , # a MutableSequence
122- "\3 " : self .read_set , # a Set
123- "\4 " : self .read_dict , # a Mapping
124- "\5 " : self .read_string , # a UTF8-encoded string
125- "\6 " : self .read_bytes , # a ByteString
126- "F" : self .read_recarray , # numpy array with fields, including recarrays
127- "d" : self .read_decimal , # a decimal
128- "t" : self .read_datetime , # date, time, or datetime
129- "u" : self .read_uuid , # UUID
118+ # basic data types
119+ "\xFF " : self .read_none , # None
120+ "\x01 " : self .read_tuple , # a Sequence (e.g. tuple)
121+ "\x02 " : self .read_list , # a MutableSequence (e.g. list)
122+ "\x03 " : self .read_set , # a Set
123+ "\x04 " : self .read_dict , # a Mapping (e.g. dict)
124+ "\x05 " : self .read_string , # a UTF8-encoded string
125+ "\x06 " : self .read_bytes , # a ByteString
126+ "\x0a " : self .read_int , # unbounded scalar int
127+ "\x0b " : self .read_bool , # scalar boolean
128+ "\x0c " : self .read_complex , # scalar 128-bit complex number
129+ "\x0d " : self .read_float , # scalar 64-bit float
130+ "F" : self .read_recarray , # numpy array with fields, including recarrays
131+ "d" : self .read_decimal , # a decimal
132+ "t" : self .read_datetime , # date, time, or datetime
133+ "u" : self .read_uuid , # UUID
130134 }[data_structure_code ]
131135 except KeyError :
132- raise DataJointError ('Unknown data structure code "%s"' % data_structure_code )
136+ raise DataJointError ('Unknown data structure code "%s". Upgrade datajoint. ' % data_structure_code )
133137 v = call ()
134138 if n_bytes is not None and self ._pos - start != n_bytes :
135139 raise DataJointError ('Blob length check failed! Invalid blob' )
@@ -146,13 +150,21 @@ def pack_blob(self, obj):
146150
147151 # blob types in the expanded dj0 blob format
148152 self .set_dj0 ()
153+ if not isinstance (obj , (np .ndarray , np .number )):
154+ # python built-in data types
155+ if isinstance (obj , bool ):
156+ return self .pack_bool (obj )
157+ if isinstance (obj , int ):
158+ return self .pack_int (obj )
159+ if isinstance (obj , complex ):
160+ return self .pack_complex (obj )
161+ if isinstance (obj , float ):
162+ return self .pack_float (obj )
149163 if isinstance (obj , np .ndarray ) and obj .dtype .fields :
150164 return self .pack_recarray (np .array (obj ))
151165 if isinstance (obj , np .number ):
152166 return self .pack_array (np .array (obj ))
153- if isinstance (obj , (bool , np .bool , np .bool_ )):
154- return self .pack_array (np .array (obj ))
155- if isinstance (obj , (float , int , complex )):
167+ if isinstance (obj , (np .bool , np .bool_ )):
156168 return self .pack_array (np .array (obj ))
157169 if isinstance (obj , (datetime .datetime , datetime .date , datetime .time )):
158170 return self .pack_datetime (obj )
@@ -209,7 +221,7 @@ def pack_array(self, array):
209221 if is_complex :
210222 array , imaginary = np .real (array ), np .imag (array )
211223 type_id = (rev_class_id [array .dtype ] if array .dtype .char != 'U'
212- else rev_class_id [np .dtype ('O' )])
224+ else rev_class_id [np .dtype ('O' )])
213225 if dtype_list [type_id ] is None :
214226 raise DataJointError ("Type %s is ambiguous or unknown" % array .dtype )
215227
@@ -251,6 +263,36 @@ def pack_recarray(self, array):
251263 def read_sparse_array (self ):
252264 raise DataJointError ('datajoint-python does not yet support sparse arrays. Issue (#590)' )
253265
266+ def read_int (self ):
267+ return int .from_bytes (self .read_binary (self .read_value ('uint16' )), byteorder = 'little' , signed = True )
268+
269+ @staticmethod
270+ def pack_int (v ):
271+ n_bytes = v .bit_length () // 8 + 1
272+ assert 0 < n_bytes <= 0xFFFF , 'Integers are limited to 65535 bytes'
273+ return b"\x0a " + np .uint16 (n_bytes ).tobytes () + v .to_bytes (n_bytes , byteorder = 'little' , signed = True )
274+
275+ def read_bool (self ):
276+ return bool (self .read_value ('bool' ))
277+
278+ @staticmethod
279+ def pack_bool (v ):
280+ return b"\x0b " + np .array (v , dtype = 'bool' ).tobytes ()
281+
282+ def read_complex (self ):
283+ return complex (self .read_value ('complex128' ))
284+
285+ @staticmethod
286+ def pack_complex (v ):
287+ return b"\x0c " + np .array (v , dtype = 'complex128' ).tobytes ()
288+
289+ def read_float (self ):
290+ return float (self .read_value ('float64' ))
291+
292+ @staticmethod
293+ def pack_float (v ):
294+ return b"\x0d " + np .array (v , dtype = 'float64' ).tobytes ()
295+
254296 def read_decimal (self ):
255297 return Decimal (self .read_string ())
256298
@@ -269,7 +311,7 @@ def pack_string(s):
269311
270312 def read_bytes (self ):
271313 return self .read_binary (self .read_value ())
272-
314+
273315 @staticmethod
274316 def pack_bytes (s ):
275317 return b"\6 " + len_u64 (s ) + s
0 commit comments