| Index: third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc
|
| ===================================================================
|
| --- third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc (revision 216642)
|
| +++ third_party/protobuf/python/google/protobuf/pyext/python-proto2.cc (working copy)
|
| @@ -207,9 +207,9 @@
|
| "Clears and sets the values of a repeated scalar field."),
|
| CMETHOD(ByteSize, METH_NOARGS,
|
| "Returns the size of the message in bytes."),
|
| - CMETHOD(Clear, METH_NOARGS,
|
| + CMETHOD(Clear, METH_O,
|
| "Clears a protocol message."),
|
| - CMETHOD(ClearField, METH_O,
|
| + CMETHOD(ClearField, METH_VARARGS,
|
| "Clears a protocol message field by name."),
|
| CMETHOD(ClearFieldByDescriptor, METH_O,
|
| "Clears a protocol message field by descriptor."),
|
| @@ -274,7 +274,7 @@
|
| PyTypeObject CMessage_Type = {
|
| PyObject_HEAD_INIT(&PyType_Type)
|
| 0,
|
| - C("google3.net.google.protobuf.python.internal."
|
| + C("google.protobuf.internal."
|
| "_net_proto2___python."
|
| "CMessage"), // tp_name
|
| sizeof(CMessage), // tp_basicsize
|
| @@ -319,14 +319,12 @@
|
| // ------ Helper Functions:
|
|
|
| static void FormatTypeError(PyObject* arg, char* expected_types) {
|
| - PyObject* s = PyObject_Str(PyObject_Type(arg));
|
| - PyObject* repr = PyObject_Repr(PyObject_Type(arg));
|
| + PyObject* repr = PyObject_Repr(arg);
|
| PyErr_Format(PyExc_TypeError,
|
| "%.100s has type %.100s, but expected one of: %s",
|
| PyString_AS_STRING(repr),
|
| - PyString_AS_STRING(s),
|
| + arg->ob_type->tp_name,
|
| expected_types);
|
| - Py_DECREF(s);
|
| Py_DECREF(repr);
|
| }
|
|
|
| @@ -398,6 +396,28 @@
|
| return global_message_factory->GetPrototype(descriptor);
|
| }
|
|
|
| +static void ReleaseSubMessage(google::protobuf::Message* message,
|
| + const google::protobuf::FieldDescriptor* field_descriptor,
|
| + CMessage* child_cmessage) {
|
| + Message* released_message = message->GetReflection()->ReleaseMessage(
|
| + message, field_descriptor, global_message_factory);
|
| + GOOGLE_DCHECK(child_cmessage->message != NULL);
|
| + // ReleaseMessage will return NULL which differs from
|
| + // child_cmessage->message, if the field does not exist. In this case,
|
| + // the latter points to the default instance via a const_cast<>, so we
|
| + // have to reset it to a new mutable object since we are taking ownership.
|
| + if (released_message == NULL) {
|
| + const Message* prototype = global_message_factory->GetPrototype(
|
| + child_cmessage->message->GetDescriptor());
|
| + GOOGLE_DCHECK(prototype != NULL);
|
| + child_cmessage->message = prototype->New();
|
| + }
|
| + child_cmessage->parent = NULL;
|
| + child_cmessage->parent_field = NULL;
|
| + child_cmessage->free_message = true;
|
| + child_cmessage->read_only = false;
|
| +}
|
| +
|
| static bool CheckAndSetString(
|
| PyObject* arg, google::protobuf::Message* message,
|
| const google::protobuf::FieldDescriptor* descriptor,
|
| @@ -407,6 +427,9 @@
|
| GOOGLE_DCHECK(descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING ||
|
| descriptor->type() == google::protobuf::FieldDescriptor::TYPE_BYTES);
|
| if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
|
| +#else
|
| + if (descriptor->file()->options().cc_api_version() == 2 &&
|
| + descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
|
| if (!PyString_Check(arg) && !PyUnicode_Check(arg)) {
|
| FormatTypeError(arg, "str, unicode");
|
| return false;
|
| @@ -434,6 +457,9 @@
|
|
|
| PyObject* encoded_string = NULL;
|
| if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
|
| +#else
|
| + if (descriptor->file()->options().cc_api_version() == 2 &&
|
| + descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
|
| if (PyString_Check(arg)) {
|
| encoded_string = PyString_AsEncodedObject(arg, "utf-8", NULL);
|
| } else {
|
| @@ -504,8 +530,6 @@
|
| self->message = reflection->MutableMessage(
|
| message, self->parent_field->descriptor, global_message_factory);
|
| self->read_only = false;
|
| - self->parent = NULL;
|
| - self->parent_field = NULL;
|
| }
|
|
|
| static PyObject* InternalGetScalar(
|
| @@ -955,9 +979,41 @@
|
|
|
| // ------ Methods:
|
|
|
| -static PyObject* CMessage_Clear(CMessage* self, PyObject* args) {
|
| +static PyObject* CMessage_Clear(CMessage* self, PyObject* arg) {
|
| AssureWritable(self);
|
| - self->message->Clear();
|
| + google::protobuf::Message* message = self->message;
|
| +
|
| + // This block of code is equivalent to the following:
|
| + // for cfield_descriptor, child_cmessage in arg:
|
| + // ReleaseSubMessage(cfield_descriptor, child_cmessage)
|
| + if (!PyList_Check(arg)) {
|
| + PyErr_SetString(PyExc_TypeError, "Must be a list");
|
| + return NULL;
|
| + }
|
| + PyObject* messages_to_clear = arg;
|
| + Py_ssize_t num_messages_to_clear = PyList_GET_SIZE(messages_to_clear);
|
| + for(int i = 0; i < num_messages_to_clear; ++i) {
|
| + PyObject* message_tuple = PyList_GET_ITEM(messages_to_clear, i);
|
| + if (!PyTuple_Check(message_tuple) || PyTuple_GET_SIZE(message_tuple) != 2) {
|
| + PyErr_SetString(PyExc_TypeError, "Must be a tuple of size 2");
|
| + return NULL;
|
| + }
|
| +
|
| + PyObject* py_cfield_descriptor = PyTuple_GET_ITEM(message_tuple, 0);
|
| + PyObject* py_child_cmessage = PyTuple_GET_ITEM(message_tuple, 1);
|
| + if (!PyObject_TypeCheck(py_cfield_descriptor, &CFieldDescriptor_Type) ||
|
| + !PyObject_TypeCheck(py_child_cmessage, &CMessage_Type)) {
|
| + PyErr_SetString(PyExc_ValueError, "Invalid Tuple");
|
| + return NULL;
|
| + }
|
| +
|
| + CFieldDescriptor* cfield_descriptor = reinterpret_cast<CFieldDescriptor *>(
|
| + py_cfield_descriptor);
|
| + CMessage* child_cmessage = reinterpret_cast<CMessage *>(py_child_cmessage);
|
| + ReleaseSubMessage(message, cfield_descriptor->descriptor, child_cmessage);
|
| + }
|
| +
|
| + message->Clear();
|
| Py_RETURN_NONE;
|
| }
|
|
|
| @@ -1039,9 +1095,11 @@
|
| Py_RETURN_NONE;
|
| }
|
|
|
| -static PyObject* CMessage_ClearField(CMessage* self, PyObject* arg) {
|
| +static PyObject* CMessage_ClearField(CMessage* self, PyObject* args) {
|
| char* field_name;
|
| - if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
|
| + CMessage* child_cmessage = NULL;
|
| + if (!PyArg_ParseTuple(args, C("s|O!:ClearField"), &field_name,
|
| + &CMessage_Type, &child_cmessage)) {
|
| return NULL;
|
| }
|
|
|
| @@ -1054,7 +1112,11 @@
|
| return NULL;
|
| }
|
|
|
| - message->GetReflection()->ClearField(message, field_descriptor);
|
| + if (child_cmessage != NULL && !FIELD_IS_REPEATED(field_descriptor)) {
|
| + ReleaseSubMessage(message, field_descriptor, child_cmessage);
|
| + } else {
|
| + message->GetReflection()->ClearField(message, field_descriptor);
|
| + }
|
| Py_RETURN_NONE;
|
| }
|
|
|
| @@ -1313,6 +1375,7 @@
|
| AssureWritable(self);
|
| google::protobuf::io::CodedInputStream input(
|
| reinterpret_cast<const uint8*>(data), data_length);
|
| + input.SetExtensionRegistry(GetDescriptorPool(), global_message_factory);
|
| bool success = self->message->MergePartialFromCodedStream(&input);
|
| if (success) {
|
| return PyInt_FromLong(self->message->ByteSize());
|
|
|