PYTHON-1284 Don't copy CodecOptions in RawBSONDocument

This commit is contained in:
A. Jesse Jiryu Davis 2017-06-16 07:13:21 -04:00
parent edc3dad823
commit 217f90bab6
4 changed files with 48 additions and 12 deletions

View File

@ -111,6 +111,26 @@ class CodecOptions(_options_base):
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self._arguments_repr())
def with_options(self, **kwargs):
"""Make a copy of this CodecOptions, overriding some options::
>>> from bson.codec_options import DEFAULT_CODEC_OPTIONS
>>> DEFAULT_CODEC_OPTIONS.tz_aware
False
>>> options = DEFAULT_CODEC_OPTIONS.with_options(tz_aware=True)
>>> options.tz_aware
True
.. versionadded:: 3.5
"""
return CodecOptions(
kwargs.get('document_class', self.document_class),
kwargs.get('tz_aware', self.tz_aware),
kwargs.get('uuid_representation', self.uuid_representation),
kwargs.get('unicode_decode_error_handler',
self.unicode_decode_error_handler),
kwargs.get('tzinfo', self.tzinfo))
DEFAULT_CODEC_OPTIONS = CodecOptions()

View File

@ -20,7 +20,7 @@ import collections
from bson import _UNPACK_INT, _iterate_elements
from bson.py3compat import iteritems
from bson.codec_options import (
CodecOptions, DEFAULT_CODEC_OPTIONS, _RAW_BSON_DOCUMENT_MARKER)
CodecOptions, DEFAULT_CODEC_OPTIONS as DEFAULT, _RAW_BSON_DOCUMENT_MARKER)
from bson.errors import InvalidBSON
@ -35,24 +35,29 @@ class RawBSONDocument(collections.Mapping):
__slots__ = ('__raw', '__inflated_doc', '__codec_options')
_type_marker = _RAW_BSON_DOCUMENT_MARKER
def __init__(self, bson_bytes, codec_options=DEFAULT_CODEC_OPTIONS):
def __init__(self, bson_bytes, codec_options=None):
"""Create a new :class:`RawBSONDocument`.
:Parameters:
- `bson_bytes`: the BSON bytes that compose this document
- `codec_options` (optional): An instance of
:class:`~bson.codec_options.CodecOptions`.
.. versionchanged:: 3.5
If a :class:`~bson.codec_options.CodecOptions` is passed in, its
`document_class` must be :class:`RawBSONDocument`.
"""
self.__raw = bson_bytes
self.__inflated_doc = None
# Always decode documents to their lazy representations.
co = codec_options
self.__codec_options = CodecOptions(
tz_aware=co.tz_aware,
document_class=RawBSONDocument,
uuid_representation=co.uuid_representation,
unicode_decode_error_handler=co.unicode_decode_error_handler,
tzinfo=co.tzinfo)
# Can't default codec_options to DEFAULT_RAW_BSON_OPTIONS in signature,
# it refers to this class RawBSONDocument.
if codec_options is None:
codec_options = DEFAULT_RAW_BSON_OPTIONS
elif codec_options.document_class is not RawBSONDocument:
raise TypeError(
"RawBSONDocument cannot use CodecOptions with document "
"class %s" % (codec_options.document_class, ))
self.__codec_options = codec_options
@property
def raw(self):
@ -96,3 +101,6 @@ class RawBSONDocument(collections.Mapping):
def __repr__(self):
return ("RawBSONDocument(%r, codec_options=%r)"
% (self.raw, self.__codec_options))
DEFAULT_RAW_BSON_OPTIONS = DEFAULT.with_options(document_class=RawBSONDocument)

View File

@ -1,6 +1,12 @@
Changelog
=========
Changes in Next Version
-----------------------
If a custom :class:`~bson.codec_options.CodecOptions` is passed to
:class:`RawBSONDocument`, its `document_class` must be :class:`RawBSONDocument`.
Changes in Version 3.4
----------------------

View File

@ -58,7 +58,8 @@ class TestRawBSONDocument(unittest.TestCase):
)
document = RawBSONDocument(
bson_string,
codec_options=CodecOptions(uuid_representation=JAVA_LEGACY))
codec_options=CodecOptions(uuid_representation=JAVA_LEGACY,
document_class=RawBSONDocument))
self.assertEqual(uuid.UUID('026fab8f-975f-4965-9fbf-85ad874c60ff'),
document['_id'])
@ -103,7 +104,8 @@ class TestRawBSONDocument(unittest.TestCase):
)
rbd = RawBSONDocument(
bson_string,
codec_options=CodecOptions(uuid_representation=JAVA_LEGACY))
codec_options=CodecOptions(uuid_representation=JAVA_LEGACY,
document_class=RawBSONDocument))
db.test_raw.drop()
db.test_raw.insert_one(rbd)