PYTHON-1648 Binary buffer protocol support
This commit is contained in:
parent
77913c7d36
commit
e92e2b0efb
@ -133,22 +133,25 @@ class Binary(bytes):
|
||||
directly to :class:`bytes`.
|
||||
|
||||
:Parameters:
|
||||
- `data`: the binary data to represent
|
||||
- `data`: the binary data to represent. Can be any bytes-like type
|
||||
that implements the buffer protocol.
|
||||
- `subtype` (optional): the `binary subtype
|
||||
<http://bsonspec.org/#/specification>`_
|
||||
to use
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
Support any bytes-like type that implements the buffer protocol.
|
||||
"""
|
||||
|
||||
_type_marker = 5
|
||||
|
||||
def __new__(cls, data, subtype=BINARY_SUBTYPE):
|
||||
if not isinstance(data, bytes):
|
||||
raise TypeError("data must be an instance of bytes")
|
||||
if not isinstance(subtype, int):
|
||||
raise TypeError("subtype must be an instance of int")
|
||||
if subtype >= 256 or subtype < 0:
|
||||
raise ValueError("subtype must be contained in [0, 256)")
|
||||
self = bytes.__new__(cls, data)
|
||||
# Support any type that implements the buffer protocol.
|
||||
self = bytes.__new__(cls, memoryview(data).tobytes())
|
||||
self.__subtype = subtype
|
||||
return self
|
||||
|
||||
|
||||
@ -60,6 +60,8 @@ Version 3.9 adds support for MongoDB 4.2. Highlights include:
|
||||
:meth:`~pymongo.collection.Collection.find_one_and_update`,
|
||||
:meth:`~pymongo.operations.UpdateOne`, and
|
||||
:meth:`~pymongo.operations.UpdateMany`.
|
||||
- :class:`~bson.binary.Binary` now supports any bytes-like type that implements
|
||||
the buffer protocol.
|
||||
|
||||
.. _URI options specification: https://github.com/mongodb/specifications/blob/master/source/uri-options/uri-options.rst
|
||||
|
||||
|
||||
@ -14,9 +14,11 @@
|
||||
|
||||
"""Tests for the Binary wrapper."""
|
||||
|
||||
import array
|
||||
import base64
|
||||
import copy
|
||||
import pickle
|
||||
import platform
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
@ -26,6 +28,7 @@ import bson
|
||||
|
||||
from bson.binary import *
|
||||
from bson.codec_options import CodecOptions
|
||||
from bson.py3compat import PY3
|
||||
from bson.son import SON
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from test import client_context, unittest
|
||||
@ -81,7 +84,6 @@ class TestBinary(unittest.TestCase):
|
||||
|
||||
def test_exceptions(self):
|
||||
self.assertRaises(TypeError, Binary, None)
|
||||
self.assertRaises(TypeError, Binary, u"hello")
|
||||
self.assertRaises(TypeError, Binary, 5)
|
||||
self.assertRaises(TypeError, Binary, 10.2)
|
||||
self.assertRaises(TypeError, Binary, b"hello", None)
|
||||
@ -90,6 +92,10 @@ class TestBinary(unittest.TestCase):
|
||||
self.assertRaises(ValueError, Binary, b"hello", 256)
|
||||
self.assertTrue(Binary(b"hello", 0))
|
||||
self.assertTrue(Binary(b"hello", 255))
|
||||
if platform.python_implementation() != "Jython":
|
||||
# Jython's memoryview accepts unicode strings...
|
||||
# https://bugs.jython.org/issue2784
|
||||
self.assertRaises(TypeError, Binary, u"hello")
|
||||
|
||||
def test_subtype(self):
|
||||
one = Binary(b"hello")
|
||||
@ -356,6 +362,22 @@ class TestBinary(unittest.TestCase):
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
self.assertEqual(uul, pickle.loads(pickle.dumps(uul, proto)))
|
||||
|
||||
def test_buffer_protocol(self):
|
||||
b0 = Binary(b'123', 2)
|
||||
|
||||
self.assertEqual(b0, Binary(memoryview(b'123'), 2))
|
||||
self.assertEqual(b0, Binary(bytearray(b'123'), 2))
|
||||
# mmap.mmap and array.array only expose the
|
||||
# buffer interface in python 3.x
|
||||
if PY3:
|
||||
# No mmap module in Jython
|
||||
import mmap
|
||||
with mmap.mmap(-1, len(b'123')) as mm:
|
||||
mm.write(b'123')
|
||||
mm.seek(0)
|
||||
self.assertEqual(b0, Binary(mm, 2))
|
||||
self.assertEqual(b0, Binary(array.array('B', b'123'), 2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user