PYTHON-949 Support CodecOptions in message.py.

This commit is contained in:
aherlihy 2015-06-15 15:39:32 -04:00 committed by Bernie Hackett
parent c10a098c2c
commit 219e8a084e
3 changed files with 101 additions and 12 deletions

View File

@ -181,16 +181,29 @@ static PyObject* _cbson_insert_message(PyObject* self, PyObject* args) {
buffer_t buffer;
int length_location, message_length;
PyObject* result;
PyObject* codec_options = Py_None;
PyObject* as_class;
unsigned char tz_aware;
if (!PyArg_ParseTuple(args, "et#ObbObb",
if (!PyArg_ParseTuple(args, "et#ObbObb|O",
"utf-8",
&collection_name,
&collection_name_length,
&docs, &check_keys, &safe,
&last_error_args,
&continue_on_error, &uuid_subtype)) {
&continue_on_error, &uuid_subtype,
&codec_options)) {
return NULL;
}
if (codec_options != Py_None) {
if (!PyArg_ParseTuple(codec_options, "Obb",
&as_class, &tz_aware, &uuid_subtype)) {
PyMem_Free(collection_name);
return NULL;
}
}
if (continue_on_error) {
options += 1;
}
@ -307,16 +320,28 @@ static PyObject* _cbson_update_message(PyObject* self, PyObject* args) {
buffer_t buffer;
int length_location, message_length;
PyObject* result;
PyObject* codec_options = Py_None;
PyObject* as_class;
unsigned char tz_aware;
if (!PyArg_ParseTuple(args, "et#bbOObObb",
if (!PyArg_ParseTuple(args, "et#bbOObObb|O",
"utf-8",
&collection_name,
&collection_name_length,
&upsert, &multi, &spec, &doc, &safe,
&last_error_args, &check_keys, &uuid_subtype)) {
&last_error_args, &check_keys, &uuid_subtype,
&codec_options)) {
return NULL;
}
if (codec_options != Py_None) {
if (!PyArg_ParseTuple(codec_options, "Obb",
&as_class, &tz_aware, &uuid_subtype)) {
PyMem_Free(collection_name);
return NULL;
}
}
options = 0;
if (upsert) {
options += 1;
@ -410,16 +435,29 @@ static PyObject* _cbson_query_message(PyObject* self, PyObject* args) {
buffer_t buffer;
int length_location, message_length;
PyObject* result;
PyObject* codec_options = Py_None;
PyObject* as_class;
unsigned char tz_aware;
if (!PyArg_ParseTuple(args, "Iet#iiO|Ob",
if (!PyArg_ParseTuple(args, "Iet#iiO|ObO",
&options,
"utf-8",
&collection_name,
&collection_name_length,
&num_to_skip, &num_to_return,
&query, &field_selector, &uuid_subtype)) {
&query, &field_selector, &uuid_subtype,
&codec_options)) {
return NULL;
}
if (codec_options != Py_None) {
if (!PyArg_ParseTuple(codec_options, "Obb",
&as_class, &tz_aware, &uuid_subtype)) {
PyMem_Free(collection_name);
return NULL;
}
}
buffer = buffer_new();
if (!buffer) {
PyErr_NoMemory();

View File

@ -81,7 +81,8 @@ def __pack_message(operation, data):
def insert(collection_name, docs, check_keys,
safe, last_error_args, continue_on_error, uuid_subtype):
safe, last_error_args, continue_on_error, uuid_subtype,
codec_options=None):
"""Get an **insert** message.
.. note:: As of PyMongo 2.6, this function is no longer used. It
@ -90,6 +91,8 @@ def insert(collection_name, docs, check_keys,
be removed in a future release.
"""
if codec_options is not None:
uuid_subtype = codec_options.uuid_representation
options = 0
if continue_on_error:
options += 1
@ -113,9 +116,12 @@ if _use_c:
def update(collection_name, upsert, multi,
spec, doc, safe, last_error_args, check_keys, uuid_subtype):
spec, doc, safe, last_error_args, check_keys, uuid_subtype,
codec_options=None):
"""Get an **update** message.
"""
if codec_options is not None:
uuid_subtype = codec_options.uuid_representation
options = 0
if upsert:
options += 1
@ -142,9 +148,11 @@ if _use_c:
def query(options, collection_name, num_to_skip,
num_to_return, query, field_selector=None,
uuid_subtype=OLD_UUID_SUBTYPE):
uuid_subtype=OLD_UUID_SUBTYPE, codec_options=None):
"""Get a **query** message.
"""
if codec_options is not None:
uuid_subtype = codec_options.uuid_representation
data = struct.pack("<I", options)
data += bson._make_c_string(collection_name)
data += struct.pack("<i", num_to_skip)
@ -175,9 +183,11 @@ if _use_c:
def delete(collection_name, spec, safe,
last_error_args, uuid_subtype, options=0):
last_error_args, uuid_subtype, options=0, codec_options=None):
"""Get a **delete** message.
"""
if codec_options is not None:
uuid_subtype = codec_options.uuid_representation
data = _ZERO_32
data += bson._make_c_string(collection_name)
data += struct.pack("<I", options)

View File

@ -28,7 +28,8 @@ from nose.plugins.skip import SkipTest
sys.path[0:0] = [""]
from bson.binary import Binary, JAVA_LEGACY
from bson import BSON
from bson.binary import Binary, JAVA_LEGACY, STANDARD, CSHARP_LEGACY
from bson.regex import Regex
from bson.code import Code
from bson.codec_options import CodecOptions
@ -63,7 +64,6 @@ try:
except ImportError:
have_uuid = False
setUpModule = skip_restricted_localhost
@ -2003,6 +2003,47 @@ class TestCollection(unittest.TestCase):
coll.uuid_subtype = 6
self.assertEqual(doc, coll.find_one({'_id': 2}))
def test_message_backport_codec_options(self):
if not have_uuid:
raise SkipTest("No uuid module")
name = "%s.%s" % (self.db.name, "test")
self.db.drop_collection("test")
key = {'_id': 1, 'key': uuid.UUID("12345678123456781234567812345678")}
key2 = {'key2': uuid.UUID("22345678123456781234567812345678")}
enc = BSON.encode(key, uuid_subtype=STANDARD)
msg = message_module.insert(
name, [key], True, False, {}, False, CSHARP_LEGACY,
CodecOptions(uuid_representation=STANDARD))
self.assertTrue(enc in msg[1])
self.db.connection._send_message(msg, False)
self.assertEqual(self.db.test.find_one(), key)
msg = message_module.update(
name, True, False, key, {"$set": key2}, False, False, False,
CSHARP_LEGACY, CodecOptions(uuid_representation=STANDARD))
self.assertTrue(enc in msg[1])
self.db.connection._send_message(msg, False)
key.update(key2)
self.assertEqual(self.db.test.find_one(), key)
enc = BSON.encode(key, uuid_subtype=STANDARD)
msg = message_module.query(
0, name, 0, 0, key, None, CSHARP_LEGACY,
CodecOptions(uuid_representation=STANDARD))
self.assertTrue(enc in msg[1])
r = self.db.connection._send_message_with_response(msg, False)
self.assertTrue(key['key'].bytes in r[1][0])
msg = message_module.delete(
name, key, False, False, CSHARP_LEGACY, 0,
CodecOptions(uuid_representation=STANDARD))
self.assertTrue(enc in msg[1])
self.assertEqual(1, self.db.test.count())
self.db.connection._send_message(msg, False)
self.assertEqual(0, self.db.test.count())
def test_map_reduce(self):
if not version.at_least(self.db.connection, (1, 1, 1)):
raise SkipTest("mapReduce command requires MongoDB >= 1.1.1")