1336 lines
58 KiB
Diff
1336 lines
58 KiB
Diff
From ef3df1663cb33cad857f5c7f9fce5565b25bd268 Mon Sep 17 00:00:00 2001
|
|
From: Prashant Mital <prashantmital@gmail.com>
|
|
Date: Fri, 9 Aug 2019 15:04:06 -0700
|
|
Subject: [PATCH] PYTHON-1918 Stop using BSON.encode and BSON.decode functions
|
|
|
|
---
|
|
bson/raw_bson.py | 3 +-
|
|
doc/migrate-to-pymongo3.rst | 9 +-
|
|
pymongo/message.py | 6 +-
|
|
test/performance/perf_test.py | 6 +-
|
|
test/test_binary.py | 57 +++----
|
|
test/test_bson.py | 311 +++++++++++++++++-----------------
|
|
test/test_bson_corpus.py | 8 +-
|
|
test/test_change_stream.py | 4 +-
|
|
test/test_client.py | 4 +-
|
|
test/test_collection.py | 9 +-
|
|
test/test_custom_types.py | 41 ++---
|
|
test/test_encryption.py | 4 +-
|
|
test/test_raw_bson.py | 16 +-
|
|
test/unicode/test_utf8.py | 4 +-
|
|
14 files changed, 237 insertions(+), 245 deletions(-)
|
|
|
|
diff --git a/bson/raw_bson.py b/bson/raw_bson.py
|
|
index f83ac40d..6a7cf504 100644
|
|
--- a/bson/raw_bson.py
|
|
+++ b/bson/raw_bson.py
|
|
@@ -45,7 +45,8 @@ class RawBSONDocument(abc.Mapping):
|
|
class from the standard library so it can be used like a read-only
|
|
``dict``::
|
|
|
|
- >>> raw_doc = RawBSONDocument(BSON.encode({'_id': 'my_doc'}))
|
|
+ >>> from bson import encode
|
|
+ >>> raw_doc = RawBSONDocument(encode({'_id': 'my_doc'}))
|
|
>>> raw_doc.raw
|
|
b'...'
|
|
>>> raw_doc['_id']
|
|
diff --git a/doc/migrate-to-pymongo3.rst b/doc/migrate-to-pymongo3.rst
|
|
index 85f495ea..bb396dde 100644
|
|
--- a/doc/migrate-to-pymongo3.rst
|
|
+++ b/doc/migrate-to-pymongo3.rst
|
|
@@ -492,7 +492,10 @@ BSON
|
|
......................................................
|
|
|
|
The `as_class`, `tz_aware`, and `uuid_subtype` parameters have been
|
|
-removed from the functions provided in :mod:`bson`. Code like this::
|
|
+removed from the functions provided in :mod:`bson`. Furthermore, the
|
|
+:func:`~bson.encode` and :func:`~bson.decode` functions have been added
|
|
+as more performant alternatives to the :meth:`bson.BSON.encode` and
|
|
+:meth:`bson.BSON.decode` methods. Code like this::
|
|
|
|
>>> from bson import BSON
|
|
>>> from bson.son import SON
|
|
@@ -502,10 +505,10 @@ can be replaced by this in PyMongo 2.9 or later:
|
|
|
|
.. doctest::
|
|
|
|
- >>> from bson import BSON
|
|
+ >>> from bson import encode
|
|
>>> from bson.codec_options import CodecOptions
|
|
>>> from bson.son import SON
|
|
- >>> encoded = BSON.encode({"a": 1}, codec_options=CodecOptions(SON))
|
|
+ >>> encoded = encode({"a": 1}, codec_options=CodecOptions(SON))
|
|
|
|
Removed features with no migration path
|
|
---------------------------------------
|
|
diff --git a/pymongo/message.py b/pymongo/message.py
|
|
index fae75a4d..56f86369 100644
|
|
--- a/pymongo/message.py
|
|
+++ b/pymongo/message.py
|
|
@@ -26,6 +26,8 @@ import struct
|
|
|
|
import bson
|
|
from bson import (CodecOptions,
|
|
+ decode,
|
|
+ encode,
|
|
_dict_to_bson,
|
|
_make_c_string)
|
|
from bson.codec_options import DEFAULT_CODEC_OPTIONS
|
|
@@ -1397,7 +1399,7 @@ def _batched_write_command_impl(
|
|
|
|
# Where to write command document length
|
|
command_start = buf.tell()
|
|
- buf.write(bson.BSON.encode(command))
|
|
+ buf.write(encode(command))
|
|
|
|
# Start of payload
|
|
buf.seek(-1, 2)
|
|
@@ -1418,7 +1420,7 @@ def _batched_write_command_impl(
|
|
for doc in docs:
|
|
# Encode the current operation
|
|
key = b(str(idx))
|
|
- value = bson.BSON.encode(doc, check_keys, opts)
|
|
+ value = encode(doc, check_keys, opts)
|
|
# Is there enough room to add this document? max_cmd_size accounts for
|
|
# the two trailing null bytes.
|
|
doc_too_large = len(value) > max_cmd_size
|
|
diff --git a/test/performance/perf_test.py b/test/performance/perf_test.py
|
|
index 392c64ca..536b5441 100644
|
|
--- a/test/performance/perf_test.py
|
|
+++ b/test/performance/perf_test.py
|
|
@@ -27,7 +27,7 @@ except ImportError:
|
|
|
|
sys.path[0:0] = [""]
|
|
|
|
-from bson import BSON
|
|
+from bson import encode
|
|
from bson.json_util import loads
|
|
from gridfs import GridFSBucket
|
|
from pymongo import MongoClient
|
|
@@ -133,7 +133,7 @@ class BsonEncodingTest(PerformanceTest):
|
|
|
|
def do_task(self):
|
|
for _ in range(NUM_DOCS):
|
|
- BSON.encode(self.document)
|
|
+ encode(self.document)
|
|
|
|
|
|
class BsonDecodingTest(PerformanceTest):
|
|
@@ -142,7 +142,7 @@ class BsonDecodingTest(PerformanceTest):
|
|
with open(
|
|
os.path.join(TEST_PATH,
|
|
os.path.join('extended_bson', self.dataset))) as data:
|
|
- self.document = BSON.encode(json.loads(data.read()))
|
|
+ self.document = encode(json.loads(data.read()))
|
|
|
|
def do_task(self):
|
|
for _ in range(NUM_DOCS):
|
|
diff --git a/test/test_binary.py b/test/test_binary.py
|
|
index b5fbb92a..392cd97c 100644
|
|
--- a/test/test_binary.py
|
|
+++ b/test/test_binary.py
|
|
@@ -26,6 +26,7 @@ sys.path[0:0] = [""]
|
|
|
|
import bson
|
|
|
|
+from bson import decode, encode
|
|
from bson.binary import *
|
|
from bson.codec_options import CodecOptions
|
|
from bson.py3compat import PY3
|
|
@@ -146,10 +147,10 @@ class TestBinary(unittest.TestCase):
|
|
"""uuid_representation should be ignored when decoding subtype 4."""
|
|
expected_uuid = uuid.uuid4()
|
|
doc = {"uuid": Binary(expected_uuid.bytes, 4)}
|
|
- encoded = bson.BSON.encode(doc)
|
|
+ encoded = encode(doc)
|
|
for uuid_representation in ALL_UUID_REPRESENTATIONS:
|
|
options = CodecOptions(uuid_representation=uuid_representation)
|
|
- self.assertEqual(expected_uuid, encoded.decode(options)["uuid"])
|
|
+ self.assertEqual(expected_uuid, decode(encoded, options)["uuid"])
|
|
|
|
def test_legacy_java_uuid(self):
|
|
# Test decoding
|
|
@@ -172,31 +173,23 @@ class TestBinary(unittest.TestCase):
|
|
|
|
# Test encoding
|
|
encoded = b''.join([
|
|
- bson.BSON.encode(doc,
|
|
- False,
|
|
- CodecOptions(uuid_representation=PYTHON_LEGACY))
|
|
+ encode(doc, False, CodecOptions(uuid_representation=PYTHON_LEGACY))
|
|
for doc in docs])
|
|
self.assertNotEqual(data, encoded)
|
|
|
|
- encoded = b''.join(
|
|
- [bson.BSON.encode(doc,
|
|
- False,
|
|
- CodecOptions(uuid_representation=STANDARD))
|
|
- for doc in docs])
|
|
+ encoded = b''.join([
|
|
+ encode(doc, False, CodecOptions(uuid_representation=STANDARD))
|
|
+ for doc in docs])
|
|
self.assertNotEqual(data, encoded)
|
|
|
|
- encoded = b''.join(
|
|
- [bson.BSON.encode(doc,
|
|
- False,
|
|
- CodecOptions(uuid_representation=CSHARP_LEGACY))
|
|
- for doc in docs])
|
|
+ encoded = b''.join([
|
|
+ encode(doc, False, CodecOptions(uuid_representation=CSHARP_LEGACY))
|
|
+ for doc in docs])
|
|
self.assertNotEqual(data, encoded)
|
|
|
|
- encoded = b''.join(
|
|
- [bson.BSON.encode(doc,
|
|
- False,
|
|
- CodecOptions(uuid_representation=JAVA_LEGACY))
|
|
- for doc in docs])
|
|
+ encoded = b''.join([
|
|
+ encode(doc, False, CodecOptions(uuid_representation=JAVA_LEGACY))
|
|
+ for doc in docs])
|
|
self.assertEqual(data, encoded)
|
|
|
|
@client_context.require_connection
|
|
@@ -242,31 +235,23 @@ class TestBinary(unittest.TestCase):
|
|
|
|
# Test encoding
|
|
encoded = b''.join([
|
|
- bson.BSON.encode(doc,
|
|
- False,
|
|
- CodecOptions(uuid_representation=PYTHON_LEGACY))
|
|
+ encode(doc, False, CodecOptions(uuid_representation=PYTHON_LEGACY))
|
|
for doc in docs])
|
|
self.assertNotEqual(data, encoded)
|
|
|
|
encoded = b''.join([
|
|
- bson.BSON.encode(doc,
|
|
- False,
|
|
- CodecOptions(uuid_representation=STANDARD))
|
|
+ encode(doc, False, CodecOptions(uuid_representation=STANDARD))
|
|
for doc in docs])
|
|
self.assertNotEqual(data, encoded)
|
|
|
|
- encoded = b''.join(
|
|
- [bson.BSON.encode(doc,
|
|
- False,
|
|
- CodecOptions(uuid_representation=JAVA_LEGACY))
|
|
- for doc in docs])
|
|
+ encoded = b''.join([
|
|
+ encode(doc, False, CodecOptions(uuid_representation=JAVA_LEGACY))
|
|
+ for doc in docs])
|
|
self.assertNotEqual(data, encoded)
|
|
|
|
- encoded = b''.join(
|
|
- [bson.BSON.encode(doc,
|
|
- False,
|
|
- CodecOptions(uuid_representation=CSHARP_LEGACY))
|
|
- for doc in docs])
|
|
+ encoded = b''.join([
|
|
+ encode(doc, False, CodecOptions(uuid_representation=CSHARP_LEGACY))
|
|
+ for doc in docs])
|
|
self.assertEqual(data, encoded)
|
|
|
|
@client_context.require_connection
|
|
diff --git a/test/test_bson.py b/test/test_bson.py
|
|
index 3380ff0c..0e1b8e1b 100644
|
|
--- a/test/test_bson.py
|
|
+++ b/test/test_bson.py
|
|
@@ -116,23 +116,23 @@ class DSTAwareTimezone(datetime.tzinfo):
|
|
|
|
class TestBSON(unittest.TestCase):
|
|
def assertInvalid(self, data):
|
|
- self.assertRaises(InvalidBSON, bson.BSON(data).decode)
|
|
+ self.assertRaises(InvalidBSON, decode, data)
|
|
|
|
- def check_encode_then_decode(self, doc_class=dict):
|
|
+ def check_encode_then_decode(self, doc_class=dict, decoder=decode,
|
|
+ encoder=encode):
|
|
|
|
# Work around http://bugs.jython.org/issue1728
|
|
if sys.platform.startswith('java'):
|
|
doc_class = SON
|
|
|
|
def helper(doc):
|
|
- self.assertEqual(doc, (BSON.encode(doc_class(doc))).decode())
|
|
- self.assertEqual(doc, decode(encode(doc)))
|
|
+ self.assertEqual(doc, (decoder(encoder(doc_class(doc)))))
|
|
+ self.assertEqual(doc, decoder(encoder(doc)))
|
|
|
|
helper({})
|
|
helper({"test": u"hello"})
|
|
- self.assertTrue(isinstance(BSON.encode({"hello": "world"})
|
|
- .decode()["hello"],
|
|
- text_type))
|
|
+ self.assertTrue(isinstance(decoder(encoder(
|
|
+ {"hello": "world"}))["hello"], text_type))
|
|
helper({"mike": -10120})
|
|
helper({"long": Int64(10)})
|
|
helper({"really big long": 2147483648})
|
|
@@ -160,8 +160,8 @@ class TestBSON(unittest.TestCase):
|
|
helper({"$field": Code("return function(){ return x; }", scope={'x': False})})
|
|
|
|
def encode_then_decode(doc):
|
|
- return doc_class(doc) == BSON.encode(doc).decode(
|
|
- CodecOptions(document_class=doc_class))
|
|
+ return doc_class(doc) == decoder(encode(doc), CodecOptions(
|
|
+ document_class=doc_class))
|
|
|
|
qcheck.check_unittest(self, encode_then_decode,
|
|
qcheck.gen_mongo_dict(3))
|
|
@@ -172,9 +172,19 @@ class TestBSON(unittest.TestCase):
|
|
def test_encode_then_decode_any_mapping(self):
|
|
self.check_encode_then_decode(doc_class=NotADict)
|
|
|
|
+ def test_encode_then_decode_legacy(self):
|
|
+ self.check_encode_then_decode(
|
|
+ encoder=BSON.encode,
|
|
+ decoder=lambda *args: BSON(args[0]).decode(*args[1:]))
|
|
+
|
|
+ def test_encode_then_decode_any_mapping_legacy(self):
|
|
+ self.check_encode_then_decode(
|
|
+ doc_class=NotADict, encoder=BSON.encode,
|
|
+ decoder=lambda *args: BSON(args[0]).decode(*args[1:]))
|
|
+
|
|
def test_encoding_defaultdict(self):
|
|
dct = collections.defaultdict(dict, [('foo', 'bar')])
|
|
- BSON.encode(dct)
|
|
+ encode(dct)
|
|
self.assertEqual(dct, collections.defaultdict(dict, [('foo', 'bar')]))
|
|
|
|
def test_basic_validation(self):
|
|
@@ -266,9 +276,9 @@ class TestBSON(unittest.TestCase):
|
|
|
|
def test_basic_decode(self):
|
|
self.assertEqual({"test": u"hello world"},
|
|
- BSON(b"\x1B\x00\x00\x00\x0E\x74\x65\x73\x74\x00\x0C"
|
|
- b"\x00\x00\x00\x68\x65\x6C\x6C\x6F\x20\x77\x6F"
|
|
- b"\x72\x6C\x64\x00\x00").decode())
|
|
+ decode(b"\x1B\x00\x00\x00\x0E\x74\x65\x73\x74\x00\x0C"
|
|
+ b"\x00\x00\x00\x68\x65\x6C\x6C\x6F\x20\x77\x6F"
|
|
+ b"\x72\x6C\x64\x00\x00"))
|
|
self.assertEqual([{"test": u"hello world"}, {}],
|
|
decode_all(b"\x1B\x00\x00\x00\x0E\x74\x65\x73\x74"
|
|
b"\x00\x0C\x00\x00\x00\x68\x65\x6C\x6C"
|
|
@@ -289,7 +299,7 @@ class TestBSON(unittest.TestCase):
|
|
|
|
def test_decode_all_buffer_protocol(self):
|
|
docs = [{'foo': 'bar'}, {}]
|
|
- bs = b"".join(map(BSON.encode, docs))
|
|
+ bs = b"".join(map(encode, docs))
|
|
self.assertEqual(docs, decode_all(bytearray(bs)))
|
|
self.assertEqual(docs, decode_all(memoryview(bs)))
|
|
self.assertEqual(docs, decode_all(memoryview(b'1' + bs + b'1')[1:-1]))
|
|
@@ -363,79 +373,80 @@ class TestBSON(unittest.TestCase):
|
|
|
|
def test_data_timestamp(self):
|
|
self.assertEqual({"test": Timestamp(4, 20)},
|
|
- BSON(b"\x13\x00\x00\x00\x11\x74\x65\x73\x74\x00\x14"
|
|
- b"\x00\x00\x00\x04\x00\x00\x00\x00").decode())
|
|
+ decode(b"\x13\x00\x00\x00\x11\x74\x65\x73\x74\x00\x14"
|
|
+ b"\x00\x00\x00\x04\x00\x00\x00\x00"))
|
|
|
|
def test_basic_encode(self):
|
|
- self.assertRaises(TypeError, BSON.encode, 100)
|
|
- self.assertRaises(TypeError, BSON.encode, "hello")
|
|
- self.assertRaises(TypeError, BSON.encode, None)
|
|
- self.assertRaises(TypeError, BSON.encode, [])
|
|
-
|
|
- self.assertEqual(BSON.encode({}), BSON(b"\x05\x00\x00\x00\x00"))
|
|
- self.assertEqual(BSON.encode({"test": u"hello world"}),
|
|
+ self.assertRaises(TypeError, encode, 100)
|
|
+ self.assertRaises(TypeError, encode, "hello")
|
|
+ self.assertRaises(TypeError, encode, None)
|
|
+ self.assertRaises(TypeError, encode, [])
|
|
+
|
|
+ self.assertEqual(encode({}), BSON(b"\x05\x00\x00\x00\x00"))
|
|
+ self.assertEqual(encode({}), b"\x05\x00\x00\x00\x00")
|
|
+ self.assertEqual(encode({"test": u"hello world"}),
|
|
b"\x1B\x00\x00\x00\x02\x74\x65\x73\x74\x00\x0C\x00"
|
|
b"\x00\x00\x68\x65\x6C\x6C\x6F\x20\x77\x6F\x72\x6C"
|
|
b"\x64\x00\x00")
|
|
- self.assertEqual(BSON.encode({u"mike": 100}),
|
|
+ self.assertEqual(encode({u"mike": 100}),
|
|
b"\x0F\x00\x00\x00\x10\x6D\x69\x6B\x65\x00\x64\x00"
|
|
b"\x00\x00\x00")
|
|
- self.assertEqual(BSON.encode({"hello": 1.5}),
|
|
+ self.assertEqual(encode({"hello": 1.5}),
|
|
b"\x14\x00\x00\x00\x01\x68\x65\x6C\x6C\x6F\x00\x00"
|
|
b"\x00\x00\x00\x00\x00\xF8\x3F\x00")
|
|
- self.assertEqual(BSON.encode({"true": True}),
|
|
+ self.assertEqual(encode({"true": True}),
|
|
b"\x0C\x00\x00\x00\x08\x74\x72\x75\x65\x00\x01\x00")
|
|
- self.assertEqual(BSON.encode({"false": False}),
|
|
+ self.assertEqual(encode({"false": False}),
|
|
b"\x0D\x00\x00\x00\x08\x66\x61\x6C\x73\x65\x00\x00"
|
|
b"\x00")
|
|
- self.assertEqual(BSON.encode({"empty": []}),
|
|
+ self.assertEqual(encode({"empty": []}),
|
|
b"\x11\x00\x00\x00\x04\x65\x6D\x70\x74\x79\x00\x05"
|
|
b"\x00\x00\x00\x00\x00")
|
|
- self.assertEqual(BSON.encode({"none": {}}),
|
|
+ self.assertEqual(encode({"none": {}}),
|
|
b"\x10\x00\x00\x00\x03\x6E\x6F\x6E\x65\x00\x05\x00"
|
|
b"\x00\x00\x00\x00")
|
|
- self.assertEqual(BSON.encode({"test": Binary(b"test", 0)}),
|
|
+ self.assertEqual(encode({"test": Binary(b"test", 0)}),
|
|
b"\x14\x00\x00\x00\x05\x74\x65\x73\x74\x00\x04\x00"
|
|
b"\x00\x00\x00\x74\x65\x73\x74\x00")
|
|
- self.assertEqual(BSON.encode({"test": Binary(b"test", 2)}),
|
|
+ self.assertEqual(encode({"test": Binary(b"test", 2)}),
|
|
b"\x18\x00\x00\x00\x05\x74\x65\x73\x74\x00\x08\x00"
|
|
b"\x00\x00\x02\x04\x00\x00\x00\x74\x65\x73\x74\x00")
|
|
- self.assertEqual(BSON.encode({"test": Binary(b"test", 128)}),
|
|
+ self.assertEqual(encode({"test": Binary(b"test", 128)}),
|
|
b"\x14\x00\x00\x00\x05\x74\x65\x73\x74\x00\x04\x00"
|
|
b"\x00\x00\x80\x74\x65\x73\x74\x00")
|
|
- self.assertEqual(BSON.encode({"test": None}),
|
|
+ self.assertEqual(encode({"test": None}),
|
|
b"\x0B\x00\x00\x00\x0A\x74\x65\x73\x74\x00\x00")
|
|
- self.assertEqual(BSON.encode({"date": datetime.datetime(2007, 1, 8,
|
|
+ self.assertEqual(encode({"date": datetime.datetime(2007, 1, 8,
|
|
0, 30, 11)}),
|
|
b"\x13\x00\x00\x00\x09\x64\x61\x74\x65\x00\x38\xBE"
|
|
b"\x1C\xFF\x0F\x01\x00\x00\x00")
|
|
- self.assertEqual(BSON.encode({"regex": re.compile(b"a*b",
|
|
+ self.assertEqual(encode({"regex": re.compile(b"a*b",
|
|
re.IGNORECASE)}),
|
|
b"\x12\x00\x00\x00\x0B\x72\x65\x67\x65\x78\x00\x61"
|
|
b"\x2A\x62\x00\x69\x00\x00")
|
|
- self.assertEqual(BSON.encode({"$where": Code("test")}),
|
|
+ self.assertEqual(encode({"$where": Code("test")}),
|
|
b"\x16\x00\x00\x00\r$where\x00\x05\x00\x00\x00test"
|
|
b"\x00\x00")
|
|
- self.assertEqual(BSON.encode({"$field":
|
|
+ self.assertEqual(encode({"$field":
|
|
Code("function(){ return true;}", scope=None)}),
|
|
b"+\x00\x00\x00\r$field\x00\x1a\x00\x00\x00"
|
|
b"function(){ return true;}\x00\x00")
|
|
- self.assertEqual(BSON.encode({"$field":
|
|
+ self.assertEqual(encode({"$field":
|
|
Code("return function(){ return x; }",
|
|
scope={'x': False})}),
|
|
b"=\x00\x00\x00\x0f$field\x000\x00\x00\x00\x1f\x00"
|
|
b"\x00\x00return function(){ return x; }\x00\t\x00"
|
|
b"\x00\x00\x08x\x00\x00\x00\x00")
|
|
unicode_empty_scope = Code(u"function(){ return 'héllo';}", {})
|
|
- self.assertEqual(BSON.encode({'$field': unicode_empty_scope}),
|
|
+ self.assertEqual(encode({'$field': unicode_empty_scope}),
|
|
b"8\x00\x00\x00\x0f$field\x00+\x00\x00\x00\x1e\x00"
|
|
b"\x00\x00function(){ return 'h\xc3\xa9llo';}\x00\x05"
|
|
b"\x00\x00\x00\x00\x00")
|
|
a = ObjectId(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B")
|
|
- self.assertEqual(BSON.encode({"oid": a}),
|
|
+ self.assertEqual(encode({"oid": a}),
|
|
b"\x16\x00\x00\x00\x07\x6F\x69\x64\x00\x00\x01\x02"
|
|
b"\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x00")
|
|
- self.assertEqual(BSON.encode({"ref": DBRef("coll", a)}),
|
|
+ self.assertEqual(encode({"ref": DBRef("coll", a)}),
|
|
b"\x2F\x00\x00\x00\x03ref\x00\x25\x00\x00\x00\x02"
|
|
b"$ref\x00\x05\x00\x00\x00coll\x00\x07$id\x00\x00"
|
|
b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x00"
|
|
@@ -452,7 +463,7 @@ class TestBSON(unittest.TestCase):
|
|
b'\x00\x14foo\x00\x01\x00\x00\x00\x00\x00\x00')]
|
|
for bs in docs:
|
|
try:
|
|
- bson.BSON(bs).decode()
|
|
+ decode(bs)
|
|
except Exception as exc:
|
|
self.assertTrue(isinstance(exc, InvalidBSON))
|
|
self.assertTrue(part in str(exc))
|
|
@@ -470,15 +481,15 @@ class TestBSON(unittest.TestCase):
|
|
b"\x00\x00RY\xb5j\xfa[\xd8A\xd6X]\x99\x00")
|
|
|
|
self.assertEqual({'': DBRef('', ObjectId('5259b56afa5bd841d6585d99'))},
|
|
- bson.BSON(bs).decode())
|
|
+ decode(bs))
|
|
|
|
def test_bad_dbref(self):
|
|
ref_only = {'ref': {'$ref': 'collection'}}
|
|
id_only = {'ref': {'$id': ObjectId()}}
|
|
|
|
self.assertEqual(DBRef('collection', id=None),
|
|
- BSON.encode(ref_only).decode()['ref'])
|
|
- self.assertEqual(id_only, BSON.encode(id_only).decode())
|
|
+ decode(encode(ref_only))['ref'])
|
|
+ self.assertEqual(id_only, decode(encode(id_only)))
|
|
|
|
def test_bytes_as_keys(self):
|
|
doc = {b"foo": 'bar'}
|
|
@@ -486,33 +497,33 @@ class TestBSON(unittest.TestCase):
|
|
# as keys in python 3.x. Using binary data as a key makes
|
|
# no sense in BSON anyway and little sense in python.
|
|
if PY3:
|
|
- self.assertRaises(InvalidDocument, BSON.encode, doc)
|
|
+ self.assertRaises(InvalidDocument, encode, doc)
|
|
else:
|
|
- self.assertTrue(BSON.encode(doc))
|
|
+ self.assertTrue(encode(doc))
|
|
|
|
def test_datetime_encode_decode(self):
|
|
# Negative timestamps
|
|
dt1 = datetime.datetime(1, 1, 1, 1, 1, 1, 111000)
|
|
- dt2 = BSON.encode({"date": dt1}).decode()["date"]
|
|
+ dt2 = decode(encode({"date": dt1}))["date"]
|
|
self.assertEqual(dt1, dt2)
|
|
|
|
dt1 = datetime.datetime(1959, 6, 25, 12, 16, 59, 999000)
|
|
- dt2 = BSON.encode({"date": dt1}).decode()["date"]
|
|
+ dt2 = decode(encode({"date": dt1}))["date"]
|
|
self.assertEqual(dt1, dt2)
|
|
|
|
# Positive timestamps
|
|
dt1 = datetime.datetime(9999, 12, 31, 23, 59, 59, 999000)
|
|
- dt2 = BSON.encode({"date": dt1}).decode()["date"]
|
|
+ dt2 = decode(encode({"date": dt1}))["date"]
|
|
self.assertEqual(dt1, dt2)
|
|
|
|
dt1 = datetime.datetime(2011, 6, 14, 10, 47, 53, 444000)
|
|
- dt2 = BSON.encode({"date": dt1}).decode()["date"]
|
|
+ dt2 = decode(encode({"date": dt1}))["date"]
|
|
self.assertEqual(dt1, dt2)
|
|
|
|
def test_large_datetime_truncation(self):
|
|
# Ensure that a large datetime is truncated correctly.
|
|
dt1 = datetime.datetime(9999, 1, 1, 1, 1, 1, 999999)
|
|
- dt2 = BSON.encode({"date": dt1}).decode()["date"]
|
|
+ dt2 = decode(encode({"date": dt1}))["date"]
|
|
self.assertEqual(dt2.microsecond, 999000)
|
|
self.assertEqual(dt2.second, dt1.second)
|
|
|
|
@@ -522,8 +533,8 @@ class TestBSON(unittest.TestCase):
|
|
as_utc = (aware - aware.utcoffset()).replace(tzinfo=utc)
|
|
self.assertEqual(datetime.datetime(1993, 4, 3, 16, 45, tzinfo=utc),
|
|
as_utc)
|
|
- after = BSON.encode({"date": aware}).decode(
|
|
- CodecOptions(tz_aware=True))["date"]
|
|
+ after = decode(encode({"date": aware}), CodecOptions(tz_aware=True))[
|
|
+ "date"]
|
|
self.assertEqual(utc, after.tzinfo)
|
|
self.assertEqual(as_utc, after)
|
|
|
|
@@ -536,29 +547,27 @@ class TestBSON(unittest.TestCase):
|
|
tzinfo=tz)
|
|
options = CodecOptions(tz_aware=True, tzinfo=tz)
|
|
# Encode with this timezone, then decode to UTC.
|
|
- encoded = BSON.encode({'date': local}, codec_options=options)
|
|
+ encoded = encode({'date': local}, codec_options=options)
|
|
self.assertEqual(local.replace(hour=1, tzinfo=None),
|
|
- encoded.decode()['date'])
|
|
+ decode(encoded)['date'])
|
|
|
|
# It's DST.
|
|
local = datetime.datetime(year=2025, month=4, hour=1, day=1,
|
|
tzinfo=tz)
|
|
- encoded = BSON.encode({'date': local}, codec_options=options)
|
|
+ encoded = encode({'date': local}, codec_options=options)
|
|
self.assertEqual(local.replace(month=3, day=31, hour=23, tzinfo=None),
|
|
- encoded.decode()['date'])
|
|
+ decode(encoded)['date'])
|
|
|
|
# Encode UTC, then decode in a different timezone.
|
|
- encoded = BSON.encode({'date': local.replace(tzinfo=utc)})
|
|
- decoded = encoded.decode(options)['date']
|
|
+ encoded = encode({'date': local.replace(tzinfo=utc)})
|
|
+ decoded = decode(encoded, options)['date']
|
|
self.assertEqual(local.replace(hour=3), decoded)
|
|
self.assertEqual(tz, decoded.tzinfo)
|
|
|
|
# Test round-tripping.
|
|
self.assertEqual(
|
|
- local,
|
|
- (BSON
|
|
- .encode({'date': local}, codec_options=options)
|
|
- .decode(options)['date']))
|
|
+ local, decode(encode(
|
|
+ {'date': local}, codec_options=options), options)['date'])
|
|
|
|
# Test around the Unix Epoch.
|
|
epochs = (
|
|
@@ -572,25 +581,25 @@ class TestBSON(unittest.TestCase):
|
|
# We always retrieve datetimes in UTC unless told to do otherwise.
|
|
self.assertEqual(
|
|
EPOCH_AWARE,
|
|
- BSON.encode(doc).decode(codec_options=utc_co)['epoch'])
|
|
+ decode(encode(doc), codec_options=utc_co)['epoch'])
|
|
# Round-trip the epoch.
|
|
local_co = CodecOptions(tz_aware=True, tzinfo=epoch.tzinfo)
|
|
self.assertEqual(
|
|
epoch,
|
|
- BSON.encode(doc).decode(codec_options=local_co)['epoch'])
|
|
+ decode(encode(doc), codec_options=local_co)['epoch'])
|
|
|
|
def test_naive_decode(self):
|
|
aware = datetime.datetime(1993, 4, 4, 2,
|
|
tzinfo=FixedOffset(555, "SomeZone"))
|
|
naive_utc = (aware - aware.utcoffset()).replace(tzinfo=None)
|
|
self.assertEqual(datetime.datetime(1993, 4, 3, 16, 45), naive_utc)
|
|
- after = BSON.encode({"date": aware}).decode()["date"]
|
|
+ after = decode(encode({"date": aware}))["date"]
|
|
self.assertEqual(None, after.tzinfo)
|
|
self.assertEqual(naive_utc, after)
|
|
|
|
def test_dst(self):
|
|
d = {"x": datetime.datetime(1993, 4, 4, 2)}
|
|
- self.assertEqual(d, BSON.encode(d).decode())
|
|
+ self.assertEqual(d, decode(encode(d)))
|
|
|
|
def test_bad_encode(self):
|
|
if not PY3:
|
|
@@ -598,7 +607,7 @@ class TestBSON(unittest.TestCase):
|
|
# an exception. If we passed the string as bytes instead we
|
|
# still wouldn't get an error since we store bytes as BSON
|
|
# binary subtype 0.
|
|
- self.assertRaises(InvalidStringData, BSON.encode,
|
|
+ self.assertRaises(InvalidStringData, encode,
|
|
{"lalala": '\xf4\xe0\xf0\xe1\xc0 Color Touch'})
|
|
# Work around what seems like a regression in python 3.5.0.
|
|
# See http://bugs.python.org/issue25222
|
|
@@ -608,25 +617,25 @@ class TestBSON(unittest.TestCase):
|
|
evil_dict = {}
|
|
evil_dict['a'] = evil_dict
|
|
for evil_data in [evil_dict, evil_list]:
|
|
- self.assertRaises(Exception, BSON.encode, evil_data)
|
|
+ self.assertRaises(Exception, encode, evil_data)
|
|
|
|
def test_overflow(self):
|
|
- self.assertTrue(BSON.encode({"x": long(9223372036854775807)}))
|
|
- self.assertRaises(OverflowError, BSON.encode,
|
|
+ self.assertTrue(encode({"x": long(9223372036854775807)}))
|
|
+ self.assertRaises(OverflowError, encode,
|
|
{"x": long(9223372036854775808)})
|
|
|
|
- self.assertTrue(BSON.encode({"x": long(-9223372036854775808)}))
|
|
- self.assertRaises(OverflowError, BSON.encode,
|
|
+ self.assertTrue(encode({"x": long(-9223372036854775808)}))
|
|
+ self.assertRaises(OverflowError, encode,
|
|
{"x": long(-9223372036854775809)})
|
|
|
|
def test_small_long_encode_decode(self):
|
|
- encoded1 = BSON.encode({'x': 256})
|
|
- decoded1 = BSON(encoded1).decode()['x']
|
|
+ encoded1 = encode({'x': 256})
|
|
+ decoded1 = decode(encoded1)['x']
|
|
self.assertEqual(256, decoded1)
|
|
self.assertEqual(type(256), type(decoded1))
|
|
|
|
- encoded2 = BSON.encode({'x': Int64(256)})
|
|
- decoded2 = BSON(encoded2).decode()['x']
|
|
+ encoded2 = encode({'x': Int64(256)})
|
|
+ decoded2 = decode(encoded2)['x']
|
|
expected = Int64(256)
|
|
self.assertEqual(expected, decoded2)
|
|
self.assertEqual(type(expected), type(decoded2))
|
|
@@ -635,12 +644,12 @@ class TestBSON(unittest.TestCase):
|
|
|
|
def test_tuple(self):
|
|
self.assertEqual({"tuple": [1, 2]},
|
|
- BSON.encode({"tuple": (1, 2)}).decode())
|
|
+ decode(encode({"tuple": (1, 2)})))
|
|
|
|
def test_uuid(self):
|
|
|
|
id = uuid.uuid4()
|
|
- transformed_id = (BSON.encode({"id": id})).decode()["id"]
|
|
+ transformed_id = decode(encode({"id": id}))["id"]
|
|
|
|
self.assertTrue(isinstance(transformed_id, uuid.UUID))
|
|
self.assertEqual(id, transformed_id)
|
|
@@ -651,7 +660,7 @@ class TestBSON(unittest.TestCase):
|
|
id = uuid.uuid4()
|
|
legacy = UUIDLegacy(id)
|
|
self.assertEqual(3, legacy.subtype)
|
|
- transformed = (BSON.encode({"uuid": legacy})).decode()["uuid"]
|
|
+ transformed = decode(encode({"uuid": legacy}))["uuid"]
|
|
self.assertTrue(isinstance(transformed, uuid.UUID))
|
|
self.assertEqual(id, transformed)
|
|
self.assertNotEqual(UUIDLegacy(uuid.uuid4()), UUIDLegacy(transformed))
|
|
@@ -660,67 +669,67 @@ class TestBSON(unittest.TestCase):
|
|
# that doesn't really test anything but the lack of a segfault.
|
|
def test_unicode_regex(self):
|
|
regex = re.compile(u'revisi\xf3n')
|
|
- BSON.encode({"regex": regex}).decode()
|
|
+ decode(encode({"regex": regex}))
|
|
|
|
def test_non_string_keys(self):
|
|
- self.assertRaises(InvalidDocument, BSON.encode, {8.9: "test"})
|
|
+ self.assertRaises(InvalidDocument, encode, {8.9: "test"})
|
|
|
|
def test_utf8(self):
|
|
w = {u"aéあ": u"aéあ"}
|
|
- self.assertEqual(w, BSON.encode(w).decode())
|
|
+ self.assertEqual(w, decode(encode(w)))
|
|
|
|
# b'a\xe9' == u"aé".encode("iso-8859-1")
|
|
iso8859_bytes = b'a\xe9'
|
|
y = {"hello": iso8859_bytes}
|
|
if PY3:
|
|
# Stored as BSON binary subtype 0.
|
|
- out = BSON.encode(y).decode()
|
|
+ out = decode(encode(y))
|
|
self.assertTrue(isinstance(out['hello'], bytes))
|
|
self.assertEqual(out['hello'], iso8859_bytes)
|
|
else:
|
|
# Python 2.
|
|
try:
|
|
- BSON.encode(y)
|
|
+ encode(y)
|
|
except InvalidStringData as e:
|
|
self.assertTrue(repr(iso8859_bytes) in str(e))
|
|
|
|
# The next two tests only make sense in python 2.x since
|
|
# you can't use `bytes` type as document keys in python 3.x.
|
|
x = {u"aéあ".encode("utf-8"): u"aéあ".encode("utf-8")}
|
|
- self.assertEqual(w, BSON.encode(x).decode())
|
|
+ self.assertEqual(w, decode(encode(x)))
|
|
|
|
z = {iso8859_bytes: "hello"}
|
|
- self.assertRaises(InvalidStringData, BSON.encode, z)
|
|
+ self.assertRaises(InvalidStringData, encode, z)
|
|
|
|
def test_null_character(self):
|
|
doc = {"a": "\x00"}
|
|
- self.assertEqual(doc, BSON.encode(doc).decode())
|
|
+ self.assertEqual(doc, decode(encode(doc)))
|
|
|
|
# This test doesn't make much sense in Python2
|
|
# since {'a': '\x00'} == {'a': u'\x00'}.
|
|
# Decoding here actually returns {'a': '\x00'}
|
|
doc = {"a": u"\x00"}
|
|
- self.assertEqual(doc, BSON.encode(doc).decode())
|
|
+ self.assertEqual(doc, decode(encode(doc)))
|
|
|
|
- self.assertRaises(InvalidDocument, BSON.encode, {b"\x00": "a"})
|
|
- self.assertRaises(InvalidDocument, BSON.encode, {u"\x00": "a"})
|
|
+ self.assertRaises(InvalidDocument, encode, {b"\x00": "a"})
|
|
+ self.assertRaises(InvalidDocument, encode, {u"\x00": "a"})
|
|
|
|
- self.assertRaises(InvalidDocument, BSON.encode,
|
|
+ self.assertRaises(InvalidDocument, encode,
|
|
{"a": re.compile(b"ab\x00c")})
|
|
- self.assertRaises(InvalidDocument, BSON.encode,
|
|
+ self.assertRaises(InvalidDocument, encode,
|
|
{"a": re.compile(u"ab\x00c")})
|
|
|
|
def test_move_id(self):
|
|
self.assertEqual(b"\x19\x00\x00\x00\x02_id\x00\x02\x00\x00\x00a\x00"
|
|
b"\x02a\x00\x02\x00\x00\x00a\x00\x00",
|
|
- BSON.encode(SON([("a", "a"), ("_id", "a")])))
|
|
+ encode(SON([("a", "a"), ("_id", "a")])))
|
|
|
|
self.assertEqual(b"\x2c\x00\x00\x00"
|
|
b"\x02_id\x00\x02\x00\x00\x00b\x00"
|
|
b"\x03b\x00"
|
|
b"\x19\x00\x00\x00\x02a\x00\x02\x00\x00\x00a\x00"
|
|
b"\x02_id\x00\x02\x00\x00\x00a\x00\x00\x00",
|
|
- BSON.encode(SON([("b",
|
|
+ encode(SON([("b",
|
|
SON([("a", "a"), ("_id", "a")])),
|
|
("_id", "b")])))
|
|
|
|
@@ -728,7 +737,7 @@ class TestBSON(unittest.TestCase):
|
|
doc = {"early": datetime.datetime(1686, 5, 5),
|
|
"late": datetime.datetime(2086, 5, 5)}
|
|
try:
|
|
- self.assertEqual(doc, BSON.encode(doc).decode())
|
|
+ self.assertEqual(doc, decode(encode(doc)))
|
|
except ValueError:
|
|
# Ignore ValueError when no C ext, since it's probably
|
|
# a problem w/ 32-bit Python - we work around this in the
|
|
@@ -737,20 +746,17 @@ class TestBSON(unittest.TestCase):
|
|
raise
|
|
|
|
def test_custom_class(self):
|
|
- self.assertIsInstance(BSON.encode({}).decode(), dict)
|
|
- self.assertNotIsInstance(BSON.encode({}).decode(), SON)
|
|
+ self.assertIsInstance(decode(encode({})), dict)
|
|
+ self.assertNotIsInstance(decode(encode({})), SON)
|
|
self.assertIsInstance(
|
|
- BSON.encode({}).decode(CodecOptions(document_class=SON)),
|
|
- SON)
|
|
+ decode(encode({}), CodecOptions(document_class=SON)), SON)
|
|
|
|
self.assertEqual(
|
|
- 1,
|
|
- BSON.encode({"x": 1}).decode(
|
|
- CodecOptions(document_class=SON))["x"])
|
|
+ 1, decode(encode({"x": 1}), CodecOptions(document_class=SON))["x"])
|
|
|
|
- x = BSON.encode({"x": [{"y": 1}]})
|
|
+ x = encode({"x": [{"y": 1}]})
|
|
self.assertIsInstance(
|
|
- x.decode(CodecOptions(document_class=SON))["x"][0], SON)
|
|
+ decode(x, CodecOptions(document_class=SON))["x"][0], SON)
|
|
|
|
def test_subclasses(self):
|
|
# make sure we can serialize subclasses of native Python types.
|
|
@@ -766,7 +772,7 @@ class TestBSON(unittest.TestCase):
|
|
d = {'a': _myint(42), 'b': _myfloat(63.9),
|
|
'c': _myunicode('hello world')
|
|
}
|
|
- d2 = BSON.encode(d).decode()
|
|
+ d2 = decode(encode(d))
|
|
for key, value in iteritems(d2):
|
|
orig_value = d[key]
|
|
orig_type = orig_value.__class__.__bases__[0]
|
|
@@ -780,8 +786,7 @@ class TestBSON(unittest.TestCase):
|
|
raise SkipTest("No OrderedDict")
|
|
d = OrderedDict([("one", 1), ("two", 2), ("three", 3), ("four", 4)])
|
|
self.assertEqual(
|
|
- d,
|
|
- BSON.encode(d).decode(CodecOptions(document_class=OrderedDict)))
|
|
+ d, decode(encode(d), CodecOptions(document_class=OrderedDict)))
|
|
|
|
def test_bson_regex(self):
|
|
# Invalid Python regex, though valid PCRE.
|
|
@@ -795,8 +800,8 @@ class TestBSON(unittest.TestCase):
|
|
b'\x0br\x00[\\w-\\.]\x00\x00' # r: regex
|
|
b'\x00') # document terminator
|
|
|
|
- self.assertEqual(doc1_bson, BSON.encode(doc1))
|
|
- self.assertEqual(doc1, BSON(doc1_bson).decode())
|
|
+ self.assertEqual(doc1_bson, encode(doc1))
|
|
+ self.assertEqual(doc1, decode(doc1_bson))
|
|
|
|
# Valid Python regex, with flags.
|
|
re2 = re.compile(u'.*', re.I | re.M | re.S | re.U | re.X)
|
|
@@ -809,11 +814,11 @@ class TestBSON(unittest.TestCase):
|
|
b"\x0br\x00.*\x00imsux\x00" # r: regex
|
|
b"\x00") # document terminator
|
|
|
|
- self.assertEqual(doc2_bson, BSON.encode(doc2_with_re))
|
|
- self.assertEqual(doc2_bson, BSON.encode(doc2_with_bson_re))
|
|
+ self.assertEqual(doc2_bson, encode(doc2_with_re))
|
|
+ self.assertEqual(doc2_bson, encode(doc2_with_bson_re))
|
|
|
|
- self.assertEqual(re2.pattern, BSON(doc2_bson).decode()['r'].pattern)
|
|
- self.assertEqual(re2.flags, BSON(doc2_bson).decode()['r'].flags)
|
|
+ self.assertEqual(re2.pattern, decode(doc2_bson)['r'].pattern)
|
|
+ self.assertEqual(re2.flags, decode(doc2_bson)['r'].flags)
|
|
|
|
def test_regex_from_native(self):
|
|
self.assertEqual('.*', Regex.from_native(re.compile('.*')).pattern)
|
|
@@ -930,22 +935,22 @@ class TestBSON(unittest.TestCase):
|
|
doc_bson = (b'\x10\x00\x00\x00'
|
|
b'\x11a\x00\xff\xff\xff\xff\xff\xff\xff\xff'
|
|
b'\x00')
|
|
- self.assertEqual(doc_bson, BSON.encode(doc))
|
|
- self.assertEqual(doc, BSON(doc_bson).decode())
|
|
+ self.assertEqual(doc_bson, encode(doc))
|
|
+ self.assertEqual(doc, decode(doc_bson))
|
|
|
|
def test_bad_id_keys(self):
|
|
- self.assertRaises(InvalidDocument, BSON.encode,
|
|
+ self.assertRaises(InvalidDocument, encode,
|
|
{"_id": {"$bad": 123}}, True)
|
|
- self.assertRaises(InvalidDocument, BSON.encode,
|
|
+ self.assertRaises(InvalidDocument, encode,
|
|
{"_id": {'$oid': "52d0b971b3ba219fdeb4170e"}}, True)
|
|
- BSON.encode({"_id": {'$oid': "52d0b971b3ba219fdeb4170e"}})
|
|
+ encode({"_id": {'$oid': "52d0b971b3ba219fdeb4170e"}})
|
|
|
|
def test_bson_encode_thread_safe(self):
|
|
|
|
def target(i):
|
|
for j in range(1000):
|
|
my_int = type('MyInt_%s_%s' % (i, j), (int,), {})
|
|
- bson.BSON.encode({'my_int': my_int()})
|
|
+ bson.encode({'my_int': my_int()})
|
|
|
|
threads = [ExceptionCatchingThread(target=target, args=(i,))
|
|
for i in range(3)]
|
|
@@ -970,7 +975,7 @@ class TestBSON(unittest.TestCase):
|
|
with self.assertRaisesRegex(
|
|
InvalidDocument,
|
|
"cannot encode object: 1, of type: " + repr(Wrapper)):
|
|
- BSON.encode({'t': Wrapper(1)})
|
|
+ encode({'t': Wrapper(1)})
|
|
|
|
|
|
class TestCodecOptions(unittest.TestCase):
|
|
@@ -1011,77 +1016,73 @@ class TestCodecOptions(unittest.TestCase):
|
|
'uuid': uuid.uuid4(),
|
|
'dt': datetime.datetime.utcnow()}
|
|
|
|
- decoded = bson.decode_all(bson.BSON.encode(doc))[0]
|
|
+ decoded = bson.decode_all(bson.encode(doc))[0]
|
|
self.assertIsInstance(decoded['sub_document'], dict)
|
|
self.assertEqual(decoded['uuid'], doc['uuid'])
|
|
self.assertIsNone(decoded['dt'].tzinfo)
|
|
|
|
def test_unicode_decode_error_handler(self):
|
|
- enc = BSON.encode({"keystr": "foobar"})
|
|
+ enc = encode({"keystr": "foobar"})
|
|
|
|
# Test handling of bad key value.
|
|
- invalid_key = BSON(enc[:7] + b'\xe9' + enc[8:])
|
|
+ invalid_key = enc[:7] + b'\xe9' + enc[8:]
|
|
replaced_key = b'ke\xe9str'.decode('utf-8', 'replace')
|
|
ignored_key = b'ke\xe9str'.decode('utf-8', 'ignore')
|
|
|
|
- dec = BSON(invalid_key).decode(CodecOptions(
|
|
- unicode_decode_error_handler="replace"))
|
|
+ dec = decode(invalid_key,
|
|
+ CodecOptions(unicode_decode_error_handler="replace"))
|
|
self.assertEqual(dec, {replaced_key: u"foobar"})
|
|
|
|
- dec = BSON(invalid_key).decode(CodecOptions(
|
|
- unicode_decode_error_handler="ignore"))
|
|
+ dec = decode(invalid_key,
|
|
+ CodecOptions(unicode_decode_error_handler="ignore"))
|
|
self.assertEqual(dec, {ignored_key: u"foobar"})
|
|
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_key).decode, CodecOptions(
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_key, CodecOptions(
|
|
unicode_decode_error_handler="strict"))
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_key).decode,
|
|
- CodecOptions())
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_key).decode)
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_key, CodecOptions())
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_key)
|
|
|
|
# Test handing of bad string value.
|
|
invalid_val = BSON(enc[:18] + b'\xe9' + enc[19:])
|
|
replaced_val = b'fo\xe9bar'.decode('utf-8', 'replace')
|
|
ignored_val = b'fo\xe9bar'.decode('utf-8', 'ignore')
|
|
|
|
- dec = BSON(invalid_val).decode(CodecOptions(
|
|
- unicode_decode_error_handler="replace"))
|
|
+ dec = decode(invalid_val,
|
|
+ CodecOptions(unicode_decode_error_handler="replace"))
|
|
self.assertEqual(dec, {u"keystr": replaced_val})
|
|
|
|
- dec = BSON(invalid_val).decode(CodecOptions(
|
|
- unicode_decode_error_handler="ignore"))
|
|
+ dec = decode(invalid_val,
|
|
+ CodecOptions(unicode_decode_error_handler="ignore"))
|
|
self.assertEqual(dec, {u"keystr": ignored_val})
|
|
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_val).decode, CodecOptions(
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_val, CodecOptions(
|
|
unicode_decode_error_handler="strict"))
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_val).decode,
|
|
- CodecOptions())
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_val).decode)
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_val, CodecOptions())
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_val)
|
|
|
|
# Test handing bad key + bad value.
|
|
- invalid_both = BSON(
|
|
- enc[:7] + b'\xe9' + enc[8:18] + b'\xe9' + enc[19:])
|
|
+ invalid_both = enc[:7] + b'\xe9' + enc[8:18] + b'\xe9' + enc[19:]
|
|
|
|
- dec = BSON(invalid_both).decode(CodecOptions(
|
|
- unicode_decode_error_handler="replace"))
|
|
+ dec = decode(invalid_both,
|
|
+ CodecOptions(unicode_decode_error_handler="replace"))
|
|
self.assertEqual(dec, {replaced_key: replaced_val})
|
|
|
|
- dec = BSON(invalid_both).decode(CodecOptions(
|
|
- unicode_decode_error_handler="ignore"))
|
|
+ dec = decode(invalid_both,
|
|
+ CodecOptions(unicode_decode_error_handler="ignore"))
|
|
self.assertEqual(dec, {ignored_key: ignored_val})
|
|
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_both).decode, CodecOptions(
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_both, CodecOptions(
|
|
unicode_decode_error_handler="strict"))
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_both).decode,
|
|
- CodecOptions())
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_both).decode)
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_both, CodecOptions())
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_both)
|
|
|
|
# Test handling bad error mode.
|
|
- dec = BSON(enc).decode(CodecOptions(
|
|
- unicode_decode_error_handler="junk"))
|
|
+ dec = decode(enc,
|
|
+ CodecOptions(unicode_decode_error_handler="junk"))
|
|
self.assertEqual(dec, {"keystr": "foobar"})
|
|
|
|
- self.assertRaises(InvalidBSON, BSON(invalid_both).decode,
|
|
- CodecOptions(unicode_decode_error_handler="junk"))
|
|
+ self.assertRaises(InvalidBSON, decode, invalid_both, CodecOptions(
|
|
+ unicode_decode_error_handler="junk"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
diff --git a/test/test_bson_corpus.py b/test/test_bson_corpus.py
|
|
index d836724d..0c461cf4 100644
|
|
--- a/test/test_bson_corpus.py
|
|
+++ b/test/test_bson_corpus.py
|
|
@@ -26,7 +26,7 @@ from decimal import DecimalException
|
|
|
|
sys.path[0:0] = [""]
|
|
|
|
-from bson import BSON, json_util
|
|
+from bson import decode, encode, json_util
|
|
from bson.binary import STANDARD
|
|
from bson.codec_options import CodecOptions
|
|
from bson.decimal128 import Decimal128
|
|
@@ -81,10 +81,10 @@ to_extjson_iso8601 = functools.partial(json_util.dumps,
|
|
json_options=json_options_iso8601)
|
|
to_relaxed_extjson = functools.partial(
|
|
json_util.dumps, json_options=json_util.RELAXED_JSON_OPTIONS)
|
|
-to_bson_uuid_04 = functools.partial(BSON.encode,
|
|
+to_bson_uuid_04 = functools.partial(encode,
|
|
codec_options=codec_options_uuid_04)
|
|
-to_bson = functools.partial(BSON.encode, codec_options=codec_options)
|
|
-decode_bson = lambda bbytes: BSON(bbytes).decode(codec_options=codec_options)
|
|
+to_bson = functools.partial(encode, codec_options=codec_options)
|
|
+decode_bson = lambda bbytes: decode(bbytes, codec_options=codec_options)
|
|
decode_extjson = functools.partial(
|
|
json_util.loads,
|
|
json_options=json_util.JSONOptions(json_mode=JSONMode.CANONICAL,
|
|
diff --git a/test/test_change_stream.py b/test/test_change_stream.py
|
|
index c9415c46..ced8af8c 100644
|
|
--- a/test/test_change_stream.py
|
|
+++ b/test/test_change_stream.py
|
|
@@ -27,7 +27,7 @@ from itertools import product
|
|
|
|
sys.path[0:0] = ['']
|
|
|
|
-from bson import BSON, ObjectId, SON, Timestamp, json_util
|
|
+from bson import ObjectId, SON, Timestamp, encode, json_util
|
|
from bson.binary import (ALL_UUID_REPRESENTATIONS,
|
|
Binary,
|
|
STANDARD,
|
|
@@ -965,7 +965,7 @@ class TestCollectionChangeStream(TestChangeStreamBase, APITestsMixin,
|
|
raw_coll = self.watched_collection(
|
|
codec_options=DEFAULT_RAW_BSON_OPTIONS)
|
|
with raw_coll.watch() as change_stream:
|
|
- raw_doc = RawBSONDocument(BSON.encode({'_id': 1}))
|
|
+ raw_doc = RawBSONDocument(encode({'_id': 1}))
|
|
self.watched_collection().insert_one(raw_doc)
|
|
change = next(change_stream)
|
|
self.assertIsInstance(change, RawBSONDocument)
|
|
diff --git a/test/test_client.py b/test/test_client.py
|
|
index 94856484..775402f5 100644
|
|
--- a/test/test_client.py
|
|
+++ b/test/test_client.py
|
|
@@ -28,7 +28,7 @@ import warnings
|
|
|
|
sys.path[0:0] = [""]
|
|
|
|
-from bson import BSON
|
|
+from bson import encode
|
|
from bson.codec_options import CodecOptions, TypeEncoder, TypeRegistry
|
|
from bson.py3compat import thread
|
|
from bson.son import SON
|
|
@@ -1512,7 +1512,7 @@ class TestExhaustCursor(IntegrationTest):
|
|
|
|
# responseFlags bit 1 is QueryFailure.
|
|
msg = struct.pack('<iiiii', 1 << 1, 0, 0, 0, 0)
|
|
- msg += BSON.encode({'$err': 'mock err', 'code': 0})
|
|
+ msg += encode({'$err': 'mock err', 'code': 0})
|
|
return message._OpReply.unpack(msg)
|
|
|
|
saved = sock_info.receive_message
|
|
diff --git a/test/test_collection.py b/test/test_collection.py
|
|
index 8b970506..f2172048 100644
|
|
--- a/test/test_collection.py
|
|
+++ b/test/test_collection.py
|
|
@@ -26,8 +26,7 @@ from collections import defaultdict
|
|
|
|
sys.path[0:0] = [""]
|
|
|
|
-import bson
|
|
-
|
|
+from bson import encode
|
|
from bson.raw_bson import RawBSONDocument
|
|
from bson.regex import Regex
|
|
from bson.code import Code
|
|
@@ -765,7 +764,7 @@ class TestCollection(IntegrationTest):
|
|
'forcing duplicate key error')
|
|
|
|
document = RawBSONDocument(
|
|
- bson.BSON.encode({'_id': ObjectId(), 'foo': 'bar'}))
|
|
+ encode({'_id': ObjectId(), 'foo': 'bar'}))
|
|
result = db.test.insert_one(document)
|
|
self.assertTrue(isinstance(result, InsertOneResult))
|
|
self.assertEqual(result.inserted_id, None)
|
|
@@ -798,7 +797,7 @@ class TestCollection(IntegrationTest):
|
|
self.assertEqual(1, db.test.count_documents({"_id": _id}))
|
|
self.assertTrue(result.acknowledged)
|
|
|
|
- docs = [RawBSONDocument(bson.BSON.encode({"_id": i + 5}))
|
|
+ docs = [RawBSONDocument(encode({"_id": i + 5}))
|
|
for i in range(5)]
|
|
result = db.test.insert_many(docs)
|
|
self.assertTrue(isinstance(result, InsertManyResult))
|
|
@@ -1397,7 +1396,7 @@ class TestCollection(IntegrationTest):
|
|
self.assertEqual(0, db.test.count_documents({"x": 1}))
|
|
self.assertEqual(db.test.find_one(id1)["y"], 1)
|
|
|
|
- replacement = RawBSONDocument(bson.BSON.encode({"_id": id1, "z": 1}))
|
|
+ replacement = RawBSONDocument(encode({"_id": id1, "z": 1}))
|
|
result = db.test.replace_one({"y": 1}, replacement, True)
|
|
self.assertTrue(isinstance(result, UpdateResult))
|
|
self.assertEqual(1, result.matched_count)
|
|
diff --git a/test/test_custom_types.py b/test/test_custom_types.py
|
|
index d7095da3..d5c75d99 100644
|
|
--- a/test/test_custom_types.py
|
|
+++ b/test/test_custom_types.py
|
|
@@ -23,11 +23,12 @@ from random import random
|
|
|
|
sys.path[0:0] = [""]
|
|
|
|
-from bson import (BSON,
|
|
- Decimal128,
|
|
+from bson import (Decimal128,
|
|
+ decode,
|
|
decode_all,
|
|
decode_file_iter,
|
|
decode_iter,
|
|
+ encode,
|
|
RE_TYPE,
|
|
_BUILT_IN_TYPES,
|
|
_dict_to_bson,
|
|
@@ -128,8 +129,8 @@ def type_obfuscating_decoder_factory(rt_type):
|
|
|
|
class CustomBSONTypeTests(object):
|
|
def roundtrip(self, doc):
|
|
- bsonbytes = BSON().encode(doc, codec_options=self.codecopts)
|
|
- rt_document = BSON(bsonbytes).decode(codec_options=self.codecopts)
|
|
+ bsonbytes = encode(doc, codec_options=self.codecopts)
|
|
+ rt_document = decode(bsonbytes, codec_options=self.codecopts)
|
|
self.assertEqual(doc, rt_document)
|
|
|
|
def test_encode_decode_roundtrip(self):
|
|
@@ -146,20 +147,20 @@ class CustomBSONTypeTests(object):
|
|
|
|
bsonstream = bytes()
|
|
for doc in documents:
|
|
- bsonstream += BSON.encode(doc, codec_options=self.codecopts)
|
|
+ bsonstream += encode(doc, codec_options=self.codecopts)
|
|
|
|
self.assertEqual(
|
|
decode_all(bsonstream, self.codecopts), documents)
|
|
|
|
def test__bson_to_dict(self):
|
|
document = {'average': Decimal('56.47')}
|
|
- rawbytes = BSON.encode(document, codec_options=self.codecopts)
|
|
+ rawbytes = encode(document, codec_options=self.codecopts)
|
|
decoded_document = _bson_to_dict(rawbytes, self.codecopts)
|
|
self.assertEqual(document, decoded_document)
|
|
|
|
def test__dict_to_bson(self):
|
|
document = {'average': Decimal('56.47')}
|
|
- rawbytes = BSON.encode(document, codec_options=self.codecopts)
|
|
+ rawbytes = encode(document, codec_options=self.codecopts)
|
|
encoded_document = _dict_to_bson(document, False, self.codecopts)
|
|
self.assertEqual(encoded_document, rawbytes)
|
|
|
|
@@ -169,7 +170,7 @@ class CustomBSONTypeTests(object):
|
|
edocs = [{'n': Decimal(dec)} for dec in inp_num]
|
|
bsonstream = b""
|
|
for doc in docs:
|
|
- bsonstream += BSON.encode(doc)
|
|
+ bsonstream += encode(doc)
|
|
return edocs, bsonstream
|
|
|
|
def test_decode_iter(self):
|
|
@@ -215,30 +216,30 @@ class TestBSONFallbackEncoder(unittest.TestCase):
|
|
def test_simple(self):
|
|
codecopts = self._get_codec_options(lambda x: Decimal128(x))
|
|
document = {'average': Decimal('56.47')}
|
|
- bsonbytes = BSON().encode(document, codec_options=codecopts)
|
|
+ bsonbytes = encode(document, codec_options=codecopts)
|
|
|
|
exp_document = {'average': Decimal128('56.47')}
|
|
- exp_bsonbytes = BSON().encode(exp_document)
|
|
+ exp_bsonbytes = encode(exp_document)
|
|
self.assertEqual(bsonbytes, exp_bsonbytes)
|
|
|
|
def test_erroring_fallback_encoder(self):
|
|
codecopts = self._get_codec_options(lambda _: 1/0)
|
|
|
|
# fallback converter should not be invoked when encoding known types.
|
|
- BSON().encode(
|
|
+ encode(
|
|
{'a': 1, 'b': Decimal128('1.01'), 'c': {'arr': ['abc', 3.678]}},
|
|
codec_options=codecopts)
|
|
|
|
# expect an error when encoding a custom type.
|
|
document = {'average': Decimal('56.47')}
|
|
with self.assertRaises(ZeroDivisionError):
|
|
- BSON().encode(document, codec_options=codecopts)
|
|
+ encode(document, codec_options=codecopts)
|
|
|
|
def test_noop_fallback_encoder(self):
|
|
codecopts = self._get_codec_options(lambda x: x)
|
|
document = {'average': Decimal('56.47')}
|
|
with self.assertRaises(InvalidDocument):
|
|
- BSON().encode(document, codec_options=codecopts)
|
|
+ encode(document, codec_options=codecopts)
|
|
|
|
def test_type_unencodable_by_fallback_encoder(self):
|
|
def fallback_encoder(value):
|
|
@@ -249,7 +250,7 @@ class TestBSONFallbackEncoder(unittest.TestCase):
|
|
codecopts = self._get_codec_options(fallback_encoder)
|
|
document = {'average': Decimal}
|
|
with self.assertRaises(TypeError):
|
|
- BSON().encode(document, codec_options=codecopts)
|
|
+ encode(document, codec_options=codecopts)
|
|
|
|
|
|
class TestBSONTypeEnDeCodecs(unittest.TestCase):
|
|
@@ -347,18 +348,18 @@ class TestBSONCustomTypeEncoderAndFallbackEncoderTandem(unittest.TestCase):
|
|
codecopts = CodecOptions(type_registry=TypeRegistry(
|
|
[self.B2BSON()], fallback_encoder=self.fallback_encoder_A2B))
|
|
testdoc = {'x': self.TypeA(123)}
|
|
- expected_bytes = BSON.encode({'x': 123})
|
|
+ expected_bytes = encode({'x': 123})
|
|
|
|
- self.assertEqual(BSON.encode(testdoc, codec_options=codecopts),
|
|
+ self.assertEqual(encode(testdoc, codec_options=codecopts),
|
|
expected_bytes)
|
|
|
|
def test_encode_custom_then_fallback(self):
|
|
codecopts = CodecOptions(type_registry=TypeRegistry(
|
|
[self.B2A()], fallback_encoder=self.fallback_encoder_A2BSON))
|
|
testdoc = {'x': self.TypeB(123)}
|
|
- expected_bytes = BSON.encode({'x': 123})
|
|
+ expected_bytes = encode({'x': 123})
|
|
|
|
- self.assertEqual(BSON.encode(testdoc, codec_options=codecopts),
|
|
+ self.assertEqual(encode(testdoc, codec_options=codecopts),
|
|
expected_bytes)
|
|
|
|
def test_chaining_encoders_fails(self):
|
|
@@ -366,7 +367,7 @@ class TestBSONCustomTypeEncoderAndFallbackEncoderTandem(unittest.TestCase):
|
|
[self.A2B(), self.B2BSON()]))
|
|
|
|
with self.assertRaises(InvalidDocument):
|
|
- BSON.encode({'x': self.TypeA(123)}, codec_options=codecopts)
|
|
+ encode({'x': self.TypeA(123)}, codec_options=codecopts)
|
|
|
|
def test_infinite_loop_exceeds_max_recursion_depth(self):
|
|
codecopts = CodecOptions(type_registry=TypeRegistry(
|
|
@@ -374,7 +375,7 @@ class TestBSONCustomTypeEncoderAndFallbackEncoderTandem(unittest.TestCase):
|
|
|
|
# Raises max recursion depth exceeded error
|
|
with self.assertRaises(RuntimeError):
|
|
- BSON.encode({'x': self.TypeA(100)}, codec_options=codecopts)
|
|
+ encode({'x': self.TypeA(100)}, codec_options=codecopts)
|
|
|
|
|
|
class TestTypeRegistry(unittest.TestCase):
|
|
diff --git a/test/test_encryption.py b/test/test_encryption.py
|
|
index bd767b83..1fc7cd20 100644
|
|
--- a/test/test_encryption.py
|
|
+++ b/test/test_encryption.py
|
|
@@ -23,7 +23,7 @@ import uuid
|
|
|
|
sys.path[0:0] = [""]
|
|
|
|
-from bson import BSON, json_util
|
|
+from bson import encode, json_util
|
|
from bson.binary import (Binary,
|
|
JAVA_LEGACY,
|
|
STANDARD,
|
|
@@ -166,7 +166,7 @@ def json_data(*paths):
|
|
|
|
|
|
def bson_data(*paths):
|
|
- return BSON.encode(json_data(*paths), codec_options=OPTS)
|
|
+ return encode(json_data(*paths), codec_options=OPTS)
|
|
|
|
|
|
class TestClientSimple(EncryptionIntegrationTest):
|
|
diff --git a/test/test_raw_bson.py b/test/test_raw_bson.py
|
|
index 82a4a331..d0a394e1 100644
|
|
--- a/test/test_raw_bson.py
|
|
+++ b/test/test_raw_bson.py
|
|
@@ -15,7 +15,7 @@
|
|
import datetime
|
|
import uuid
|
|
|
|
-from bson import BSON
|
|
+from bson import decode, encode
|
|
from bson.binary import Binary, JAVA_LEGACY
|
|
from bson.codec_options import CodecOptions
|
|
from bson.errors import InvalidBSON
|
|
@@ -56,17 +56,17 @@ class TestRawBSONDocument(IntegrationTest):
|
|
self.assertEqual(self.bson_string, self.document.raw)
|
|
|
|
def test_empty_doc(self):
|
|
- doc = RawBSONDocument(BSON.encode({}))
|
|
+ doc = RawBSONDocument(encode({}))
|
|
with self.assertRaises(KeyError):
|
|
doc['does-not-exist']
|
|
|
|
def test_invalid_bson_sequence(self):
|
|
- bson_byte_sequence = BSON.encode({'a': 1})+BSON.encode({})
|
|
+ bson_byte_sequence = encode({'a': 1})+encode({})
|
|
with self.assertRaisesRegex(InvalidBSON, 'invalid object length'):
|
|
RawBSONDocument(bson_byte_sequence)
|
|
|
|
def test_invalid_bson_eoo(self):
|
|
- invalid_bson_eoo = BSON.encode({'a': 1})[:-1] + b'\x01'
|
|
+ invalid_bson_eoo = encode({'a': 1})[:-1] + b'\x01'
|
|
with self.assertRaisesRegex(InvalidBSON, 'bad eoo'):
|
|
RawBSONDocument(invalid_bson_eoo)
|
|
|
|
@@ -87,7 +87,7 @@ class TestRawBSONDocument(IntegrationTest):
|
|
doc = {'_id': 1,
|
|
'bin4': Binary(uid.bytes, 4),
|
|
'bin3': Binary(uid.bytes, 3)}
|
|
- raw = RawBSONDocument(BSON.encode(doc))
|
|
+ raw = RawBSONDocument(encode(doc))
|
|
coll.insert_one(raw)
|
|
self.assertEqual(coll.find_one(), {'_id': 1, 'bin4': uid, 'bin3': uid})
|
|
|
|
@@ -127,7 +127,7 @@ class TestRawBSONDocument(IntegrationTest):
|
|
document_class=RawBSONDocument)
|
|
coll = db.get_collection('test_raw', codec_options=raw_java_legacy)
|
|
self.assertEqual(
|
|
- RawBSONDocument(BSON.encode(doc, codec_options=raw_java_legacy)),
|
|
+ RawBSONDocument(encode(doc, codec_options=raw_java_legacy)),
|
|
coll.find_one())
|
|
|
|
@client_context.require_connection
|
|
@@ -136,7 +136,7 @@ class TestRawBSONDocument(IntegrationTest):
|
|
db = self.client.pymongo_test
|
|
db.test_raw.insert_one(doc)
|
|
result = db.test_raw.find_one()
|
|
- self.assertEqual(BSON(self.document.raw).decode(), result['embedded'])
|
|
+ self.assertEqual(decode(self.document.raw), result['embedded'])
|
|
|
|
# Make sure that CodecOptions are preserved.
|
|
# {'embedded': [
|
|
@@ -178,7 +178,7 @@ class TestRawBSONDocument(IntegrationTest):
|
|
|
|
def test_preserve_key_ordering(self):
|
|
keyvaluepairs = [('a', 1), ('b', 2), ('c', 3),]
|
|
- rawdoc = RawBSONDocument(BSON.encode(SON(keyvaluepairs)))
|
|
+ rawdoc = RawBSONDocument(encode(SON(keyvaluepairs)))
|
|
|
|
for rkey, elt in zip(rawdoc, keyvaluepairs):
|
|
self.assertEqual(rkey, elt[0])
|
|
diff --git a/test/unicode/test_utf8.py b/test/unicode/test_utf8.py
|
|
index d66515d0..d5cbdb7b 100644
|
|
--- a/test/unicode/test_utf8.py
|
|
+++ b/test/unicode/test_utf8.py
|
|
@@ -2,7 +2,7 @@ import sys
|
|
|
|
sys.path[0:0] = [""]
|
|
|
|
-from bson import BSON
|
|
+from bson import encode
|
|
from bson.errors import InvalidStringData
|
|
from bson.py3compat import PY3
|
|
from test import unittest
|
|
@@ -19,7 +19,7 @@ class TestUTF8(unittest.TestCase):
|
|
py_is_legal = False
|
|
|
|
try:
|
|
- BSON.encode({'x': data})
|
|
+ encode({'x': data})
|
|
bson_is_legal = True
|
|
except InvalidStringData:
|
|
bson_is_legal = False
|
|
--
|
|
2.42.0.windows.2
|
|
|