PYTHON-881 - Backport CodecOptions class from 3.x.
This commit is contained in:
parent
f2c01af265
commit
d70578f650
@ -67,29 +67,53 @@ change to this in a future release.
|
||||
.. versionadded:: 1.5
|
||||
"""
|
||||
|
||||
JAVA_LEGACY = 5
|
||||
"""Used with :attr:`pymongo.collection.Collection.uuid_subtype`
|
||||
to specify that UUIDs should be stored in the legacy byte order
|
||||
used by the Java driver.
|
||||
STANDARD = UUID_SUBTYPE
|
||||
"""The standard UUID representation.
|
||||
|
||||
:class:`uuid.UUID` instances will automatically be encoded
|
||||
by :mod:`bson` using :data:`OLD_UUID_SUBTYPE`.
|
||||
:class:`uuid.UUID` instances will automatically be encoded to
|
||||
and decoded from BSON binary, using RFC-4122 byte order with
|
||||
binary subtype :data:`UUID_SUBTYPE`.
|
||||
|
||||
.. versionadded:: 2.9
|
||||
"""
|
||||
|
||||
PYTHON_LEGACY = OLD_UUID_SUBTYPE
|
||||
"""The Python legacy UUID representation.
|
||||
|
||||
:class:`uuid.UUID` instances will automatically be encoded to
|
||||
and decoded from BSON binary, using RFC-4122 byte order with
|
||||
binary subtype :data:`OLD_UUID_SUBTYPE`.
|
||||
|
||||
.. versionadded:: 2.9
|
||||
"""
|
||||
|
||||
JAVA_LEGACY = 5
|
||||
"""The Java legacy UUID representation.
|
||||
|
||||
:class:`uuid.UUID` instances will automatically be encoded to
|
||||
and decoded from BSON binary, using the Java driver's legacy
|
||||
byte order with binary subtype :data:`OLD_UUID_SUBTYPE`.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
"""
|
||||
|
||||
CSHARP_LEGACY = 6
|
||||
"""Used with :attr:`pymongo.collection.Collection.uuid_subtype`
|
||||
to specify that UUIDs should be stored in the legacy byte order
|
||||
used by the C# driver.
|
||||
"""The C#/.net legacy UUID representation.
|
||||
|
||||
:class:`uuid.UUID` instances will automatically be encoded
|
||||
by :mod:`bson` using :data:`OLD_UUID_SUBTYPE`.
|
||||
:class:`uuid.UUID` instances will automatically be encoded to
|
||||
and decoded from BSON binary, using the C# driver's legacy
|
||||
byte order and binary subtype :data:`OLD_UUID_SUBTYPE`.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
"""
|
||||
|
||||
ALL_UUID_SUBTYPES = (OLD_UUID_SUBTYPE, UUID_SUBTYPE, JAVA_LEGACY, CSHARP_LEGACY)
|
||||
ALL_UUID_REPRESENTATIONS = (STANDARD, PYTHON_LEGACY, JAVA_LEGACY, CSHARP_LEGACY)
|
||||
UUID_REPRESENTATION_NAMES = {
|
||||
PYTHON_LEGACY: 'PYTHON_LEGACY',
|
||||
STANDARD: 'STANDARD',
|
||||
JAVA_LEGACY: 'JAVA_LEGACY',
|
||||
CSHARP_LEGACY: 'CSHARP_LEGACY'}
|
||||
|
||||
MD5_SUBTYPE = 5
|
||||
"""BSON binary subtype for an MD5 hash.
|
||||
|
||||
77
bson/codec_options.py
Normal file
77
bson/codec_options.py
Normal file
@ -0,0 +1,77 @@
|
||||
# Copyright 2014-2015 MongoDB, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Tools for specifying BSON codec options."""
|
||||
|
||||
from bson.binary import (ALL_UUID_REPRESENTATIONS,
|
||||
PYTHON_LEGACY,
|
||||
UUID_REPRESENTATION_NAMES)
|
||||
|
||||
|
||||
class CodecOptions(tuple):
|
||||
"""Encapsulates BSON options used in CRUD operations.
|
||||
|
||||
:Parameters:
|
||||
- `document_class`: BSON documents returned in queries will be decoded
|
||||
to an instance of this class.
|
||||
- `tz_aware`: If ``True``, BSON datetimes will be decoded to timezone
|
||||
aware instances of :class:`~datetime.datetime`. Otherwise they will be
|
||||
naive. Defaults to ``False``.
|
||||
- `uuid_representation`: The BSON representation to use when encoding
|
||||
and decoding instances of :class:`~uuid.UUID`. Defaults to
|
||||
:data:`~bson.binary.PYTHON_LEGACY`.
|
||||
"""
|
||||
|
||||
__slots__ = ()
|
||||
|
||||
def __new__(cls, document_class=dict,
|
||||
tz_aware=False, uuid_representation=PYTHON_LEGACY):
|
||||
if not isinstance(tz_aware, bool):
|
||||
raise TypeError("tz_aware must be True or False")
|
||||
if uuid_representation not in ALL_UUID_REPRESENTATIONS:
|
||||
raise ValueError("uuid_representation must be a value "
|
||||
"from bson.binary.ALL_UUID_REPRESENTATIONS")
|
||||
|
||||
return tuple.__new__(
|
||||
cls, (document_class, tz_aware, uuid_representation))
|
||||
|
||||
def __repr__(self):
|
||||
if self.document_class is dict:
|
||||
document_class_repr = 'dict'
|
||||
else:
|
||||
document_class_repr = repr(self.document_class)
|
||||
|
||||
uuid_rep_repr = UUID_REPRESENTATION_NAMES.get(self.uuid_representation,
|
||||
self.uuid_representation)
|
||||
|
||||
return (
|
||||
'CodecOptions(document_class=%s, tz_aware=%r, uuid_representation='
|
||||
'%s)' % (document_class_repr, self.tz_aware, uuid_rep_repr))
|
||||
|
||||
def __getnewargs__(self):
|
||||
return tuple(self)
|
||||
|
||||
@property
|
||||
def document_class(self):
|
||||
return self[0]
|
||||
|
||||
@property
|
||||
def tz_aware(self):
|
||||
return self[1]
|
||||
|
||||
@property
|
||||
def uuid_representation(self):
|
||||
return self[2]
|
||||
|
||||
DEFAULT_CODEC_OPTIONS = CodecOptions()
|
||||
@ -9,6 +9,8 @@
|
||||
.. autodata:: OLD_BINARY_SUBTYPE
|
||||
.. autodata:: OLD_UUID_SUBTYPE
|
||||
.. autodata:: UUID_SUBTYPE
|
||||
.. autodata:: STANDARD
|
||||
.. autodata:: PYTHON_LEGACY
|
||||
.. autodata:: JAVA_LEGACY
|
||||
.. autodata:: CSHARP_LEGACY
|
||||
.. autodata:: MD5_SUBTYPE
|
||||
|
||||
6
doc/api/bson/codec_options.rst
Normal file
6
doc/api/bson/codec_options.rst
Normal file
@ -0,0 +1,6 @@
|
||||
:mod:`codec_options` -- Tools for specifying BSON codec options
|
||||
===============================================================
|
||||
|
||||
.. automodule:: bson.codec_options
|
||||
:synopsis: Tools for specifying BSON codec options.
|
||||
:members:
|
||||
@ -11,14 +11,15 @@ Sub-modules:
|
||||
:maxdepth: 2
|
||||
|
||||
binary
|
||||
regex
|
||||
code
|
||||
codec_options
|
||||
dbref
|
||||
errors
|
||||
json_util
|
||||
max_key
|
||||
min_key
|
||||
objectid
|
||||
regex
|
||||
son
|
||||
timestamp
|
||||
tz_util
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
.. autoattribute:: full_name
|
||||
.. autoattribute:: name
|
||||
.. autoattribute:: database
|
||||
.. autoattribute:: codec_options
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: tag_sets
|
||||
.. autoattribute:: secondary_acceptable_latency_ms
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
.. autoattribute:: max_message_size
|
||||
.. autoattribute:: min_wire_version
|
||||
.. autoattribute:: max_wire_version
|
||||
.. autoattribute:: codec_options
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: tag_sets
|
||||
.. autoattribute:: secondary_acceptable_latency_ms
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
.. note:: Use dictionary style access if `collection_name` is an
|
||||
attribute of the :class:`Database` class eg: db[`collection_name`].
|
||||
|
||||
.. autoattribute:: codec_options
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: tag_sets
|
||||
.. autoattribute:: secondary_acceptable_latency_ms
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
.. autoattribute:: max_message_size
|
||||
.. autoattribute:: min_wire_version
|
||||
.. autoattribute:: max_wire_version
|
||||
.. autoattribute:: codec_options
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: tag_sets
|
||||
.. autoattribute:: secondary_acceptable_latency_ms
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
.. autoattribute:: min_wire_version
|
||||
.. autoattribute:: max_wire_version
|
||||
.. autoattribute:: auto_start_request
|
||||
.. autoattribute:: codec_options
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: tag_sets
|
||||
.. autoattribute:: secondary_acceptable_latency_ms
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
.. autoattribute:: min_wire_version
|
||||
.. autoattribute:: max_wire_version
|
||||
.. autoattribute:: auto_start_request
|
||||
.. autoattribute:: codec_options
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: tag_sets
|
||||
.. autoattribute:: secondary_acceptable_latency_ms
|
||||
|
||||
@ -93,7 +93,7 @@ class Collection(common.BaseObject):
|
||||
secondary_acceptable_latency_ms=(
|
||||
database.secondary_acceptable_latency_ms),
|
||||
safe=database.safe,
|
||||
uuidrepresentation=database.uuid_subtype,
|
||||
codec_options=database.codec_options,
|
||||
**database.write_concern)
|
||||
|
||||
if not isinstance(name, basestring):
|
||||
|
||||
@ -16,13 +16,14 @@
|
||||
"""Functions and classes common to multiple pymongo modules."""
|
||||
import sys
|
||||
import warnings
|
||||
from pymongo import read_preferences
|
||||
|
||||
from bson.binary import (OLD_UUID_SUBTYPE, UUID_SUBTYPE,
|
||||
JAVA_LEGACY, CSHARP_LEGACY)
|
||||
from bson.codec_options import CodecOptions
|
||||
from pymongo import read_preferences
|
||||
from pymongo.auth import MECHANISMS
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.errors import ConfigurationError
|
||||
from bson.binary import (OLD_UUID_SUBTYPE, UUID_SUBTYPE,
|
||||
JAVA_LEGACY, CSHARP_LEGACY)
|
||||
|
||||
HAS_SSL = True
|
||||
try:
|
||||
@ -395,12 +396,12 @@ class BaseObject(object):
|
||||
|
||||
def __init__(self, **options):
|
||||
|
||||
self._codec_options = None
|
||||
self.__slave_okay = False
|
||||
self.__read_pref = ReadPreference.PRIMARY
|
||||
self.__tag_sets = [{}]
|
||||
self.__secondary_acceptable_latency_ms = 15
|
||||
self.__safe = None
|
||||
self.__uuid_subtype = OLD_UUID_SUBTYPE
|
||||
self.__write_concern = WriteConcern()
|
||||
self.__set_options(options)
|
||||
if (self.__read_pref == ReadPreference.PRIMARY
|
||||
@ -444,8 +445,8 @@ class BaseObject(object):
|
||||
self.__read_pref = validate_read_preference(option, value)
|
||||
elif option in ('tag_sets', 'readpreferencetags'):
|
||||
self.__tag_sets = validate_tag_sets(option, value)
|
||||
elif option == 'uuidrepresentation':
|
||||
self.__uuid_subtype = validate_uuid_subtype(option, value)
|
||||
elif option == 'codec_options':
|
||||
self._codec_options = value
|
||||
elif option in ('secondaryacceptablelatencyms',
|
||||
'secondary_acceptable_latency_ms'):
|
||||
self.__secondary_acceptable_latency_ms = (
|
||||
@ -458,6 +459,15 @@ class BaseObject(object):
|
||||
else:
|
||||
self.__set_safe_option(option, value)
|
||||
|
||||
@property
|
||||
def codec_options(self):
|
||||
"""Read only access to the :class:`~bson.codec_options.CodecOptions`
|
||||
of this instance.
|
||||
|
||||
.. versionadded:: 2.9
|
||||
"""
|
||||
return self._codec_options
|
||||
|
||||
def __set_write_concern(self, value):
|
||||
"""Property setter for write_concern."""
|
||||
if not isinstance(value, dict):
|
||||
@ -622,11 +632,14 @@ class BaseObject(object):
|
||||
subtype 4. It can also be used to force legacy byte order and subtype
|
||||
compatibility with the Java and C# drivers. See the :mod:`bson.binary`
|
||||
module for all options."""
|
||||
return self.__uuid_subtype
|
||||
return self._codec_options.uuid_representation
|
||||
|
||||
def __set_uuid_subtype(self, value):
|
||||
"""Sets the BSON Binary subtype to be used when storing UUIDs."""
|
||||
self.__uuid_subtype = validate_uuid_subtype("uuid_subtype", value)
|
||||
as_class = self._codec_options.document_class
|
||||
tz_aware = self._codec_options.tz_aware
|
||||
uuid_rep = validate_uuid_subtype("uuid_subtype", value)
|
||||
self._codec_options = CodecOptions(as_class, tz_aware, uuid_rep)
|
||||
|
||||
uuid_subtype = property(__get_uuid_subtype, __set_uuid_subtype)
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ class Database(common.BaseObject):
|
||||
secondary_acceptable_latency_ms=(
|
||||
connection.secondary_acceptable_latency_ms),
|
||||
safe=connection.safe,
|
||||
uuidrepresentation=connection.uuid_subtype,
|
||||
codec_options=connection.codec_options,
|
||||
**connection.write_concern)
|
||||
|
||||
if not isinstance(name, basestring):
|
||||
|
||||
@ -33,9 +33,10 @@ directly to the master and each slave with instances of
|
||||
|
||||
import warnings
|
||||
|
||||
from bson.codec_options import CodecOptions
|
||||
from pymongo import helpers, thread_util
|
||||
from pymongo import ReadPreference
|
||||
from pymongo.common import BaseObject
|
||||
from pymongo.common import BaseObject, validate_boolean
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from pymongo.database import Database
|
||||
from pymongo.errors import AutoReconnect
|
||||
@ -85,15 +86,16 @@ class MasterSlaveConnection(BaseObject):
|
||||
" removed in PyMongo 3.0.",
|
||||
DeprecationWarning, stacklevel=2)
|
||||
|
||||
validate_boolean('tz_aware', tz_aware)
|
||||
codec_options = CodecOptions(document_class, tz_aware)
|
||||
super(MasterSlaveConnection,
|
||||
self).__init__(read_preference=ReadPreference.SECONDARY,
|
||||
safe=master.safe,
|
||||
codec_options=codec_options,
|
||||
**master.write_concern)
|
||||
|
||||
self.__master = master
|
||||
self.__slaves = slaves
|
||||
self.__document_class = document_class
|
||||
self.__tz_aware = tz_aware
|
||||
self.__request_counter = thread_util.Counter(master.use_greenlets)
|
||||
|
||||
@property
|
||||
@ -122,10 +124,12 @@ class MasterSlaveConnection(BaseObject):
|
||||
return self.master.use_greenlets
|
||||
|
||||
def get_document_class(self):
|
||||
return self.__document_class
|
||||
return self._codec_options.document_class
|
||||
|
||||
def set_document_class(self, klass):
|
||||
self.__document_class = klass
|
||||
tz_aware = self._codec_options.tz_aware
|
||||
uuid_rep = self._codec_options.uuid_representation
|
||||
self._codec_options = CodecOptions(klass, tz_aware, uuid_rep)
|
||||
|
||||
document_class = property(get_document_class, set_document_class,
|
||||
doc="""Default class to use for documents
|
||||
@ -133,7 +137,7 @@ class MasterSlaveConnection(BaseObject):
|
||||
|
||||
@property
|
||||
def tz_aware(self):
|
||||
return self.__tz_aware
|
||||
return self._codec_options.tz_aware
|
||||
|
||||
@property
|
||||
def max_bson_size(self):
|
||||
|
||||
@ -42,6 +42,8 @@ import threading
|
||||
import time
|
||||
import warnings
|
||||
|
||||
from bson.binary import PYTHON_LEGACY
|
||||
from bson.codec_options import CodecOptions
|
||||
from bson.py3compat import b
|
||||
from pymongo import (auth,
|
||||
common,
|
||||
@ -292,6 +294,11 @@ class MongoClient(common.BaseObject):
|
||||
options[option] = value
|
||||
options.update(opts)
|
||||
|
||||
common.validate_boolean('tz_aware', tz_aware)
|
||||
uuid_representation = options.pop('uuidrepresentation', PYTHON_LEGACY)
|
||||
options['codec_options'] = CodecOptions(
|
||||
document_class, tz_aware, uuid_representation)
|
||||
|
||||
self.__max_pool_size = common.validate_positive_integer_or_none(
|
||||
'max_pool_size', max_pool_size)
|
||||
|
||||
@ -356,8 +363,6 @@ class MongoClient(common.BaseObject):
|
||||
self.__event_class = event_class
|
||||
|
||||
self.__future_member = None
|
||||
self.__document_class = document_class
|
||||
self.__tz_aware = common.validate_boolean('tz_aware', tz_aware)
|
||||
self.__auto_start_request = options.get('auto_start_request', False)
|
||||
|
||||
# cache of existing indexes used by ensure_index ops
|
||||
@ -606,10 +611,12 @@ class MongoClient(common.BaseObject):
|
||||
return self.__auto_start_request
|
||||
|
||||
def get_document_class(self):
|
||||
return self.__document_class
|
||||
return self._codec_options.document_class
|
||||
|
||||
def set_document_class(self, klass):
|
||||
self.__document_class = klass
|
||||
tz_aware = self._codec_options.tz_aware
|
||||
uuid_rep = self._codec_options.uuid_representation
|
||||
self._codec_options = CodecOptions(klass, tz_aware, uuid_rep)
|
||||
|
||||
document_class = property(get_document_class, set_document_class,
|
||||
doc="""Default class to use for documents
|
||||
@ -624,7 +631,7 @@ class MongoClient(common.BaseObject):
|
||||
|
||||
.. versionadded:: 1.8
|
||||
"""
|
||||
return self.__tz_aware
|
||||
return self._codec_options.tz_aware
|
||||
|
||||
@property
|
||||
def max_bson_size(self):
|
||||
|
||||
@ -40,6 +40,8 @@ import time
|
||||
import warnings
|
||||
import weakref
|
||||
|
||||
from bson.binary import PYTHON_LEGACY
|
||||
from bson.codec_options import CodecOptions
|
||||
from bson.py3compat import b
|
||||
from pymongo import (auth,
|
||||
common,
|
||||
@ -59,7 +61,6 @@ from pymongo.errors import (AutoReconnect,
|
||||
DuplicateKeyError,
|
||||
OperationFailure,
|
||||
InvalidOperation)
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.thread_util import DummyLock
|
||||
|
||||
EMPTY = b("")
|
||||
@ -593,8 +594,6 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
|
||||
self.__max_pool_size = common.validate_positive_integer_or_none(
|
||||
'max_pool_size', max_pool_size)
|
||||
self.__tz_aware = common.validate_boolean('tz_aware', tz_aware)
|
||||
self.__document_class = document_class
|
||||
self.__monitor = None
|
||||
self.__closed = False
|
||||
|
||||
@ -631,6 +630,11 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
self.__opts[option] = value
|
||||
self.__opts.update(options)
|
||||
|
||||
common.validate_boolean('tz_aware', tz_aware)
|
||||
uuid_representation = options.pop('uuidrepresentation', PYTHON_LEGACY)
|
||||
self.__opts['codec_options'] = CodecOptions(
|
||||
document_class, tz_aware, uuid_representation)
|
||||
|
||||
self.__use_greenlets = self.__opts.get('use_greenlets', False)
|
||||
if self.__use_greenlets and not have_gevent:
|
||||
raise ConfigurationError(
|
||||
@ -927,11 +931,13 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
|
||||
def get_document_class(self):
|
||||
"""document_class getter"""
|
||||
return self.__document_class
|
||||
return self._codec_options.document_class
|
||||
|
||||
def set_document_class(self, klass):
|
||||
"""document_class setter"""
|
||||
self.__document_class = klass
|
||||
tz_aware = self._codec_options.tz_aware
|
||||
uuid_rep = self._codec_options.uuid_representation
|
||||
self._codec_options = CodecOptions(klass, tz_aware, uuid_rep)
|
||||
|
||||
document_class = property(get_document_class, set_document_class,
|
||||
doc="""Default class to use for documents
|
||||
@ -942,7 +948,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
def tz_aware(self):
|
||||
"""Does this client return timezone-aware datetimes?
|
||||
"""
|
||||
return self.__tz_aware
|
||||
return self._codec_options.tz_aware
|
||||
|
||||
@property
|
||||
def max_bson_size(self):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user