Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove py2 compatibility #136

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 16 additions & 21 deletions bson/codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@
from dateutil.tz import tzutc
from binascii import b2a_hex

from six import integer_types, iterkeys, text_type, PY3
from six.moves import xrange


utc = tzutc()

class MissingClassDefinition(ValueError):
Expand Down Expand Up @@ -132,7 +128,7 @@ def encode_string(value):

def encode_cstring(value):
if not isinstance(value, bytes):
value = text_type(value).encode("utf-8")
value = str(value).encode("utf-8")
if b"\x00" in value:
raise ValueError("Element names may not include NUL bytes.")
# A NUL byte is used to delimit our string, accepting one would cause
Expand Down Expand Up @@ -172,24 +168,26 @@ def encode_double_element(name, value):
def encode_string_element(name, value):
return b"\x02" + encode_cstring(name) + encode_string(value)


# any need for this at all with py3??
def _is_string(value):
if isinstance(value, text_type):
if isinstance(value, str):
return True
elif isinstance(value, str) or isinstance(value, bytes):
try:
unicode(value, errors='strict')
return True
except:
pass
return False
# this never worked in py3
# elif isinstance(value, str) or isinstance(value, bytes):
# try:
# unicode(value, errors='strict')
# return True
# except:
# pass
else:
return False


def encode_value(name, value, buf, traversal_stack,
generator_func, on_unknown=None):
if isinstance(value, bool):
buf.write(encode_boolean_element(name, value))
elif isinstance(value, integer_types):
elif isinstance(value, int):
if value < -0x80000000 or 0x7FFFFFFFFFFFFFFF >= value > 0x7fffffff:
buf.write(encode_int64_element(name, value))
elif value > 0x7FFFFFFFFFFFFFFF:
Expand Down Expand Up @@ -238,7 +236,7 @@ def encode_value(name, value, buf, traversal_stack,
def encode_document(obj, traversal_stack, traversal_parent=None,
generator_func=None, on_unknown=None):
buf = StringIO()
key_iter = iterkeys(obj)
key_iter = iter(obj)
if generator_func is not None:
key_iter = generator_func(obj, traversal_stack)
for name in key_iter:
Expand All @@ -256,7 +254,7 @@ def encode_document(obj, traversal_stack, traversal_parent=None,
def encode_array(array, traversal_stack, traversal_parent=None,
generator_func=None, on_unknown=None):
buf = StringIO()
for i in xrange(0, len(array)):
for i in range(0, len(array)):
value = array[i]
traversal_stack.append(TraversalStep(traversal_parent or array, i))
encode_value(str(i), value, buf, traversal_stack,
Expand Down Expand Up @@ -295,10 +293,7 @@ def decode_document(data, base, as_array=False):

element_type = char_struct.unpack(data[base:base + 1])[0]

if PY3:
ll = data.index(0, base + 1) + 1
else:
ll = data.index("\x00", base + 1) + 1
ll = data.index(0, base + 1) + 1
if decode_name:
name = data[base + 1:ll - 1]
try:
Expand Down
9 changes: 5 additions & 4 deletions bson/network.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python
from struct import unpack

from six import BytesIO, b
from io import BytesIO

from . import dumps, loads

Expand Down Expand Up @@ -55,9 +55,10 @@ def recvbytes(self, bytes_needed, sock_buf = None):
chunk = self.recv(min(bytes_needed - bytes_count, 32768))
part_count = len(chunk)

if type(chunk) == str:
chunk = b(chunk)

if type(chunk) == str: # this probably never occurs ...
# chunk = b(chunk)
# six.b() encoded to latin-1
chunk = chunk.encode("latin-1")
if part_count < 1:
return None

Expand Down
22 changes: 9 additions & 13 deletions bson/objectid.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,14 @@
import threading
import time

from bson.py3compat import PY3, bytes_from_hex, string_type, text_type
# from bson.py3compat import bytes_from_hex #string_type
from bson.tz_util import utc


# fnv_1a_24 adaptation taken from MongoDB Python Driver at https://github.com/mongodb/mongo-python-driver/commit/61850357a0e0eeec1a30e1adc0bbf7ebee807358
if PY3:
_ord = lambda x: x
else:
_ord = ord
# is this needed at all for Py3?
_ord = lambda x: x

# http://isthe.com/chongo/tech/comp/fnv/index.html#FNV-1a
def _fnv_1a_24(data, _ord=_ord):
"""FNV-1a 24 bit hash"""
Expand Down Expand Up @@ -212,18 +211,17 @@ def __validate(self, oid):
"""
if isinstance(oid, ObjectId):
self.__id = oid.binary
# bytes or unicode in python 2, str in python 3
elif isinstance(oid, string_type):
elif isinstance(oid, str):
if len(oid) == 24:
try:
self.__id = bytes_from_hex(oid)
self.__id = bytes.fromhex(oid)
except (TypeError, ValueError):
_raise_invalid_id(oid)
else:
_raise_invalid_id(oid)
else:
raise TypeError("id must be an instance of (bytes, %s, ObjectId), "
"not %s" % (text_type.__name__, type(oid)))
"not %s" % ('str', type(oid)))

@property
def binary(self):
Expand Down Expand Up @@ -261,15 +259,13 @@ def __setstate__(self, value):
# ObjectIds pickled in python 2.x used `str` for __id.
# In python 3.x this has to be converted to `bytes`
# by encoding latin-1.
if PY3 and isinstance(oid, text_type):
if isinstance(oid, str):
self.__id = oid.encode('latin-1')
else:
self.__id = oid

def __str__(self):
if PY3:
return binascii.hexlify(self.__id).decode()
return binascii.hexlify(self.__id)
return binascii.hexlify(self.__id).decode()

def __repr__(self):
return "ObjectId('%s')" % (str(self),)
Expand Down
88 changes: 0 additions & 88 deletions bson/py3compat.py

This file was deleted.

2 changes: 1 addition & 1 deletion scripts/test
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

set -x # print executed commands to the terminal

uvx --with python-dateutil --with six pytest "${@}"
uvx --with python-dateutil pytest "${@}"
3 changes: 1 addition & 2 deletions tests/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from unittest import TestCase

from bson import dumps, loads
from six import PY3


class TestArray(TestCase):
Expand Down Expand Up @@ -74,5 +73,5 @@ def test_long_array(self):

def test_encoded_order(self):
serialized = dumps(self.doc)
expected = repr(serialized)[1:] if PY3 else repr(serialized)
expected = repr(serialized)[1:]
self.assertEqual(expected, '\'\\xea\\x08\\x00\\x00\\x04lyrics\\x00\\xdd\\x08\\x00\\x00\\x020\\x00\\x14\\x00\\x00\\x00Viva La Vida lyrics\\x00\\x021\\x00\\x01\\x00\\x00\\x00\\x00\\x022\\x00!\\x00\\x00\\x00 I used to rule the world\\x00\\x023\\x00-\\x00\\x00\\x00 Seas would rise when I gave the word\\x00\\x024\\x00)\\x00\\x00\\x00 Now in the morning I sleep alone\\x00\\x025\\x00(\\x00\\x00\\x00 Sweep the streets I used to own\\x00\\x026\\x00\\x01\\x00\\x00\\x00\\x00\\x027\\x00 \\x00\\x00\\x00 I used to roll the dice\\x00\\x028\\x00)\\x00\\x00\\x00 Feel the fear in my enemy\\\'s eyes\\x00\\x029\\x00\\\'\\x00\\x00\\x00 Listen as the crowd would sing\\x00\\x0210\\x008\\x00\\x00\\x00 "Now the old king is dead! Long live the king!"\\x00\\x0211\\x00\\x01\\x00\\x00\\x00\\x00\\x0212\\x00"\\x00\\x00\\x00 One minute I held the key\\x00\\x0213\\x00)\\x00\\x00\\x00 Next the walls were closed on me\\x00\\x0214\\x00/\\x00\\x00\\x00 And I discovered that my castles stand\\x00\\x0215\\x001\\x00\\x00\\x00 Upon pillars of salt and pillars of sand\\x00\\x0216\\x00\\x01\\x00\\x00\\x00\\x00\\x0217\\x00)\\x00\\x00\\x00 I hear Jerusalem bells a ringing\\x00\\x0218\\x00)\\x00\\x00\\x00 Roman Cavalry choirs are singing\\x00\\x0219\\x00*\\x00\\x00\\x00 Be my mirror, my sword and shield\\x00\\x0220\\x00+\\x00\\x00\\x00 My missionaries in a foreign field\\x00\\x0221\\x00\\x01\\x00\\x00\\x00\\x00\\x0222\\x00(\\x00\\x00\\x00 For some reason I can\\\'t explain\\x00\\x0223\\x00$\\x00\\x00\\x00 Once you go there was never\\x00\\x0224\\x00\\x1d\\x00\\x00\\x00 Never an honest word\\x00\\x0225\\x00,\\x00\\x00\\x00 And that was when I ruled the world\\x00\\x0226\\x00\\x01\\x00\\x00\\x00\\x00\\x0227\\x00(\\x00\\x00\\x00 It was the wicked and wild wind\\x00\\x0228\\x00)\\x00\\x00\\x00 Blew down the doors to let me in\\x00\\x0229\\x001\\x00\\x00\\x00 Shattered windows and the sound of drums\\x00\\x0230\\x000\\x00\\x00\\x00 People couldn\\\'t believe what I\\\'d become\\x00\\x0231\\x00\\x01\\x00\\x00\\x00\\x00\\x0232\\x00\\x1d\\x00\\x00\\x00 Revolutionaries wait\\x00\\x0233\\x00&\\x00\\x00\\x00 For my head on a silver plate\\x00\\x0234\\x00)\\x00\\x00\\x00 Just a puppet on a lonely string\\x00\\x0235\\x00+\\x00\\x00\\x00 Oh who would ever want to be king?\\x00\\x0236\\x00\\x01\\x00\\x00\\x00\\x00\\x0237\\x00)\\x00\\x00\\x00 I hear Jerusalem bells a ringing\\x00\\x0238\\x00)\\x00\\x00\\x00 Roman Cavalry choirs are singing\\x00\\x0239\\x00*\\x00\\x00\\x00 Be my mirror, my sword and shield\\x00\\x0240\\x00+\\x00\\x00\\x00 My missionaries in a foreign field\\x00\\x0241\\x00\\x01\\x00\\x00\\x00\\x00\\x0242\\x00(\\x00\\x00\\x00 For some reason I can\\\'t explain\\x00\\x0243\\x00.\\x00\\x00\\x00 I know Saint Peter won\\\'t call my name\\x00\\x0244\\x00\\x1d\\x00\\x00\\x00 Never an honest word\\x00\\x0245\\x00,\\x00\\x00\\x00 But that was when I ruled the world\\x00\\x0246\\x00\\x01\\x00\\x00\\x00\\x00\\x0247\\x00)\\x00\\x00\\x00 I hear Jerusalem bells a ringing\\x00\\x0248\\x00)\\x00\\x00\\x00 Roman Cavalry choirs are singing\\x00\\x0249\\x00*\\x00\\x00\\x00 Be my mirror, my sword and shield\\x00\\x0250\\x00+\\x00\\x00\\x00 My missionaries in a foreign field\\x00\\x0251\\x00\\x01\\x00\\x00\\x00\\x00\\x0252\\x00(\\x00\\x00\\x00 For some reason I can\\\'t explain\\x00\\x0253\\x00.\\x00\\x00\\x00 I know Saint Peter won\\\'t call my name\\x00\\x0254\\x00\\x1d\\x00\\x00\\x00 Never an honest word\\x00\\x0255\\x00,\\x00\\x00\\x00 But that was when I ruled the world\\x00\\x00\\x00\'')
1 change: 0 additions & 1 deletion tests/test_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from bson import BSONCoding, dumps, loads, import_class


class TestData(BSONCoding):
__test__ = False

Expand Down
20 changes: 8 additions & 12 deletions tests/test_objectid.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

from bson.objectid import ObjectId, _fnv_1a_24
from bson.objectid import InvalidId
from bson.py3compat import PY3, _unicode
from bson.tz_util import (FixedOffset,
utc)

Expand Down Expand Up @@ -467,7 +466,7 @@ def test_fnv_1a_24(self):

def test_unicode(self):
a = ObjectId()
self.assertEqual(a, ObjectId(_unicode(a)))
self.assertEqual(a, ObjectId(a))
self.assertEqual(ObjectId("123456789012123456789012"),
ObjectId(u"123456789012123456789012"))
self.assertRaises(InvalidId, ObjectId, u"hello")
Expand Down Expand Up @@ -511,18 +510,19 @@ def test_pid(self):
self.assertTrue(oid_generated_on_client(ObjectId()))

def test_generation_time(self):
d1 = datetime.datetime.utcnow()
d1 = datetime.datetime.now(utc)
d2 = ObjectId().generation_time

self.assertEqual(utc, d2.tzinfo)
d2 = d2.replace(tzinfo=None)
self.assertTrue(d2 - d1 < datetime.timedelta(seconds=2))

def test_from_datetime(self):
if 'PyPy 1.8.0' in sys.version:
# See https://bugs.pypy.org/issue1092
raise SkipTest("datetime.timedelta is broken in pypy 1.8.0")
d = datetime.datetime.utcnow()
# note: could use tz aware datetimes here?
d = datetime.datetime.now(utc).replace(tzinfo=None)

d = d - datetime.timedelta(microseconds=d.microsecond)
oid = ObjectId.from_datetime(d)
self.assertEqual(d, oid.generation_time.replace(tzinfo=None))
Expand Down Expand Up @@ -559,13 +559,9 @@ def test_pickle_backwards_compatability(self):
b"object\np2\nNtp3\nRp4\n"
b"S'M\\x9afV\\x13v\\xc0\\x0b\\x88\\x00\\x00\\x00'\np5\nb.")

if PY3:
# Have to load using 'latin-1' since these were pickled in python2.x.
oid_1_9 = pickle.loads(pickled_with_1_9, encoding='latin-1')
oid_1_10 = pickle.loads(pickled_with_1_10, encoding='latin-1')
else:
oid_1_9 = pickle.loads(pickled_with_1_9)
oid_1_10 = pickle.loads(pickled_with_1_10)
# Have to load using 'latin-1' since these were pickled in python2.x.
oid_1_9 = pickle.loads(pickled_with_1_9, encoding='latin-1')
oid_1_10 = pickle.loads(pickled_with_1_10, encoding='latin-1')

self.assertEqual(oid_1_9, ObjectId("4d9a66561376c00b88000000"))
self.assertEqual(oid_1_9, oid_1_10)
Expand Down
Loading
Loading