Skip to content

Commit c70071d

Browse files
committed
PYTHON-2133 Remove Py2 compatibility from bson
1 parent 1128129 commit c70071d

File tree

13 files changed

+124
-207
lines changed

13 files changed

+124
-207
lines changed

bson/__init__.py

Lines changed: 56 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575

7676
from 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

7980
from bson.binary import (Binary, UuidRepresentation, ALL_UUID_SUBTYPES,
8081
OLD_UUID_SUBTYPE,
@@ -92,13 +93,6 @@
9293
from bson.max_key import MaxKey
9394
from bson.min_key import MinKey
9495
from bson.objectid import ObjectId
95-
from bson.py3compat import (abc,
96-
b,
97-
PY3,
98-
iteritems,
99-
text_type,
100-
string_type,
101-
reraise)
10296
from bson.regex import Regex
10397
from bson.son import SON, RE_TYPE
10498
from bson.timestamp import Timestamp
@@ -147,46 +141,18 @@
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

185151
def _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

192158
def _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

436402
if _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)
492458
if _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

504470
def 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

519485
def _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

564526
def _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

585537
def _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

849797
def _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

1042990
if _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]

bson/binary.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
from uuid import UUID
1616
from warnings import warn
1717

18-
from bson.py3compat import PY3
19-
2018
"""Tools for representing BSON binary data.
2119
"""
2220

@@ -318,7 +316,7 @@ def subtype(self):
318316
def __getnewargs__(self):
319317
# Work around http://bugs.python.org/issue7382
320318
data = super(Binary, self).__getnewargs__()[0]
321-
if PY3 and not isinstance(data, bytes):
319+
if not isinstance(data, bytes):
322320
data = data.encode('latin-1')
323321
return data, self.__subtype
324322

bson/code.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"""Tools for representing JavaScript code in BSON.
1616
"""
1717

18-
from bson.py3compat import abc, string_type, PY3, text_type
18+
from collections.abc import Mapping as _Mapping
1919

2020

2121
class Code(str):
@@ -49,22 +49,18 @@ class Code(str):
4949
_type_marker = 13
5050

5151
def __new__(cls, code, scope=None, **kwargs):
52-
if not isinstance(code, string_type):
53-
raise TypeError("code must be an "
54-
"instance of %s" % (string_type.__name__))
52+
if not isinstance(code, str):
53+
raise TypeError("code must be an instance of str")
5554

56-
if not PY3 and isinstance(code, text_type):
57-
self = str.__new__(cls, code.encode('utf8'))
58-
else:
59-
self = str.__new__(cls, code)
55+
self = str.__new__(cls, code)
6056

6157
try:
6258
self.__scope = code.scope
6359
except AttributeError:
6460
self.__scope = None
6561

6662
if scope is not None:
67-
if not isinstance(scope, abc.Mapping):
63+
if not isinstance(scope, _Mapping):
6864
raise TypeError("scope must be an instance of dict")
6965
if self.__scope is not None:
7066
self.__scope.update(scope)

0 commit comments

Comments
 (0)