93
93
_UNPACK_TIMESTAMP = struct .Struct ("<II" ).unpack
94
94
95
95
96
- def _get_int (data , position , dummy0 , dummy1 ):
96
+ def _raise_unknown_type (element_type , element_name ):
97
+ """Unknown type helper."""
98
+ raise InvalidBSON ("Detected unknown BSON type %r for fieldname '%s'. Are "
99
+ "you using the latest driver version?" % (
100
+ element_type , element_name ))
101
+
102
+
103
+ def _get_int (data , position , dummy0 , dummy1 , dummy2 ):
97
104
"""Decode a BSON int32 to python int."""
98
105
end = position + 4
99
106
return _UNPACK_INT (data [position :end ])[0 ], end
@@ -106,13 +113,13 @@ def _get_c_string(data, position, opts):
106
113
opts .unicode_decode_error_handler , True )[0 ], end + 1
107
114
108
115
109
- def _get_float (data , position , dummy0 , dummy1 ):
116
+ def _get_float (data , position , dummy0 , dummy1 , dummy2 ):
110
117
"""Decode a BSON double to python float."""
111
118
end = position + 8
112
119
return _UNPACK_FLOAT (data [position :end ])[0 ], end
113
120
114
121
115
- def _get_string (data , position , obj_end , opts ):
122
+ def _get_string (data , position , obj_end , opts , dummy ):
116
123
"""Decode a BSON string to python unicode string."""
117
124
length = _UNPACK_INT (data [position :position + 4 ])[0 ]
118
125
position += 4
@@ -125,7 +132,7 @@ def _get_string(data, position, obj_end, opts):
125
132
opts .unicode_decode_error_handler , True )[0 ], end + 1
126
133
127
134
128
- def _get_object (data , position , obj_end , opts ):
135
+ def _get_object (data , position , obj_end , opts , dummy ):
129
136
"""Decode a BSON subdocument to opts.document_class or bson.dbref.DBRef."""
130
137
obj_size = _UNPACK_INT (data [position :position + 4 ])[0 ]
131
138
end = position + obj_size - 1
@@ -146,7 +153,7 @@ def _get_object(data, position, obj_end, opts):
146
153
return obj , position
147
154
148
155
149
- def _get_array (data , position , obj_end , opts ):
156
+ def _get_array (data , position , obj_end , opts , element_name ):
150
157
"""Decode a BSON array to python list."""
151
158
size = _UNPACK_INT (data [position :position + 4 ])[0 ]
152
159
end = position + size - 1
@@ -166,12 +173,16 @@ def _get_array(data, position, obj_end, opts):
166
173
element_type = data [position :position + 1 ]
167
174
# Just skip the keys.
168
175
position = index (b'\x00 ' , position ) + 1
169
- value , position = getter [element_type ](data , position , obj_end , opts )
176
+ try :
177
+ value , position = getter [element_type ](
178
+ data , position , obj_end , opts , element_name )
179
+ except KeyError :
180
+ _raise_unknown_type (element_type , element_name )
170
181
append (value )
171
182
return result , position + 1
172
183
173
184
174
- def _get_binary (data , position , dummy , opts ):
185
+ def _get_binary (data , position , dummy0 , opts , dummy1 ):
175
186
"""Decode a BSON binary to bson.binary.Binary or python UUID."""
176
187
length , subtype = _UNPACK_LENGTH_SUBTYPE (data [position :position + 5 ])
177
188
position += 5
@@ -203,19 +214,19 @@ def _get_binary(data, position, dummy, opts):
203
214
return value , end
204
215
205
216
206
- def _get_oid (data , position , dummy0 , dummy1 ):
217
+ def _get_oid (data , position , dummy0 , dummy1 , dummy2 ):
207
218
"""Decode a BSON ObjectId to bson.objectid.ObjectId."""
208
219
end = position + 12
209
220
return ObjectId (data [position :end ]), end
210
221
211
222
212
- def _get_boolean (data , position , dummy0 , dummy1 ):
223
+ def _get_boolean (data , position , dummy0 , dummy1 , dummy2 ):
213
224
"""Decode a BSON true/false to python True/False."""
214
225
end = position + 1
215
226
return data [position :end ] == b"\x01 " , end
216
227
217
228
218
- def _get_date (data , position , dummy , opts ):
229
+ def _get_date (data , position , dummy0 , opts , dummy1 ):
219
230
"""Decode a BSON datetime to python datetime.datetime."""
220
231
end = position + 8
221
232
millis = _UNPACK_LONG (data [position :end ])[0 ]
@@ -233,42 +244,44 @@ def _get_date(data, position, dummy, opts):
233
244
return dt , end
234
245
235
246
236
- def _get_code (data , position , obj_end , opts ):
247
+ def _get_code (data , position , obj_end , opts , element_name ):
237
248
"""Decode a BSON code to bson.code.Code."""
238
- code , position = _get_string (data , position , obj_end , opts )
249
+ code , position = _get_string (data , position , obj_end , opts , element_name )
239
250
return Code (code ), position
240
251
241
252
242
- def _get_code_w_scope (data , position , obj_end , opts ):
253
+ def _get_code_w_scope (data , position , obj_end , opts , element_name ):
243
254
"""Decode a BSON code_w_scope to bson.code.Code."""
244
- code , position = _get_string (data , position + 4 , obj_end , opts )
245
- scope , position = _get_object (data , position , obj_end , opts )
255
+ code , position = _get_string (
256
+ data , position + 4 , obj_end , opts , element_name )
257
+ scope , position = _get_object (data , position , obj_end , opts , element_name )
246
258
return Code (code , scope ), position
247
259
248
260
249
- def _get_regex (data , position , dummy0 , opts ):
261
+ def _get_regex (data , position , dummy0 , opts , dummy1 ):
250
262
"""Decode a BSON regex to bson.regex.Regex or a python pattern object."""
251
263
pattern , position = _get_c_string (data , position , opts )
252
264
bson_flags , position = _get_c_string (data , position , opts )
253
265
bson_re = Regex (pattern , bson_flags )
254
266
return bson_re , position
255
267
256
268
257
- def _get_ref (data , position , obj_end , opts ):
269
+ def _get_ref (data , position , obj_end , opts , element_name ):
258
270
"""Decode (deprecated) BSON DBPointer to bson.dbref.DBRef."""
259
- collection , position = _get_string (data , position , obj_end , opts )
260
- oid , position = _get_oid (data , position , obj_end , opts )
271
+ collection , position = _get_string (
272
+ data , position , obj_end , opts , element_name )
273
+ oid , position = _get_oid (data , position , obj_end , opts , element_name )
261
274
return DBRef (collection , oid ), position
262
275
263
276
264
- def _get_timestamp (data , position , dummy0 , dummy1 ):
277
+ def _get_timestamp (data , position , dummy0 , dummy1 , dummy2 ):
265
278
"""Decode a BSON timestamp to bson.timestamp.Timestamp."""
266
279
end = position + 8
267
280
inc , timestamp = _UNPACK_TIMESTAMP (data [position :end ])
268
281
return Timestamp (timestamp , inc ), end
269
282
270
283
271
- def _get_int64 (data , position , dummy0 , dummy1 ):
284
+ def _get_int64 (data , position , dummy0 , dummy1 , dummy2 ):
272
285
"""Decode a BSON int64 to bson.int64.Int64."""
273
286
end = position + 8
274
287
return Int64 (_UNPACK_LONG (data [position :end ])[0 ]), end
@@ -285,11 +298,11 @@ def _get_int64(data, position, dummy0, dummy1):
285
298
BSONOBJ : _get_object ,
286
299
BSONARR : _get_array ,
287
300
BSONBIN : _get_binary ,
288
- BSONUND : lambda w , x , y , z : (None , x ), # Deprecated undefined
301
+ BSONUND : lambda v , w , x , y , z : (None , w ), # Deprecated undefined
289
302
BSONOID : _get_oid ,
290
303
BSONBOO : _get_boolean ,
291
304
BSONDAT : _get_date ,
292
- BSONNUL : lambda w , x , y , z : (None , x ),
305
+ BSONNUL : lambda v , w , x , y , z : (None , w ),
293
306
BSONRGX : _get_regex ,
294
307
BSONREF : _get_ref , # Deprecated DBPointer
295
308
BSONCOD : _get_code ,
@@ -298,17 +311,21 @@ def _get_int64(data, position, dummy0, dummy1):
298
311
BSONINT : _get_int ,
299
312
BSONTIM : _get_timestamp ,
300
313
BSONLON : _get_int64 ,
301
- BSONMIN : lambda w , x , y , z : (MinKey (), x ),
302
- BSONMAX : lambda w , x , y , z : (MaxKey (), x )}
314
+ BSONMIN : lambda v , w , x , y , z : (MinKey (), w ),
315
+ BSONMAX : lambda v , w , x , y , z : (MaxKey (), w )}
303
316
304
317
305
318
def _element_to_dict (data , position , obj_end , opts ):
306
319
"""Decode a single key, value pair."""
307
320
element_type = data [position :position + 1 ]
308
321
position += 1
309
322
element_name , position = _get_c_string (data , position , opts )
310
- value , position = _ELEMENT_GETTER [element_type ](data ,
311
- position , obj_end , opts )
323
+ try :
324
+ value , position = _ELEMENT_GETTER [element_type ](data , position ,
325
+ obj_end , opts ,
326
+ element_name )
327
+ except KeyError :
328
+ _raise_unknown_type (element_type , element_name )
312
329
return element_name , value , position
313
330
if _USE_C :
314
331
_element_to_dict = _cbson ._element_to_dict
0 commit comments