7575
7676from codecs import (utf_8_decode as _utf_8_decode ,
7777 utf_8_encode as _utf_8_encode )
78+ from collections import abc as _abc
7879
7980from bson .binary import (Binary , UuidRepresentation , ALL_UUID_SUBTYPES ,
8081 OLD_UUID_SUBTYPE ,
9293from bson .max_key import MaxKey
9394from bson .min_key import MinKey
9495from bson .objectid import ObjectId
95- from bson .py3compat import (abc ,
96- b ,
97- PY3 ,
98- iteritems ,
99- text_type ,
100- string_type ,
101- reraise )
10296from bson .regex import Regex
10397from bson .son import SON , RE_TYPE
10498from bson .timestamp import Timestamp
147141_UNPACK_TIMESTAMP_FROM = struct .Struct ("<II" ).unpack_from
148142
149143
150- if PY3 :
151- _OBJEND = 0
152- # Only used to generate the _ELEMENT_GETTER dict
153- def _maybe_ord (element_type ):
154- return ord (element_type )
155- # Only used in _raise_unkown_type below
156- def _elt_to_hex (element_type ):
157- return chr (element_type ).encode ()
158- _supported_buffer_types = (bytes , bytearray )
159- else :
160- _OBJEND = b"\x00 "
161- def _maybe_ord (element_type ):
162- return element_type
163- def _elt_to_hex (element_type ):
164- return element_type
165- _supported_buffer_types = (bytes ,)
166-
167-
168-
169- if platform .python_implementation () == 'Jython' :
170- # This is why we can't have nice things.
171- # https://bugs.jython.org/issue2788
172- def get_data_and_view (data ):
173- if isinstance (data , _supported_buffer_types ):
174- return data , data
175- data = memoryview (data ).tobytes ()
176- return data , data
177- else :
178- def get_data_and_view (data ):
179- if isinstance (data , _supported_buffer_types ):
180- return data , memoryview (data )
181- view = memoryview (data )
182- return view .tobytes (), view
144+ def get_data_and_view (data ):
145+ if isinstance (data , (bytes , bytearray )):
146+ return data , memoryview (data )
147+ view = memoryview (data )
148+ return view .tobytes (), view
183149
184150
185151def _raise_unknown_type (element_type , element_name ):
186152 """Unknown type helper."""
187153 raise InvalidBSON ("Detected unknown BSON type %r for fieldname '%s'. Are "
188154 "you using the latest driver version?" % (
189- _elt_to_hex (element_type ), element_name ))
155+ chr (element_type ). encode ( ), element_name ))
190156
191157
192158def _get_int (data , view , position , dummy0 , dummy1 , dummy2 ):
@@ -213,7 +179,7 @@ def _get_string(data, view, position, obj_end, opts, dummy):
213179 if length < 1 or obj_end - position < length :
214180 raise InvalidBSON ("invalid string length" )
215181 end = position + length - 1
216- if data [end ] != _OBJEND :
182+ if data [end ] != 0 :
217183 raise InvalidBSON ("invalid end of string" )
218184 return _utf_8_decode (view [position :end ],
219185 opts .unicode_decode_error_handler , True )[0 ], end + 1
@@ -226,7 +192,7 @@ def _get_object_size(data, position, obj_end):
226192 except struct .error as exc :
227193 raise InvalidBSON (str (exc ))
228194 end = position + obj_size - 1
229- if data [end ] != _OBJEND :
195+ if data [end ] != 0 :
230196 raise InvalidBSON ("bad eoo" )
231197 if end >= obj_end :
232198 raise InvalidBSON ("invalid object length" )
@@ -256,7 +222,7 @@ def _get_array(data, view, position, obj_end, opts, element_name):
256222 """Decode a BSON array to python list."""
257223 size = _UNPACK_INT_FROM (data , position )[0 ]
258224 end = position + size - 1
259- if data [end ] != _OBJEND :
225+ if data [end ] != 0 :
260226 raise InvalidBSON ("bad eoo" )
261227
262228 position += 4
@@ -321,8 +287,8 @@ def _get_binary(data, view, position, obj_end, opts, dummy1):
321287 uuid_representation = UuidRepresentation .PYTHON_LEGACY
322288 return binary_value .as_uuid (uuid_representation ), end
323289
324- # Python3 special case. Decode subtype 0 to 'bytes'.
325- if PY3 and subtype == 0 :
290+ # Decode subtype 0 to 'bytes'.
291+ if subtype == 0 :
326292 value = data [position :end ]
327293 else :
328294 value = Binary (data [position :end ], subtype )
@@ -410,27 +376,27 @@ def _get_decimal128(data, view, position, dummy0, dummy1, dummy2):
410376# - obj_end: int, end of object to decode in 'data' if variable-length type
411377# - opts: a CodecOptions
412378_ELEMENT_GETTER = {
413- _maybe_ord (BSONNUM ): _get_float ,
414- _maybe_ord (BSONSTR ): _get_string ,
415- _maybe_ord (BSONOBJ ): _get_object ,
416- _maybe_ord (BSONARR ): _get_array ,
417- _maybe_ord (BSONBIN ): _get_binary ,
418- _maybe_ord (BSONUND ): lambda u , v , w , x , y , z : (None , w ), # Deprecated undefined
419- _maybe_ord (BSONOID ): _get_oid ,
420- _maybe_ord (BSONBOO ): _get_boolean ,
421- _maybe_ord (BSONDAT ): _get_date ,
422- _maybe_ord (BSONNUL ): lambda u , v , w , x , y , z : (None , w ),
423- _maybe_ord (BSONRGX ): _get_regex ,
424- _maybe_ord (BSONREF ): _get_ref , # Deprecated DBPointer
425- _maybe_ord (BSONCOD ): _get_code ,
426- _maybe_ord (BSONSYM ): _get_string , # Deprecated symbol
427- _maybe_ord (BSONCWS ): _get_code_w_scope ,
428- _maybe_ord (BSONINT ): _get_int ,
429- _maybe_ord (BSONTIM ): _get_timestamp ,
430- _maybe_ord (BSONLON ): _get_int64 ,
431- _maybe_ord (BSONDEC ): _get_decimal128 ,
432- _maybe_ord (BSONMIN ): lambda u , v , w , x , y , z : (MinKey (), w ),
433- _maybe_ord (BSONMAX ): lambda u , v , w , x , y , z : (MaxKey (), w )}
379+ ord (BSONNUM ): _get_float ,
380+ ord (BSONSTR ): _get_string ,
381+ ord (BSONOBJ ): _get_object ,
382+ ord (BSONARR ): _get_array ,
383+ ord (BSONBIN ): _get_binary ,
384+ ord (BSONUND ): lambda u , v , w , x , y , z : (None , w ), # Deprecated undefined
385+ ord (BSONOID ): _get_oid ,
386+ ord (BSONBOO ): _get_boolean ,
387+ ord (BSONDAT ): _get_date ,
388+ ord (BSONNUL ): lambda u , v , w , x , y , z : (None , w ),
389+ ord (BSONRGX ): _get_regex ,
390+ ord (BSONREF ): _get_ref , # Deprecated DBPointer
391+ ord (BSONCOD ): _get_code ,
392+ ord (BSONSYM ): _get_string , # Deprecated symbol
393+ ord (BSONCWS ): _get_code_w_scope ,
394+ ord (BSONINT ): _get_int ,
395+ ord (BSONTIM ): _get_timestamp ,
396+ ord (BSONLON ): _get_int64 ,
397+ ord (BSONDEC ): _get_decimal128 ,
398+ ord (BSONMIN ): lambda u , v , w , x , y , z : (MinKey (), w ),
399+ ord (BSONMAX ): lambda u , v , w , x , y , z : (MaxKey (), w )}
434400
435401
436402if _USE_C :
@@ -488,7 +454,7 @@ def _bson_to_dict(data, opts):
488454 except Exception :
489455 # Change exception type to InvalidBSON but preserve traceback.
490456 _ , exc_value , exc_tb = sys .exc_info ()
491- reraise ( InvalidBSON , exc_value , exc_tb )
457+ raise InvalidBSON ( str ( exc_value )). with_traceback ( exc_tb )
492458if _USE_C :
493459 _bson_to_dict = _cbson ._bson_to_dict
494460
@@ -498,7 +464,7 @@ def _bson_to_dict(data, opts):
498464_PACK_LENGTH_SUBTYPE = struct .Struct ("<iB" ).pack
499465_PACK_LONG = struct .Struct ("<q" ).pack
500466_PACK_TIMESTAMP = struct .Struct ("<II" ).pack
501- _LIST_NAMES = tuple (b (str (i )) + b "\x00 " for i in range (1000 ))
467+ _LIST_NAMES = tuple ((str (i ) + "\x00 " ). encode ( 'utf8' ) for i in range (1000 ))
502468
503469
504470def gen_list_name ():
@@ -513,7 +479,7 @@ def gen_list_name():
513479
514480 counter = itertools .count (1000 )
515481 while True :
516- yield b (str (next (counter ))) + b "\x00 "
482+ yield (str (next (counter )) + "\x00 " ). encode ( 'utf8' )
517483
518484
519485def _make_c_string_check (string ):
@@ -548,46 +514,32 @@ def _make_c_string(string):
548514 return _utf_8_encode (string )[0 ] + b"\x00 "
549515
550516
551- if PY3 :
552- def _make_name (string ):
553- """Make a 'C' string suitable for a BSON key."""
554- # Keys can only be text in python 3.
555- if "\x00 " in string :
556- raise InvalidDocument ("BSON keys / regex patterns must not "
557- "contain a NUL character" )
558- return _utf_8_encode (string )[0 ] + b"\x00 "
559- else :
560- # Keys can be unicode or bytes in python 2.
561- _make_name = _make_c_string_check
517+ def _make_name (string ):
518+ """Make a 'C' string suitable for a BSON key."""
519+ # Keys can only be text in python 3.
520+ if "\x00 " in string :
521+ raise InvalidDocument ("BSON keys / regex patterns must not "
522+ "contain a NUL character" )
523+ return _utf_8_encode (string )[0 ] + b"\x00 "
562524
563525
564526def _encode_float (name , value , dummy0 , dummy1 ):
565527 """Encode a float."""
566528 return b"\x01 " + name + _PACK_FLOAT (value )
567529
568530
569- if PY3 :
570- def _encode_bytes (name , value , dummy0 , dummy1 ):
571- """Encode a python bytes."""
572- # Python3 special case. Store 'bytes' as BSON binary subtype 0.
573- return b"\x05 " + name + _PACK_INT (len (value )) + b"\x00 " + value
574- else :
575- def _encode_bytes (name , value , dummy0 , dummy1 ):
576- """Encode a python str (python 2.x)."""
577- try :
578- _utf_8_decode (value , None , True )
579- except UnicodeError :
580- raise InvalidStringData ("strings in documents must be valid "
581- "UTF-8: %r" % (value ,))
582- return b"\x02 " + name + _PACK_INT (len (value ) + 1 ) + value + b"\x00 "
531+ def _encode_bytes (name , value , dummy0 , dummy1 ):
532+ """Encode a python bytes."""
533+ # Python3 special case. Store 'bytes' as BSON binary subtype 0.
534+ return b"\x05 " + name + _PACK_INT (len (value )) + b"\x00 " + value
583535
584536
585537def _encode_mapping (name , value , check_keys , opts ):
586538 """Encode a mapping type."""
587539 if _raw_document_class (value ):
588540 return b'\x03 ' + name + value .raw
589541 data = b"" .join ([_element_to_bson (key , val , check_keys , opts )
590- for key , val in iteritems ( value )])
542+ for key , val in value . items ( )])
591543 return b"\x03 " + name + _PACK_INT (len (data ) + 5 ) + data + b"\x00 "
592544
593545
@@ -603,7 +555,7 @@ def _encode_dbref(name, value, check_keys, opts):
603555 if value .database is not None :
604556 buf += _name_value_to_bson (
605557 b"$db\x00 " , value .database , check_keys , opts )
606- for key , val in iteritems ( value ._DBRef__kwargs ):
558+ for key , val in value ._DBRef__kwargs . items ( ):
607559 buf += _element_to_bson (key , val , check_keys , opts )
608560
609561 buf += b"\x00 "
@@ -751,8 +703,7 @@ def _encode_maxkey(name, dummy0, dummy1, dummy2):
751703 float : _encode_float ,
752704 int : _encode_int ,
753705 list : _encode_list ,
754- # unicode in py2, str in py3
755- text_type : _encode_text ,
706+ str : _encode_text ,
756707 tuple : _encode_list ,
757708 type (None ): _encode_none ,
758709 uuid .UUID : _encode_uuid ,
@@ -770,7 +721,7 @@ def _encode_maxkey(name, dummy0, dummy1, dummy2):
770721 UUIDLegacy : _encode_binary ,
771722 Decimal128 : _encode_decimal128 ,
772723 # Special case. This will never be looked up directly.
773- abc .Mapping : _encode_mapping ,
724+ _abc .Mapping : _encode_mapping ,
774725}
775726
776727
@@ -786,9 +737,6 @@ def _encode_maxkey(name, dummy0, dummy1, dummy2):
786737 255 : _encode_minkey ,
787738}
788739
789- if not PY3 :
790- _ENCODERS [long ] = _encode_long
791-
792740
793741_BUILT_IN_TYPES = tuple (t for t in _ENCODERS )
794742
@@ -848,7 +796,7 @@ def _name_value_to_bson(name, value, check_keys, opts,
848796
849797def _element_to_bson (key , value , check_keys , opts ):
850798 """Encode a single key, value pair."""
851- if not isinstance (key , string_type ):
799+ if not isinstance (key , str ):
852800 raise InvalidDocument ("documents must have only string keys, "
853801 "key was %r" % (key ,))
854802 if check_keys :
@@ -870,7 +818,7 @@ def _dict_to_bson(doc, check_keys, opts, top_level=True):
870818 if top_level and "_id" in doc :
871819 elements .append (_name_value_to_bson (b"_id\x00 " , doc ["_id" ],
872820 check_keys , opts ))
873- for ( key , value ) in iteritems ( doc ):
821+ for key , value in doc . items ( ):
874822 if not top_level or key != "_id" :
875823 elements .append (_element_to_bson (key , value ,
876824 check_keys , opts ))
@@ -1017,7 +965,7 @@ def decode_all(data, codec_options=DEFAULT_CODEC_OPTIONS):
1017965 if data_len - position < obj_size :
1018966 raise InvalidBSON ("invalid object size" )
1019967 obj_end = position + obj_size - 1
1020- if data [obj_end ] != _OBJEND :
968+ if data [obj_end ] != 0 :
1021969 raise InvalidBSON ("bad eoo" )
1022970 if use_raw :
1023971 docs .append (
@@ -1036,7 +984,7 @@ def decode_all(data, codec_options=DEFAULT_CODEC_OPTIONS):
1036984 except Exception :
1037985 # Change exception type to InvalidBSON but preserve traceback.
1038986 _ , exc_value , exc_tb = sys .exc_info ()
1039- reraise ( InvalidBSON , exc_value , exc_tb )
987+ raise InvalidBSON ( str ( exc_value )). with_traceback ( exc_tb )
1040988
1041989
1042990if _USE_C :
@@ -1051,7 +999,7 @@ def _decode_selective(rawdoc, fields, codec_options):
1051999 else :
10521000 # Else, use the specified document_class.
10531001 doc = codec_options .document_class ()
1054- for key , value in iteritems ( rawdoc ):
1002+ for key , value in rawdoc . items ( ):
10551003 if key in fields :
10561004 if fields [key ] == 1 :
10571005 doc [key ] = _bson_to_dict (rawdoc .raw , codec_options )[key ]
0 commit comments