1
1
"""
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
3
3
compatibility with Matlab-based serialization implemented by mYm.
4
4
"""
5
5
@@ -115,21 +115,25 @@ def read_blob(self, n_bytes=None):
115
115
"P" : self .read_sparse_array , # matlab sparse array -- not supported yet
116
116
"S" : self .read_struct , # matlab struct array
117
117
"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
130
134
}[data_structure_code ]
131
135
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 )
133
137
v = call ()
134
138
if n_bytes is not None and self ._pos - start != n_bytes :
135
139
raise DataJointError ('Blob length check failed! Invalid blob' )
@@ -146,13 +150,21 @@ def pack_blob(self, obj):
146
150
147
151
# blob types in the expanded dj0 blob format
148
152
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 )
149
163
if isinstance (obj , np .ndarray ) and obj .dtype .fields :
150
164
return self .pack_recarray (np .array (obj ))
151
165
if isinstance (obj , np .number ):
152
166
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_ )):
156
168
return self .pack_array (np .array (obj ))
157
169
if isinstance (obj , (datetime .datetime , datetime .date , datetime .time )):
158
170
return self .pack_datetime (obj )
@@ -209,7 +221,7 @@ def pack_array(self, array):
209
221
if is_complex :
210
222
array , imaginary = np .real (array ), np .imag (array )
211
223
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' )])
213
225
if dtype_list [type_id ] is None :
214
226
raise DataJointError ("Type %s is ambiguous or unknown" % array .dtype )
215
227
@@ -251,6 +263,36 @@ def pack_recarray(self, array):
251
263
def read_sparse_array (self ):
252
264
raise DataJointError ('datajoint-python does not yet support sparse arrays. Issue (#590)' )
253
265
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
+
254
296
def read_decimal (self ):
255
297
return Decimal (self .read_string ())
256
298
@@ -269,7 +311,7 @@ def pack_string(s):
269
311
270
312
def read_bytes (self ):
271
313
return self .read_binary (self .read_value ())
272
-
314
+
273
315
@staticmethod
274
316
def pack_bytes (s ):
275
317
return b"\6 " + len_u64 (s ) + s
0 commit comments