From 217f90bab6b0b9b8eeeed900e5561ab83015a4e9 Mon Sep 17 00:00:00 2001 From: "A. Jesse Jiryu Davis" Date: Fri, 16 Jun 2017 07:13:21 -0400 Subject: [PATCH] PYTHON-1284 Don't copy CodecOptions in RawBSONDocument --- bson/codec_options.py | 20 ++++++++++++++++++++ bson/raw_bson.py | 28 ++++++++++++++++++---------- doc/changelog.rst | 6 ++++++ test/test_raw_bson.py | 6 ++++-- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/bson/codec_options.py b/bson/codec_options.py index 7ef4151de..5ddae7b17 100644 --- a/bson/codec_options.py +++ b/bson/codec_options.py @@ -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() diff --git a/bson/raw_bson.py b/bson/raw_bson.py index ddf1fd2a6..54fff0ec9 100644 --- a/bson/raw_bson.py +++ b/bson/raw_bson.py @@ -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) diff --git a/doc/changelog.rst b/doc/changelog.rst index 6332cf2ea..67a08a056 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -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 ---------------------- diff --git a/test/test_raw_bson.py b/test/test_raw_bson.py index b81f04fb8..c73968c8e 100644 --- a/test/test_raw_bson.py +++ b/test/test_raw_bson.py @@ -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)