Skip to content

Commit 103bd3f

Browse files
author
Mike Dirolf
committed
just move _id for all top level docs, don't differentiate by operation
1 parent 2716395 commit 103bd3f

File tree

4 files changed

+26
-43
lines changed

4 files changed

+26
-43
lines changed

pymongo/_cbsonmodule.c

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ typedef struct {
9797
} bson_buffer;
9898

9999
static int write_dict(bson_buffer* buffer, PyObject* dict,
100-
unsigned char check_keys, unsigned char move_id);
100+
unsigned char check_keys, unsigned char top_level);
101101
static PyObject* elements_to_dict(const char* string, int max);
102102

103103
static bson_buffer* buffer_new(void) {
@@ -664,7 +664,7 @@ static int write_pair(bson_buffer* buffer, const char* name, Py_ssize_t name_len
664664

665665
static int decode_and_write_pair(bson_buffer* buffer,
666666
PyObject* key, PyObject* value,
667-
unsigned char check_keys, unsigned char move_id) {
667+
unsigned char check_keys, unsigned char top_level) {
668668
PyObject* encoded;
669669
if (PyUnicode_Check(key)) {
670670
result_t status;
@@ -706,9 +706,9 @@ static int decode_and_write_pair(bson_buffer* buffer,
706706
return 0;
707707
}
708708

709-
/* If move_id is True, don't allow writing _id here - it was already written. */
709+
/* If top_level is True, don't allow writing _id here - it was already written. */
710710
if (!write_pair(buffer, PyString_AsString(encoded),
711-
PyString_Size(encoded), value, check_keys, !move_id)) {
711+
PyString_Size(encoded), value, check_keys, !top_level)) {
712712
Py_DECREF(encoded);
713713
return 0;
714714
}
@@ -719,7 +719,7 @@ static int decode_and_write_pair(bson_buffer* buffer,
719719

720720
static int write_son(bson_buffer* buffer, PyObject* dict, int start_position,
721721
int length_location, unsigned char check_keys,
722-
unsigned char move_id) {
722+
unsigned char top_level) {
723723
PyObject* keys = PyObject_CallMethod(dict, "keys", NULL);
724724
int items,
725725
i;
@@ -738,7 +738,7 @@ static int write_son(bson_buffer* buffer, PyObject* dict, int start_position,
738738
}
739739
value = PyDict_GetItem(dict, key);
740740
if (!value ||
741-
!decode_and_write_pair(buffer, key, value, check_keys, move_id)) {
741+
!decode_and_write_pair(buffer, key, value, check_keys, top_level)) {
742742
Py_DECREF(keys);
743743
return 0;
744744
}
@@ -748,7 +748,7 @@ static int write_son(bson_buffer* buffer, PyObject* dict, int start_position,
748748
}
749749

750750
/* returns 0 on failure */
751-
static int write_dict(bson_buffer* buffer, PyObject* dict, unsigned char check_keys, unsigned char move_id) {
751+
static int write_dict(bson_buffer* buffer, PyObject* dict, unsigned char check_keys, unsigned char top_level) {
752752
int start_position = buffer->position;
753753
char zero = 0;
754754
int length;
@@ -761,8 +761,8 @@ static int write_dict(bson_buffer* buffer, PyObject* dict, unsigned char check_k
761761
return 0;
762762
}
763763

764-
/* Write _id first if we have one and move_id is true, whether or not we're SON. */
765-
if (is_dict && move_id) {
764+
/* Write _id first if this is a top level doc. */
765+
if (is_dict && top_level) {
766766
PyObject* _id = PyDict_GetItemString(dict, "_id");
767767
if (_id) {
768768
/* Don't bother checking keys, but do make sure we're allowed to
@@ -774,7 +774,7 @@ static int write_dict(bson_buffer* buffer, PyObject* dict, unsigned char check_k
774774
}
775775

776776
if (PyObject_IsInstance(dict, SON)) {
777-
if (!write_son(buffer, dict, start_position, length_location, check_keys, move_id)) {
777+
if (!write_son(buffer, dict, start_position, length_location, check_keys, top_level)) {
778778
return 0;
779779
}
780780
} else if (is_dict) {
@@ -783,7 +783,7 @@ static int write_dict(bson_buffer* buffer, PyObject* dict, unsigned char check_k
783783
Py_ssize_t pos = 0;
784784

785785
while (PyDict_Next(dict, &pos, &key, &value)) {
786-
if (!decode_and_write_pair(buffer, key, value, check_keys, move_id)) {
786+
if (!decode_and_write_pair(buffer, key, value, check_keys, top_level)) {
787787
return 0;
788788
}
789789
}
@@ -814,10 +814,9 @@ static PyObject* _cbson_dict_to_bson(PyObject* self, PyObject* args) {
814814
PyObject* dict;
815815
PyObject* result;
816816
unsigned char check_keys;
817-
unsigned char move_id;
818817
bson_buffer* buffer;
819818

820-
if (!PyArg_ParseTuple(args, "Obb", &dict, &check_keys, &move_id)) {
819+
if (!PyArg_ParseTuple(args, "Ob", &dict, &check_keys)) {
821820
return NULL;
822821
}
823822

@@ -826,7 +825,7 @@ static PyObject* _cbson_dict_to_bson(PyObject* self, PyObject* args) {
826825
return NULL;
827826
}
828827

829-
if (!write_dict(buffer, dict, check_keys, move_id)) {
828+
if (!write_dict(buffer, dict, check_keys, 1)) {
830829
buffer_free(buffer);
831830
return NULL;
832831
}
@@ -908,7 +907,6 @@ static PyObject* _cbson_insert_message(PyObject* self, PyObject* args) {
908907

909908
for (i = 0; i < PyList_Size(docs); i++) {
910909
PyObject* doc = PyList_GetItem(docs, i);
911-
/* We move_id for all inserts. */
912910
if (!write_dict(buffer, doc, check_keys, 1)) {
913911
buffer_free(buffer);
914912
return NULL;
@@ -968,8 +966,6 @@ static PyObject* _cbson_update_message(PyObject* self, PyObject* args) {
968966
}
969967

970968
// save space for message length
971-
/* Note we move_id for the doc part of the update, but not for the spec.
972-
* This is to handle the upsert case. */
973969
length_location = buffer_save_bytes(buffer, 4);
974970
if (length_location == -1 ||
975971
!buffer_write_bytes(buffer, (const char*)&request_id, 4) ||
@@ -982,7 +978,7 @@ static PyObject* _cbson_update_message(PyObject* self, PyObject* args) {
982978
collection_name,
983979
collection_name_length + 1) ||
984980
!buffer_write_bytes(buffer, (const char*)&options, 4) ||
985-
!write_dict(buffer, spec, 0, 0) ||
981+
!write_dict(buffer, spec, 0, 1) ||
986982
!write_dict(buffer, doc, 0, 1)) {
987983
buffer_free(buffer);
988984
PyMem_Free(collection_name);

pymongo/bson.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ def _element_to_bson(key, value, check_keys):
411411
chr(subtype), value)
412412
if isinstance(value, Code):
413413
cstring = _make_c_string(value)
414-
scope = _dict_to_bson(value.scope, False)
414+
scope = _dict_to_bson(value.scope, False, False)
415415
full_length = struct.pack("<i", 8 + len(cstring) + len(scope))
416416
length = struct.pack("<i", len(cstring))
417417
return "\x0F" + name + full_length + length + cstring + scope
@@ -424,10 +424,10 @@ def _element_to_bson(key, value, check_keys):
424424
length = struct.pack("<i", len(cstring))
425425
return "\x02" + name + length + cstring
426426
if isinstance(value, dict):
427-
return "\x03" + name + _dict_to_bson(value, check_keys)
427+
return "\x03" + name + _dict_to_bson(value, check_keys, False)
428428
if isinstance(value, (list, tuple)):
429429
as_dict = SON(zip([str(i) for i in range(len(value))], value))
430-
return "\x04" + name + _dict_to_bson(as_dict, check_keys)
430+
return "\x04" + name + _dict_to_bson(as_dict, check_keys, False)
431431
if isinstance(value, ObjectId):
432432
return "\x07" + name + value.binary
433433
if value is True:
@@ -471,13 +471,13 @@ def _element_to_bson(key, value, check_keys):
471471
type(value))
472472

473473

474-
def _dict_to_bson(dict, check_keys, move_id=False):
474+
def _dict_to_bson(dict, check_keys, top_level=True):
475475
try:
476476
elements = ""
477-
if move_id and "_id" in dict:
477+
if top_level and "_id" in dict:
478478
elements += _element_to_bson("_id", dict["_id"], False)
479479
for (key, value) in dict.iteritems():
480-
if not move_id or key != "_id":
480+
if not top_level or key != "_id":
481481
elements += _element_to_bson(key, value, check_keys)
482482
except AttributeError:
483483
raise TypeError("encoder expected a mapping type but got: %r" % dict)
@@ -554,7 +554,7 @@ def __new__(cls, bson):
554554
"""
555555
return str.__new__(cls, bson)
556556

557-
def from_dict(cls, dct, check_keys=False, move_id=False):
557+
def from_dict(cls, dct, check_keys=False):
558558
"""Create a new :class:`BSON` instance from a mapping type
559559
(like :class:`dict`).
560560
@@ -568,10 +568,8 @@ def from_dict(cls, dct, check_keys=False, move_id=False):
568568
- `check_keys` (optional): check if keys start with '$' or
569569
contain '.', raising :class:`~pymongo.errors.InvalidName`
570570
in either case
571-
- `move_id` (optional): move ``_id`` to the front of the
572-
document's :class:`BSON` representation, if it is present.
573571
"""
574-
return cls(_dict_to_bson(dct, check_keys, move_id))
572+
return cls(_dict_to_bson(dct, check_keys))
575573
from_dict = classmethod(from_dict)
576574

577575
def to_dict(self):

pymongo/message.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def insert(collection_name, docs, check_keys, safe):
6363
"""
6464
data = __ZERO
6565
data += bson._make_c_string(collection_name)
66-
data += "".join([bson.BSON.from_dict(doc, check_keys, move_id=True)
66+
data += "".join([bson.BSON.from_dict(doc, check_keys)
6767
for doc in docs])
6868
if safe:
6969
(_, insert_message) = __pack_message(2002, data)
@@ -88,7 +88,7 @@ def update(collection_name, upsert, multi, spec, doc, safe):
8888
data += bson._make_c_string(collection_name)
8989
data += struct.pack("<i", options)
9090
data += bson.BSON.from_dict(spec)
91-
data += bson.BSON.from_dict(doc, move_id=True)
91+
data += bson.BSON.from_dict(doc)
9292
if safe:
9393
(_, update_message) = __pack_message(2001, data)
9494
(request_id, error_message) = __last_error()

test/test_bson.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -234,28 +234,17 @@ def test_null_character(self):
234234
self.assertRaises(InvalidDocument, BSON.from_dict, {"a": re.compile(u"ab\x00c")})
235235

236236
def test_move_id(self):
237-
self.assertEqual("\x19\x00\x00\x00\x02a\x00\x02\x00\x00\x00a\x00"
238-
"\x02_id\x00\x02\x00\x00\x00a\x00\x00",
239-
BSON.from_dict(SON([("a", "a"), ("_id", "a")])))
240-
241237
self.assertEqual("\x19\x00\x00\x00\x02_id\x00\x02\x00\x00\x00a\x00"
242238
"\x02a\x00\x02\x00\x00\x00a\x00\x00",
243-
BSON.from_dict(SON([("a", "a"), ("_id", "a")]), move_id=True))
244-
245-
self.assertEqual("\x2c\x00\x00\x00\x03b\x00"
246-
"\x19\x00\x00\x00\x02a\x00\x02\x00\x00\x00a\x00"
247-
"\x02_id\x00\x02\x00\x00\x00a\x00\x00"
248-
"\x02_id\x00\x02\x00\x00\x00b\x00\x00",
249-
BSON.from_dict(SON([("b", SON([("a", "a"), ("_id", "a")])),
250-
("_id", "b")])))
239+
BSON.from_dict(SON([("a", "a"), ("_id", "a")])))
251240

252241
self.assertEqual("\x2c\x00\x00\x00"
253242
"\x02_id\x00\x02\x00\x00\x00b\x00"
254243
"\x03b\x00"
255244
"\x19\x00\x00\x00\x02a\x00\x02\x00\x00\x00a\x00"
256245
"\x02_id\x00\x02\x00\x00\x00a\x00\x00\x00",
257246
BSON.from_dict(SON([("b", SON([("a", "a"), ("_id", "a")])),
258-
("_id", "b")]), move_id=True))
247+
("_id", "b")])))
259248

260249

261250
# TODO this test doesn't pass w/ C extension

0 commit comments

Comments
 (0)