|  | @@ -49,9 +49,10 @@
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  #include <google/protobuf/descriptor.pb.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/stubs/common.h>
 | 
	
		
			
				|  |  | +#include <google/protobuf/stubs/logging.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/io/coded_stream.h>
 | 
	
		
			
				|  |  | +#include <google/protobuf/util/message_differencer.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/descriptor.h>
 | 
	
		
			
				|  |  | -#include <google/protobuf/dynamic_message.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/message.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/text_format.h>
 | 
	
		
			
				|  |  |  #include <google/protobuf/pyext/descriptor.h>
 | 
	
	
		
			
				|  | @@ -88,12 +89,308 @@ namespace google {
 | 
	
		
			
				|  |  |  namespace protobuf {
 | 
	
		
			
				|  |  |  namespace python {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static PyObject* kDESCRIPTOR;
 | 
	
		
			
				|  |  | +static PyObject* k_extensions_by_name;
 | 
	
		
			
				|  |  | +static PyObject* k_extensions_by_number;
 | 
	
		
			
				|  |  | +PyObject* EnumTypeWrapper_class;
 | 
	
		
			
				|  |  | +static PyObject* PythonMessage_class;
 | 
	
		
			
				|  |  | +static PyObject* kEmptyWeakref;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Defines the Metaclass of all Message classes.
 | 
	
		
			
				|  |  | +// It allows us to cache some C++ pointers in the class object itself, they are
 | 
	
		
			
				|  |  | +// faster to extract than from the type's dictionary.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct PyMessageMeta {
 | 
	
		
			
				|  |  | +  // This is how CPython subclasses C structures: the base structure must be
 | 
	
		
			
				|  |  | +  // the first member of the object.
 | 
	
		
			
				|  |  | +  PyHeapTypeObject super;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // C++ descriptor of this message.
 | 
	
		
			
				|  |  | +  const Descriptor* message_descriptor;
 | 
	
		
			
				|  |  | +  // Owned reference, used to keep the pointer above alive.
 | 
	
		
			
				|  |  | +  PyObject* py_message_descriptor;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +namespace message_meta {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static int InsertEmptyWeakref(PyTypeObject* base);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Add the number of a field descriptor to the containing message class.
 | 
	
		
			
				|  |  | +// Equivalent to:
 | 
	
		
			
				|  |  | +//   _cls.<field>_FIELD_NUMBER = <number>
 | 
	
		
			
				|  |  | +static bool AddFieldNumberToClass(
 | 
	
		
			
				|  |  | +    PyObject* cls, const FieldDescriptor* field_descriptor) {
 | 
	
		
			
				|  |  | +  string constant_name = field_descriptor->name() + "_FIELD_NUMBER";
 | 
	
		
			
				|  |  | +  UpperString(&constant_name);
 | 
	
		
			
				|  |  | +  ScopedPyObjectPtr attr_name(PyString_FromStringAndSize(
 | 
	
		
			
				|  |  | +      constant_name.c_str(), constant_name.size()));
 | 
	
		
			
				|  |  | +  if (attr_name == NULL) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  ScopedPyObjectPtr number(PyInt_FromLong(field_descriptor->number()));
 | 
	
		
			
				|  |  | +  if (number == NULL) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (PyObject_SetAttr(cls, attr_name, number) == -1) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return true;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Finalize the creation of the Message class.
 | 
	
		
			
				|  |  | +// Called from its metaclass: GeneratedProtocolMessageType.__init__().
 | 
	
		
			
				|  |  | +static int AddDescriptors(PyObject* cls, PyObject* descriptor) {
 | 
	
		
			
				|  |  | +  const Descriptor* message_descriptor =
 | 
	
		
			
				|  |  | +      cdescriptor_pool::RegisterMessageClass(
 | 
	
		
			
				|  |  | +          GetDescriptorPool(), cls, descriptor);
 | 
	
		
			
				|  |  | +  if (message_descriptor == NULL) {
 | 
	
		
			
				|  |  | +    return -1;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // If there are extension_ranges, the message is "extendable", and extension
 | 
	
		
			
				|  |  | +  // classes will register themselves in this class.
 | 
	
		
			
				|  |  | +  if (message_descriptor->extension_range_count() > 0) {
 | 
	
		
			
				|  |  | +    ScopedPyObjectPtr by_name(PyDict_New());
 | 
	
		
			
				|  |  | +    if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) {
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    ScopedPyObjectPtr by_number(PyDict_New());
 | 
	
		
			
				|  |  | +    if (PyObject_SetAttr(cls, k_extensions_by_number, by_number) < 0) {
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // For each field set: cls.<field>_FIELD_NUMBER = <number>
 | 
	
		
			
				|  |  | +  for (int i = 0; i < message_descriptor->field_count(); ++i) {
 | 
	
		
			
				|  |  | +    if (!AddFieldNumberToClass(cls, message_descriptor->field(i))) {
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // For each enum set cls.<enum name> = EnumTypeWrapper(<enum descriptor>).
 | 
	
		
			
				|  |  | +  //
 | 
	
		
			
				|  |  | +  // The enum descriptor we get from
 | 
	
		
			
				|  |  | +  // <messagedescriptor>.enum_types_by_name[name]
 | 
	
		
			
				|  |  | +  // which was built previously.
 | 
	
		
			
				|  |  | +  for (int i = 0; i < message_descriptor->enum_type_count(); ++i) {
 | 
	
		
			
				|  |  | +    const EnumDescriptor* enum_descriptor = message_descriptor->enum_type(i);
 | 
	
		
			
				|  |  | +    ScopedPyObjectPtr enum_type(
 | 
	
		
			
				|  |  | +        PyEnumDescriptor_FromDescriptor(enum_descriptor));
 | 
	
		
			
				|  |  | +    if (enum_type == NULL) {
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +     }
 | 
	
		
			
				|  |  | +    // Add wrapped enum type to message class.
 | 
	
		
			
				|  |  | +    ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
 | 
	
		
			
				|  |  | +        EnumTypeWrapper_class, enum_type.get(), NULL));
 | 
	
		
			
				|  |  | +    if (wrapped == NULL) {
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (PyObject_SetAttrString(
 | 
	
		
			
				|  |  | +            cls, enum_descriptor->name().c_str(), wrapped) == -1) {
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // For each enum value add cls.<name> = <number>
 | 
	
		
			
				|  |  | +    for (int j = 0; j < enum_descriptor->value_count(); ++j) {
 | 
	
		
			
				|  |  | +      const EnumValueDescriptor* enum_value_descriptor =
 | 
	
		
			
				|  |  | +          enum_descriptor->value(j);
 | 
	
		
			
				|  |  | +      ScopedPyObjectPtr value_number(PyInt_FromLong(
 | 
	
		
			
				|  |  | +          enum_value_descriptor->number()));
 | 
	
		
			
				|  |  | +      if (value_number == NULL) {
 | 
	
		
			
				|  |  | +        return -1;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (PyObject_SetAttrString(
 | 
	
		
			
				|  |  | +              cls, enum_value_descriptor->name().c_str(), value_number) == -1) {
 | 
	
		
			
				|  |  | +        return -1;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // For each extension set cls.<extension name> = <extension descriptor>.
 | 
	
		
			
				|  |  | +  //
 | 
	
		
			
				|  |  | +  // Extension descriptors come from
 | 
	
		
			
				|  |  | +  // <message descriptor>.extensions_by_name[name]
 | 
	
		
			
				|  |  | +  // which was defined previously.
 | 
	
		
			
				|  |  | +  for (int i = 0; i < message_descriptor->extension_count(); ++i) {
 | 
	
		
			
				|  |  | +    const google::protobuf::FieldDescriptor* field = message_descriptor->extension(i);
 | 
	
		
			
				|  |  | +    ScopedPyObjectPtr extension_field(PyFieldDescriptor_FromDescriptor(field));
 | 
	
		
			
				|  |  | +    if (extension_field == NULL) {
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Add the extension field to the message class.
 | 
	
		
			
				|  |  | +    if (PyObject_SetAttrString(
 | 
	
		
			
				|  |  | +            cls, field->name().c_str(), extension_field) == -1) {
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // For each extension set cls.<extension name>_FIELD_NUMBER = <number>.
 | 
	
		
			
				|  |  | +    if (!AddFieldNumberToClass(cls, field)) {
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static PyObject* New(PyTypeObject* type,
 | 
	
		
			
				|  |  | +                     PyObject* args, PyObject* kwargs) {
 | 
	
		
			
				|  |  | +  static char *kwlist[] = {"name", "bases", "dict", 0};
 | 
	
		
			
				|  |  | +  PyObject *bases, *dict;
 | 
	
		
			
				|  |  | +  const char* name;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Check arguments: (name, bases, dict)
 | 
	
		
			
				|  |  | +  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!O!:type", kwlist,
 | 
	
		
			
				|  |  | +                                   &name,
 | 
	
		
			
				|  |  | +                                   &PyTuple_Type, &bases,
 | 
	
		
			
				|  |  | +                                   &PyDict_Type, &dict)) {
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Check bases: only (), or (message.Message,) are allowed
 | 
	
		
			
				|  |  | +  if (!(PyTuple_GET_SIZE(bases) == 0 ||
 | 
	
		
			
				|  |  | +        (PyTuple_GET_SIZE(bases) == 1 &&
 | 
	
		
			
				|  |  | +         PyTuple_GET_ITEM(bases, 0) == PythonMessage_class))) {
 | 
	
		
			
				|  |  | +    PyErr_SetString(PyExc_TypeError,
 | 
	
		
			
				|  |  | +                    "A Message class can only inherit from Message");
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Check dict['DESCRIPTOR']
 | 
	
		
			
				|  |  | +  PyObject* descriptor = PyDict_GetItem(dict, kDESCRIPTOR);
 | 
	
		
			
				|  |  | +  if (descriptor == NULL) {
 | 
	
		
			
				|  |  | +    PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) {
 | 
	
		
			
				|  |  | +    PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
 | 
	
		
			
				|  |  | +                 descriptor->ob_type->tp_name);
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Build the arguments to the base metaclass.
 | 
	
		
			
				|  |  | +  // We change the __bases__ classes.
 | 
	
		
			
				|  |  | +  ScopedPyObjectPtr new_args(Py_BuildValue(
 | 
	
		
			
				|  |  | +      "s(OO)O", name, &CMessage_Type, PythonMessage_class, dict));
 | 
	
		
			
				|  |  | +  if (new_args == NULL) {
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  // Call the base metaclass.
 | 
	
		
			
				|  |  | +  ScopedPyObjectPtr result(PyType_Type.tp_new(type, new_args, NULL));
 | 
	
		
			
				|  |  | +  if (result == NULL) {
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  PyMessageMeta* newtype = reinterpret_cast<PyMessageMeta*>(result.get());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Insert the empty weakref into the base classes.
 | 
	
		
			
				|  |  | +  if (InsertEmptyWeakref(
 | 
	
		
			
				|  |  | +          reinterpret_cast<PyTypeObject*>(PythonMessage_class)) < 0 ||
 | 
	
		
			
				|  |  | +      InsertEmptyWeakref(&CMessage_Type) < 0) {
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Cache the descriptor, both as Python object and as C++ pointer.
 | 
	
		
			
				|  |  | +  const Descriptor* message_descriptor =
 | 
	
		
			
				|  |  | +      PyMessageDescriptor_AsDescriptor(descriptor);
 | 
	
		
			
				|  |  | +  if (message_descriptor == NULL) {
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  Py_INCREF(descriptor);
 | 
	
		
			
				|  |  | +  newtype->py_message_descriptor = descriptor;
 | 
	
		
			
				|  |  | +  newtype->message_descriptor = message_descriptor;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Continue with type initialization: add other descriptors, enum values...
 | 
	
		
			
				|  |  | +  if (AddDescriptors(result, descriptor) < 0) {
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return result.release();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static void Dealloc(PyMessageMeta *self) {
 | 
	
		
			
				|  |  | +  Py_DECREF(self->py_message_descriptor);
 | 
	
		
			
				|  |  | +  Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static PyObject* GetDescriptor(PyMessageMeta *self, void *closure) {
 | 
	
		
			
				|  |  | +  Py_INCREF(self->py_message_descriptor);
 | 
	
		
			
				|  |  | +  return self->py_message_descriptor;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// This function inserts and empty weakref at the end of the list of
 | 
	
		
			
				|  |  | +// subclasses for the main protocol buffer Message class.
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +// This eliminates a O(n^2) behaviour in the internal add_subclass
 | 
	
		
			
				|  |  | +// routine.
 | 
	
		
			
				|  |  | +static int InsertEmptyWeakref(PyTypeObject *base_type) {
 | 
	
		
			
				|  |  | +#if PY_MAJOR_VERSION >= 3
 | 
	
		
			
				|  |  | +  // Python 3.4 has already included the fix for the issue that this
 | 
	
		
			
				|  |  | +  // hack addresses. For further background and the fix please see
 | 
	
		
			
				|  |  | +  // https://bugs.python.org/issue17936.
 | 
	
		
			
				|  |  | +  return 0;
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +  PyObject *subclasses = base_type->tp_subclasses;
 | 
	
		
			
				|  |  | +  if (subclasses && PyList_CheckExact(subclasses)) {
 | 
	
		
			
				|  |  | +    return PyList_Append(subclasses, kEmptyWeakref);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return 0;
 | 
	
		
			
				|  |  | +#endif  // PY_MAJOR_VERSION >= 3
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +}  // namespace message_meta
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +PyTypeObject PyMessageMeta_Type {
 | 
	
		
			
				|  |  | +  PyVarObject_HEAD_INIT(&PyType_Type, 0)
 | 
	
		
			
				|  |  | +  FULL_MODULE_NAME ".MessageMeta",     // tp_name
 | 
	
		
			
				|  |  | +  sizeof(PyMessageMeta),               // tp_basicsize
 | 
	
		
			
				|  |  | +  0,                                   // tp_itemsize
 | 
	
		
			
				|  |  | +  (destructor)message_meta::Dealloc,   // tp_dealloc
 | 
	
		
			
				|  |  | +  0,                                   // tp_print
 | 
	
		
			
				|  |  | +  0,                                   // tp_getattr
 | 
	
		
			
				|  |  | +  0,                                   // tp_setattr
 | 
	
		
			
				|  |  | +  0,                                   // tp_compare
 | 
	
		
			
				|  |  | +  0,                                   // tp_repr
 | 
	
		
			
				|  |  | +  0,                                   // tp_as_number
 | 
	
		
			
				|  |  | +  0,                                   // tp_as_sequence
 | 
	
		
			
				|  |  | +  0,                                   // tp_as_mapping
 | 
	
		
			
				|  |  | +  0,                                   // tp_hash
 | 
	
		
			
				|  |  | +  0,                                   // tp_call
 | 
	
		
			
				|  |  | +  0,                                   // tp_str
 | 
	
		
			
				|  |  | +  0,                                   // tp_getattro
 | 
	
		
			
				|  |  | +  0,                                   // tp_setattro
 | 
	
		
			
				|  |  | +  0,                                   // tp_as_buffer
 | 
	
		
			
				|  |  | +  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  // tp_flags
 | 
	
		
			
				|  |  | +  "The metaclass of ProtocolMessages",  // tp_doc
 | 
	
		
			
				|  |  | +  0,                                   // tp_traverse
 | 
	
		
			
				|  |  | +  0,                                   // tp_clear
 | 
	
		
			
				|  |  | +  0,                                   // tp_richcompare
 | 
	
		
			
				|  |  | +  0,                                   // tp_weaklistoffset
 | 
	
		
			
				|  |  | +  0,                                   // tp_iter
 | 
	
		
			
				|  |  | +  0,                                   // tp_iternext
 | 
	
		
			
				|  |  | +  0,                                   // tp_methods
 | 
	
		
			
				|  |  | +  0,                                   // tp_members
 | 
	
		
			
				|  |  | +  0,                                   // tp_getset
 | 
	
		
			
				|  |  | +  0,                                   // tp_base
 | 
	
		
			
				|  |  | +  0,                                   // tp_dict
 | 
	
		
			
				|  |  | +  0,                                   // tp_descr_get
 | 
	
		
			
				|  |  | +  0,                                   // tp_descr_set
 | 
	
		
			
				|  |  | +  0,                                   // tp_dictoffset
 | 
	
		
			
				|  |  | +  0,                                   // tp_init
 | 
	
		
			
				|  |  | +  0,                                   // tp_alloc
 | 
	
		
			
				|  |  | +  message_meta::New,                   // tp_new
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
 | 
	
		
			
				|  |  | +  if (!PyObject_TypeCheck(cls, &PyMessageMeta_Type)) {
 | 
	
		
			
				|  |  | +    PyErr_Format(PyExc_TypeError, "Class %s is not a Message", cls->tp_name);
 | 
	
		
			
				|  |  | +    return NULL;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return reinterpret_cast<PyMessageMeta*>(cls)->message_descriptor;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // Forward declarations
 | 
	
		
			
				|  |  |  namespace cmessage {
 | 
	
		
			
				|  |  | -static const FieldDescriptor* GetFieldDescriptor(
 | 
	
		
			
				|  |  | -    CMessage* self, PyObject* name);
 | 
	
		
			
				|  |  | -static const Descriptor* GetMessageDescriptor(PyTypeObject* cls);
 | 
	
		
			
				|  |  | -static string GetMessageName(CMessage* self);
 | 
	
		
			
				|  |  |  int InternalReleaseFieldByDescriptor(
 | 
	
		
			
				|  |  |      CMessage* self,
 | 
	
		
			
				|  |  |      const FieldDescriptor* field_descriptor,
 | 
	
	
		
			
				|  | @@ -180,7 +477,7 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
 | 
	
		
			
				|  |  |    if (self->composite_fields) {
 | 
	
		
			
				|  |  |      // Never use self->message in this function, it may be already freed.
 | 
	
		
			
				|  |  |      const Descriptor* message_descriptor =
 | 
	
		
			
				|  |  | -        cmessage::GetMessageDescriptor(Py_TYPE(self));
 | 
	
		
			
				|  |  | +        GetMessageDescriptor(Py_TYPE(self));
 | 
	
		
			
				|  |  |      while (PyDict_Next(self->composite_fields, &pos, &key, &field)) {
 | 
	
		
			
				|  |  |        Py_ssize_t key_str_size;
 | 
	
		
			
				|  |  |        char *key_str_data;
 | 
	
	
		
			
				|  | @@ -213,8 +510,6 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // ---------------------------------------------------------------------
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static DynamicMessageFactory* message_factory;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  // Constants used for integer type range checking.
 | 
	
		
			
				|  |  |  PyObject* kPythonZero;
 | 
	
		
			
				|  |  |  PyObject* kint32min_py;
 | 
	
	
		
			
				|  | @@ -224,17 +519,13 @@ PyObject* kint64min_py;
 | 
	
		
			
				|  |  |  PyObject* kint64max_py;
 | 
	
		
			
				|  |  |  PyObject* kuint64max_py;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -PyObject* EnumTypeWrapper_class;
 | 
	
		
			
				|  |  |  PyObject* EncodeError_class;
 | 
	
		
			
				|  |  |  PyObject* DecodeError_class;
 | 
	
		
			
				|  |  |  PyObject* PickleError_class;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Constant PyString values used for GetAttr/GetItem.
 | 
	
		
			
				|  |  | -static PyObject* kDESCRIPTOR;
 | 
	
		
			
				|  |  |  static PyObject* k_cdescriptor;
 | 
	
		
			
				|  |  |  static PyObject* kfull_name;
 | 
	
		
			
				|  |  | -static PyObject* k_extensions_by_name;
 | 
	
		
			
				|  |  | -static PyObject* k_extensions_by_number;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* Is 64bit */
 | 
	
		
			
				|  |  |  void FormatTypeError(PyObject* arg, char* expected_types) {
 | 
	
	
		
			
				|  | @@ -432,10 +723,6 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace cmessage {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -DynamicMessageFactory* GetMessageFactory() {
 | 
	
		
			
				|  |  | -  return message_factory;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  static int MaybeReleaseOverlappingOneofField(
 | 
	
		
			
				|  |  |      CMessage* cmessage,
 | 
	
		
			
				|  |  |      const FieldDescriptor* field) {
 | 
	
	
		
			
				|  | @@ -486,7 +773,7 @@ static Message* GetMutableMessage(
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return reflection->MutableMessage(
 | 
	
		
			
				|  |  | -      parent_message, parent_field, message_factory);
 | 
	
		
			
				|  |  | +      parent_message, parent_field, GetDescriptorPool()->message_factory);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  struct FixupMessageReference : public ChildVisitor {
 | 
	
	
		
			
				|  | @@ -527,8 +814,9 @@ int AssureWritable(CMessage* self) {
 | 
	
		
			
				|  |  |      // If parent is NULL but we are trying to modify a read-only message, this
 | 
	
		
			
				|  |  |      // is a reference to a constant default instance that needs to be replaced
 | 
	
		
			
				|  |  |      // with a mutable top-level message.
 | 
	
		
			
				|  |  | -    const Message* prototype = message_factory->GetPrototype(
 | 
	
		
			
				|  |  | -        self->message->GetDescriptor());
 | 
	
		
			
				|  |  | +    const Message* prototype =
 | 
	
		
			
				|  |  | +        GetDescriptorPool()->message_factory->GetPrototype(
 | 
	
		
			
				|  |  | +            self->message->GetDescriptor());
 | 
	
		
			
				|  |  |      self->message = prototype->New();
 | 
	
		
			
				|  |  |      self->owner.reset(self->message);
 | 
	
		
			
				|  |  |      // Cascade the new owner to eventual children: even if this message is
 | 
	
	
		
			
				|  | @@ -567,23 +855,6 @@ int AssureWritable(CMessage* self) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // --- Globals:
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Retrieve the C++ Descriptor of a message class.
 | 
	
		
			
				|  |  | -// On error, returns NULL with an exception set.
 | 
	
		
			
				|  |  | -static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
 | 
	
		
			
				|  |  | -  ScopedPyObjectPtr descriptor(PyObject_GetAttr(
 | 
	
		
			
				|  |  | -      reinterpret_cast<PyObject*>(cls), kDESCRIPTOR));
 | 
	
		
			
				|  |  | -  if (descriptor == NULL) {
 | 
	
		
			
				|  |  | -    PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
 | 
	
		
			
				|  |  | -    return NULL;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) {
 | 
	
		
			
				|  |  | -    PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
 | 
	
		
			
				|  |  | -                 descriptor->ob_type->tp_name);
 | 
	
		
			
				|  |  | -    return NULL;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return PyMessageDescriptor_AsDescriptor(descriptor);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  // Retrieve a C++ FieldDescriptor for a message attribute.
 | 
	
		
			
				|  |  |  // The C++ message must be valid.
 | 
	
		
			
				|  |  |  // TODO(amauryfa): This function should stay internal, because exception
 | 
	
	
		
			
				|  | @@ -846,9 +1117,9 @@ int InitAttributes(CMessage* self, PyObject* kwargs) {
 | 
	
		
			
				|  |  |            return -1;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        } else {
 | 
	
		
			
				|  |  | -        if (repeated_scalar_container::Extend(
 | 
	
		
			
				|  |  | +        if (ScopedPyObjectPtr(repeated_scalar_container::Extend(
 | 
	
		
			
				|  |  |                  reinterpret_cast<RepeatedScalarContainer*>(container.get()),
 | 
	
		
			
				|  |  | -                value) ==
 | 
	
		
			
				|  |  | +                value)) ==
 | 
	
		
			
				|  |  |              NULL) {
 | 
	
		
			
				|  |  |            return -1;
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -927,7 +1198,7 @@ static PyObject* New(PyTypeObject* type,
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    const Message* default_message =
 | 
	
		
			
				|  |  | -      message_factory->GetPrototype(message_descriptor);
 | 
	
		
			
				|  |  | +      GetDescriptorPool()->message_factory->GetPrototype(message_descriptor);
 | 
	
		
			
				|  |  |    if (default_message == NULL) {
 | 
	
		
			
				|  |  |      PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
	
		
			
				|  | @@ -1257,6 +1528,7 @@ int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner) {
 | 
	
		
			
				|  |  |  Message* ReleaseMessage(CMessage* self,
 | 
	
		
			
				|  |  |                          const Descriptor* descriptor,
 | 
	
		
			
				|  |  |                          const FieldDescriptor* field_descriptor) {
 | 
	
		
			
				|  |  | +  MessageFactory* message_factory = GetDescriptorPool()->message_factory;
 | 
	
		
			
				|  |  |    Message* released_message = self->message->GetReflection()->ReleaseMessage(
 | 
	
		
			
				|  |  |        self->message, field_descriptor, message_factory);
 | 
	
		
			
				|  |  |    // ReleaseMessage will return NULL which differs from
 | 
	
	
		
			
				|  | @@ -1492,34 +1764,35 @@ static PyObject* SerializePartialToString(CMessage* self) {
 | 
	
		
			
				|  |  |  // appropriate.
 | 
	
		
			
				|  |  |  class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter {
 | 
	
		
			
				|  |  |   public:
 | 
	
		
			
				|  |  | -  PythonFieldValuePrinter() : float_holder_(PyFloat_FromDouble(0)) {}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    // Python has some differences from C++ when printing floating point numbers.
 | 
	
		
			
				|  |  |    //
 | 
	
		
			
				|  |  |    // 1) Trailing .0 is always printed.
 | 
	
		
			
				|  |  | -  // 2) Outputted is rounded to 12 digits.
 | 
	
		
			
				|  |  | +  // 2) (Python2) Output is rounded to 12 digits.
 | 
	
		
			
				|  |  | +  // 3) (Python3) The full precision of the double is preserved (and Python uses
 | 
	
		
			
				|  |  | +  //    David M. Gay's dtoa(), when the C++ code uses SimpleDtoa. There are some
 | 
	
		
			
				|  |  | +  //    differences, but they rarely happen)
 | 
	
		
			
				|  |  |    //
 | 
	
		
			
				|  |  |    // We override floating point printing with the C-API function for printing
 | 
	
		
			
				|  |  |    // Python floats to ensure consistency.
 | 
	
		
			
				|  |  |    string PrintFloat(float value) const { return PrintDouble(value); }
 | 
	
		
			
				|  |  |    string PrintDouble(double value) const {
 | 
	
		
			
				|  |  | -    reinterpret_cast<PyFloatObject*>(float_holder_.get())->ob_fval = value;
 | 
	
		
			
				|  |  | -    ScopedPyObjectPtr s(PyObject_Str(float_holder_.get()));
 | 
	
		
			
				|  |  | -    if (s == NULL) return string();
 | 
	
		
			
				|  |  | +    // Same as float.__str__()
 | 
	
		
			
				|  |  | +    char* buf = PyOS_double_to_string(
 | 
	
		
			
				|  |  | +        value,
 | 
	
		
			
				|  |  |  #if PY_MAJOR_VERSION < 3
 | 
	
		
			
				|  |  | -    char *cstr = PyBytes_AS_STRING(static_cast<PyObject*>(s));
 | 
	
		
			
				|  |  | +        'g', PyFloat_STR_PRECISION,  // Output is rounded to 12 digits.
 | 
	
		
			
				|  |  |  #else
 | 
	
		
			
				|  |  | -    char *cstr = PyUnicode_AsUTF8(s);
 | 
	
		
			
				|  |  | +        'r', 0,
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  | -    return string(cstr);
 | 
	
		
			
				|  |  | +        Py_DTSF_ADD_DOT_0,  // Trailing .0 is always printed.
 | 
	
		
			
				|  |  | +        NULL);
 | 
	
		
			
				|  |  | +    if (!buf) {
 | 
	
		
			
				|  |  | +      return string();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    string result(buf);
 | 
	
		
			
				|  |  | +    PyMem_Free(buf);
 | 
	
		
			
				|  |  | +    return result;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | - private:
 | 
	
		
			
				|  |  | -  // Holder for a python float object which we use to allow us to use
 | 
	
		
			
				|  |  | -  // the Python API for printing doubles. We initialize once and then
 | 
	
		
			
				|  |  | -  // directly modify it for every float printed to save on allocations
 | 
	
		
			
				|  |  | -  // and refcounting.
 | 
	
		
			
				|  |  | -  ScopedPyObjectPtr float_holder_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static PyObject* ToStr(CMessage* self) {
 | 
	
	
		
			
				|  | @@ -1590,7 +1863,7 @@ static PyObject* CopyFrom(CMessage* self, PyObject* arg) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // CopyFrom on the message will not clean up self->composite_fields,
 | 
	
		
			
				|  |  |    // which can leave us in an inconsistent state, so clear it out here.
 | 
	
		
			
				|  |  | -  Clear(self);
 | 
	
		
			
				|  |  | +  (void)ScopedPyObjectPtr(Clear(self));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    self->message->CopyFrom(*other_message->message);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1607,7 +1880,8 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
 | 
	
		
			
				|  |  |    AssureWritable(self);
 | 
	
		
			
				|  |  |    io::CodedInputStream input(
 | 
	
		
			
				|  |  |        reinterpret_cast<const uint8*>(data), data_length);
 | 
	
		
			
				|  |  | -  input.SetExtensionRegistry(GetDescriptorPool()->pool, message_factory);
 | 
	
		
			
				|  |  | +  input.SetExtensionRegistry(GetDescriptorPool()->pool,
 | 
	
		
			
				|  |  | +                             GetDescriptorPool()->message_factory);
 | 
	
		
			
				|  |  |    bool success = self->message->MergePartialFromCodedStream(&input);
 | 
	
		
			
				|  |  |    if (success) {
 | 
	
		
			
				|  |  |      return PyInt_FromLong(input.CurrentPosition());
 | 
	
	
		
			
				|  | @@ -1618,7 +1892,7 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static PyObject* ParseFromString(CMessage* self, PyObject* arg) {
 | 
	
		
			
				|  |  | -  if (Clear(self) == NULL) {
 | 
	
		
			
				|  |  | +  if (ScopedPyObjectPtr(Clear(self)) == NULL) {
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return MergeFromString(self, arg);
 | 
	
	
		
			
				|  | @@ -1790,6 +2064,7 @@ static PyObject* ListFields(CMessage* self) {
 | 
	
		
			
				|  |  |        // Steals reference to 'extension'
 | 
	
		
			
				|  |  |        PyTuple_SET_ITEM(t.get(), 1, extension);
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | +      // Normal field
 | 
	
		
			
				|  |  |        const string& field_name = fields[i]->name();
 | 
	
		
			
				|  |  |        ScopedPyObjectPtr py_field_name(PyString_FromStringAndSize(
 | 
	
		
			
				|  |  |            field_name.c_str(), field_name.length()));
 | 
	
	
		
			
				|  | @@ -1841,28 +2116,34 @@ PyObject* FindInitializationErrors(CMessage* self) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) {
 | 
	
		
			
				|  |  | -  if (!PyObject_TypeCheck(other, &CMessage_Type)) {
 | 
	
		
			
				|  |  | -    if (opid == Py_EQ) {
 | 
	
		
			
				|  |  | -      Py_RETURN_FALSE;
 | 
	
		
			
				|  |  | -    } else if (opid == Py_NE) {
 | 
	
		
			
				|  |  | -      Py_RETURN_TRUE;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (opid == Py_EQ || opid == Py_NE) {
 | 
	
		
			
				|  |  | -    ScopedPyObjectPtr self_fields(ListFields(self));
 | 
	
		
			
				|  |  | -    if (!self_fields) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    ScopedPyObjectPtr other_fields(ListFields(
 | 
	
		
			
				|  |  | -        reinterpret_cast<CMessage*>(other)));
 | 
	
		
			
				|  |  | -    if (!other_fields) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    return PyObject_RichCompare(self_fields, other_fields, opid);
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | +  // Only equality comparisons are implemented.
 | 
	
		
			
				|  |  | +  if (opid != Py_EQ && opid != Py_NE) {
 | 
	
		
			
				|  |  |      Py_INCREF(Py_NotImplemented);
 | 
	
		
			
				|  |  |      return Py_NotImplemented;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  bool equals = true;
 | 
	
		
			
				|  |  | +  // If other is not a message, it cannot be equal.
 | 
	
		
			
				|  |  | +  if (!PyObject_TypeCheck(other, &CMessage_Type)) {
 | 
	
		
			
				|  |  | +    equals = false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  const google::protobuf::Message* other_message =
 | 
	
		
			
				|  |  | +      reinterpret_cast<CMessage*>(other)->message;
 | 
	
		
			
				|  |  | +  // If messages don't have the same descriptors, they are not equal.
 | 
	
		
			
				|  |  | +  if (equals &&
 | 
	
		
			
				|  |  | +      self->message->GetDescriptor() != other_message->GetDescriptor()) {
 | 
	
		
			
				|  |  | +    equals = false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  // Check the message contents.
 | 
	
		
			
				|  |  | +  if (equals && !google::protobuf::util::MessageDifferencer::Equals(
 | 
	
		
			
				|  |  | +          *self->message,
 | 
	
		
			
				|  |  | +          *reinterpret_cast<CMessage*>(other)->message)) {
 | 
	
		
			
				|  |  | +    equals = false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (equals ^ (opid == Py_EQ)) {
 | 
	
		
			
				|  |  | +    Py_RETURN_FALSE;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    Py_RETURN_TRUE;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  PyObject* InternalGetScalar(const Message* message,
 | 
	
	
		
			
				|  | @@ -1950,7 +2231,7 @@ PyObject* InternalGetSubMessage(
 | 
	
		
			
				|  |  |      CMessage* self, const FieldDescriptor* field_descriptor) {
 | 
	
		
			
				|  |  |    const Reflection* reflection = self->message->GetReflection();
 | 
	
		
			
				|  |  |    const Message& sub_message = reflection->GetMessage(
 | 
	
		
			
				|  |  | -      *self->message, field_descriptor, message_factory);
 | 
	
		
			
				|  |  | +      *self->message, field_descriptor, GetDescriptorPool()->message_factory);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    PyObject *message_class = cdescriptor_pool::GetMessageClass(
 | 
	
		
			
				|  |  |        GetDescriptorPool(), field_descriptor->message_type());
 | 
	
	
		
			
				|  | @@ -2085,125 +2366,6 @@ PyObject* FromString(PyTypeObject* cls, PyObject* serialized) {
 | 
	
		
			
				|  |  |    return py_cmsg;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Add the number of a field descriptor to the containing message class.
 | 
	
		
			
				|  |  | -// Equivalent to:
 | 
	
		
			
				|  |  | -//   _cls.<field>_FIELD_NUMBER = <number>
 | 
	
		
			
				|  |  | -static bool AddFieldNumberToClass(
 | 
	
		
			
				|  |  | -    PyObject* cls, const FieldDescriptor* field_descriptor) {
 | 
	
		
			
				|  |  | -  string constant_name = field_descriptor->name() + "_FIELD_NUMBER";
 | 
	
		
			
				|  |  | -  UpperString(&constant_name);
 | 
	
		
			
				|  |  | -  ScopedPyObjectPtr attr_name(PyString_FromStringAndSize(
 | 
	
		
			
				|  |  | -      constant_name.c_str(), constant_name.size()));
 | 
	
		
			
				|  |  | -  if (attr_name == NULL) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  ScopedPyObjectPtr number(PyInt_FromLong(field_descriptor->number()));
 | 
	
		
			
				|  |  | -  if (number == NULL) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (PyObject_SetAttr(cls, attr_name, number) == -1) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return true;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// Finalize the creation of the Message class.
 | 
	
		
			
				|  |  | -// Called from its metaclass: GeneratedProtocolMessageType.__init__().
 | 
	
		
			
				|  |  | -static PyObject* AddDescriptors(PyObject* cls, PyObject* descriptor) {
 | 
	
		
			
				|  |  | -  const Descriptor* message_descriptor =
 | 
	
		
			
				|  |  | -      cdescriptor_pool::RegisterMessageClass(
 | 
	
		
			
				|  |  | -          GetDescriptorPool(), cls, descriptor);
 | 
	
		
			
				|  |  | -  if (message_descriptor == NULL) {
 | 
	
		
			
				|  |  | -    return NULL;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // If there are extension_ranges, the message is "extendable", and extension
 | 
	
		
			
				|  |  | -  // classes will register themselves in this class.
 | 
	
		
			
				|  |  | -  if (message_descriptor->extension_range_count() > 0) {
 | 
	
		
			
				|  |  | -    ScopedPyObjectPtr by_name(PyDict_New());
 | 
	
		
			
				|  |  | -    if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    ScopedPyObjectPtr by_number(PyDict_New());
 | 
	
		
			
				|  |  | -    if (PyObject_SetAttr(cls, k_extensions_by_number, by_number) < 0) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // For each field set: cls.<field>_FIELD_NUMBER = <number>
 | 
	
		
			
				|  |  | -  for (int i = 0; i < message_descriptor->field_count(); ++i) {
 | 
	
		
			
				|  |  | -    if (!AddFieldNumberToClass(cls, message_descriptor->field(i))) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // For each enum set cls.<enum name> = EnumTypeWrapper(<enum descriptor>).
 | 
	
		
			
				|  |  | -  //
 | 
	
		
			
				|  |  | -  // The enum descriptor we get from
 | 
	
		
			
				|  |  | -  // <messagedescriptor>.enum_types_by_name[name]
 | 
	
		
			
				|  |  | -  // which was built previously.
 | 
	
		
			
				|  |  | -  for (int i = 0; i < message_descriptor->enum_type_count(); ++i) {
 | 
	
		
			
				|  |  | -    const EnumDescriptor* enum_descriptor = message_descriptor->enum_type(i);
 | 
	
		
			
				|  |  | -    ScopedPyObjectPtr enum_type(
 | 
	
		
			
				|  |  | -        PyEnumDescriptor_FromDescriptor(enum_descriptor));
 | 
	
		
			
				|  |  | -    if (enum_type == NULL) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -     }
 | 
	
		
			
				|  |  | -    // Add wrapped enum type to message class.
 | 
	
		
			
				|  |  | -    ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
 | 
	
		
			
				|  |  | -        EnumTypeWrapper_class, enum_type.get(), NULL));
 | 
	
		
			
				|  |  | -    if (wrapped == NULL) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (PyObject_SetAttrString(
 | 
	
		
			
				|  |  | -            cls, enum_descriptor->name().c_str(), wrapped) == -1) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // For each enum value add cls.<name> = <number>
 | 
	
		
			
				|  |  | -    for (int j = 0; j < enum_descriptor->value_count(); ++j) {
 | 
	
		
			
				|  |  | -      const EnumValueDescriptor* enum_value_descriptor =
 | 
	
		
			
				|  |  | -          enum_descriptor->value(j);
 | 
	
		
			
				|  |  | -      ScopedPyObjectPtr value_number(PyInt_FromLong(
 | 
	
		
			
				|  |  | -          enum_value_descriptor->number()));
 | 
	
		
			
				|  |  | -      if (value_number == NULL) {
 | 
	
		
			
				|  |  | -        return NULL;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      if (PyObject_SetAttrString(
 | 
	
		
			
				|  |  | -              cls, enum_value_descriptor->name().c_str(), value_number) == -1) {
 | 
	
		
			
				|  |  | -        return NULL;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // For each extension set cls.<extension name> = <extension descriptor>.
 | 
	
		
			
				|  |  | -  //
 | 
	
		
			
				|  |  | -  // Extension descriptors come from
 | 
	
		
			
				|  |  | -  // <message descriptor>.extensions_by_name[name]
 | 
	
		
			
				|  |  | -  // which was defined previously.
 | 
	
		
			
				|  |  | -  for (int i = 0; i < message_descriptor->extension_count(); ++i) {
 | 
	
		
			
				|  |  | -    const google::protobuf::FieldDescriptor* field = message_descriptor->extension(i);
 | 
	
		
			
				|  |  | -    ScopedPyObjectPtr extension_field(PyFieldDescriptor_FromDescriptor(field));
 | 
	
		
			
				|  |  | -    if (extension_field == NULL) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Add the extension field to the message class.
 | 
	
		
			
				|  |  | -    if (PyObject_SetAttrString(
 | 
	
		
			
				|  |  | -            cls, field->name().c_str(), extension_field) == -1) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // For each extension set cls.<extension name>_FIELD_NUMBER = <number>.
 | 
	
		
			
				|  |  | -    if (!AddFieldNumberToClass(cls, field)) {
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  Py_RETURN_NONE;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  PyObject* DeepCopy(CMessage* self, PyObject* arg) {
 | 
	
		
			
				|  |  |    PyObject* clone = PyObject_CallObject(
 | 
	
		
			
				|  |  |        reinterpret_cast<PyObject*>(Py_TYPE(self)), NULL);
 | 
	
	
		
			
				|  | @@ -2214,8 +2376,9 @@ PyObject* DeepCopy(CMessage* self, PyObject* arg) {
 | 
	
		
			
				|  |  |      Py_DECREF(clone);
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (MergeFrom(reinterpret_cast<CMessage*>(clone),
 | 
	
		
			
				|  |  | -                reinterpret_cast<PyObject*>(self)) == NULL) {
 | 
	
		
			
				|  |  | +  if (ScopedPyObjectPtr(MergeFrom(
 | 
	
		
			
				|  |  | +          reinterpret_cast<CMessage*>(clone),
 | 
	
		
			
				|  |  | +          reinterpret_cast<PyObject*>(self))) == NULL) {
 | 
	
		
			
				|  |  |      Py_DECREF(clone);
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -2281,7 +2444,7 @@ PyObject* SetState(CMessage* self, PyObject* state) {
 | 
	
		
			
				|  |  |    if (serialized == NULL) {
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (ParseFromString(self, serialized) == NULL) {
 | 
	
		
			
				|  |  | +  if (ScopedPyObjectPtr(ParseFromString(self, serialized)) == NULL) {
 | 
	
		
			
				|  |  |      return NULL;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    Py_RETURN_NONE;
 | 
	
	
		
			
				|  | @@ -2314,8 +2477,6 @@ static PyMethodDef Methods[] = {
 | 
	
		
			
				|  |  |      "Inputs picklable representation of the message." },
 | 
	
		
			
				|  |  |    { "__unicode__", (PyCFunction)ToUnicode, METH_NOARGS,
 | 
	
		
			
				|  |  |      "Outputs a unicode representation of the message." },
 | 
	
		
			
				|  |  | -  { "AddDescriptors", (PyCFunction)AddDescriptors, METH_O | METH_CLASS,
 | 
	
		
			
				|  |  | -    "Adds field descriptors to the class" },
 | 
	
		
			
				|  |  |    { "ByteSize", (PyCFunction)ByteSize, METH_NOARGS,
 | 
	
		
			
				|  |  |      "Returns the size of the message in bytes." },
 | 
	
		
			
				|  |  |    { "Clear", (PyCFunction)Clear, METH_NOARGS,
 | 
	
	
		
			
				|  | @@ -2441,6 +2602,9 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
 | 
	
		
			
				|  |  |      PyObject* sub_message = InternalGetSubMessage(self, field_descriptor);
 | 
	
		
			
				|  |  | +    if (sub_message == NULL) {
 | 
	
		
			
				|  |  | +      return NULL;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |      if (!SetCompositeField(self, name, sub_message)) {
 | 
	
		
			
				|  |  |        Py_DECREF(sub_message);
 | 
	
		
			
				|  |  |        return NULL;
 | 
	
	
		
			
				|  | @@ -2484,7 +2648,7 @@ int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
 | 
	
		
			
				|  |  |  }  // namespace cmessage
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  PyTypeObject CMessage_Type = {
 | 
	
		
			
				|  |  | -  PyVarObject_HEAD_INIT(&PyType_Type, 0)
 | 
	
		
			
				|  |  | +  PyVarObject_HEAD_INIT(&PyMessageMeta_Type, 0)
 | 
	
		
			
				|  |  |    FULL_MODULE_NAME ".CMessage",        // tp_name
 | 
	
		
			
				|  |  |    sizeof(CMessage),                    // tp_basicsize
 | 
	
		
			
				|  |  |    0,                                   //  tp_itemsize
 | 
	
	
		
			
				|  | @@ -2497,7 +2661,7 @@ PyTypeObject CMessage_Type = {
 | 
	
		
			
				|  |  |    0,                                   //  tp_as_number
 | 
	
		
			
				|  |  |    0,                                   //  tp_as_sequence
 | 
	
		
			
				|  |  |    0,                                   //  tp_as_mapping
 | 
	
		
			
				|  |  | -  0,                                   //  tp_hash
 | 
	
		
			
				|  |  | +  PyObject_HashNotImplemented,         //  tp_hash
 | 
	
		
			
				|  |  |    0,                                   //  tp_call
 | 
	
		
			
				|  |  |    (reprfunc)cmessage::ToStr,           //  tp_str
 | 
	
		
			
				|  |  |    (getattrofunc)cmessage::GetAttr,     //  tp_getattro
 | 
	
	
		
			
				|  | @@ -2580,8 +2744,9 @@ void InitGlobals() {
 | 
	
		
			
				|  |  |    k_extensions_by_name = PyString_FromString("_extensions_by_name");
 | 
	
		
			
				|  |  |    k_extensions_by_number = PyString_FromString("_extensions_by_number");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  message_factory = new DynamicMessageFactory();
 | 
	
		
			
				|  |  | -  message_factory->SetDelegateToGeneratedFactory(true);
 | 
	
		
			
				|  |  | +  PyObject *dummy_obj = PySet_New(NULL);
 | 
	
		
			
				|  |  | +  kEmptyWeakref = PyWeakref_NewRef(dummy_obj, NULL);
 | 
	
		
			
				|  |  | +  Py_DECREF(dummy_obj);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  bool InitProto2MessageModule(PyObject *m) {
 | 
	
	
		
			
				|  | @@ -2598,7 +2763,13 @@ bool InitProto2MessageModule(PyObject *m) {
 | 
	
		
			
				|  |  |    // Initialize constants defined in this file.
 | 
	
		
			
				|  |  |    InitGlobals();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  CMessage_Type.tp_hash = PyObject_HashNotImplemented;
 | 
	
		
			
				|  |  | +  PyMessageMeta_Type.tp_base = &PyType_Type;
 | 
	
		
			
				|  |  | +  if (PyType_Ready(&PyMessageMeta_Type) < 0) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  PyModule_AddObject(m, "MessageMeta",
 | 
	
		
			
				|  |  | +                     reinterpret_cast<PyObject*>(&PyMessageMeta_Type));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    if (PyType_Ready(&CMessage_Type) < 0) {
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -2628,86 +2799,106 @@ bool InitProto2MessageModule(PyObject *m) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(&CMessage_Type));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  RepeatedScalarContainer_Type.tp_hash =
 | 
	
		
			
				|  |  | -      PyObject_HashNotImplemented;
 | 
	
		
			
				|  |  | -  if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  // Initialize Repeated container types.
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +    if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  PyModule_AddObject(m, "RepeatedScalarContainer",
 | 
	
		
			
				|  |  | -                     reinterpret_cast<PyObject*>(
 | 
	
		
			
				|  |  | -                         &RepeatedScalarContainer_Type));
 | 
	
		
			
				|  |  | +    PyModule_AddObject(m, "RepeatedScalarContainer",
 | 
	
		
			
				|  |  | +                       reinterpret_cast<PyObject*>(
 | 
	
		
			
				|  |  | +                           &RepeatedScalarContainer_Type));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  RepeatedCompositeContainer_Type.tp_hash = PyObject_HashNotImplemented;
 | 
	
		
			
				|  |  | -  if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +    if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  PyModule_AddObject(
 | 
	
		
			
				|  |  | -      m, "RepeatedCompositeContainer",
 | 
	
		
			
				|  |  | -      reinterpret_cast<PyObject*>(
 | 
	
		
			
				|  |  | -          &RepeatedCompositeContainer_Type));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // ScalarMapContainer_Type derives from our MutableMapping type.
 | 
	
		
			
				|  |  | -  PyObject* containers =
 | 
	
		
			
				|  |  | -      PyImport_ImportModule("google.protobuf.internal.containers");
 | 
	
		
			
				|  |  | -  if (containers == NULL) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | +    PyModule_AddObject(
 | 
	
		
			
				|  |  | +        m, "RepeatedCompositeContainer",
 | 
	
		
			
				|  |  | +        reinterpret_cast<PyObject*>(
 | 
	
		
			
				|  |  | +            &RepeatedCompositeContainer_Type));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Register them as collections.Sequence
 | 
	
		
			
				|  |  | +    ScopedPyObjectPtr collections(PyImport_ImportModule("collections"));
 | 
	
		
			
				|  |  | +    if (collections == NULL) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    ScopedPyObjectPtr mutable_sequence(PyObject_GetAttrString(
 | 
	
		
			
				|  |  | +        collections, "MutableSequence"));
 | 
	
		
			
				|  |  | +    if (mutable_sequence == NULL) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (ScopedPyObjectPtr(PyObject_CallMethod(mutable_sequence, "register", "O",
 | 
	
		
			
				|  |  | +                                              &RepeatedScalarContainer_Type))
 | 
	
		
			
				|  |  | +        == NULL) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (ScopedPyObjectPtr(PyObject_CallMethod(mutable_sequence, "register", "O",
 | 
	
		
			
				|  |  | +                                              &RepeatedCompositeContainer_Type))
 | 
	
		
			
				|  |  | +        == NULL) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  PyObject* mutable_mapping =
 | 
	
		
			
				|  |  | -      PyObject_GetAttrString(containers, "MutableMapping");
 | 
	
		
			
				|  |  | -  Py_DECREF(containers);
 | 
	
		
			
				|  |  | +  // Initialize Map container types.
 | 
	
		
			
				|  |  | +  {
 | 
	
		
			
				|  |  | +    // ScalarMapContainer_Type derives from our MutableMapping type.
 | 
	
		
			
				|  |  | +    ScopedPyObjectPtr containers(PyImport_ImportModule(
 | 
	
		
			
				|  |  | +        "google.protobuf.internal.containers"));
 | 
	
		
			
				|  |  | +    if (containers == NULL) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (mutable_mapping == NULL) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +    ScopedPyObjectPtr mutable_mapping(
 | 
	
		
			
				|  |  | +        PyObject_GetAttrString(containers, "MutableMapping"));
 | 
	
		
			
				|  |  | +    if (mutable_mapping == NULL) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (!PyObject_TypeCheck(mutable_mapping, &PyType_Type)) {
 | 
	
		
			
				|  |  | -    Py_DECREF(mutable_mapping);
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +    if (!PyObject_TypeCheck(mutable_mapping, &PyType_Type)) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  ScalarMapContainer_Type.tp_base =
 | 
	
		
			
				|  |  | -      reinterpret_cast<PyTypeObject*>(mutable_mapping);
 | 
	
		
			
				|  |  | +    Py_INCREF(mutable_mapping);
 | 
	
		
			
				|  |  | +    ScalarMapContainer_Type.tp_base =
 | 
	
		
			
				|  |  | +        reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (PyType_Ready(&ScalarMapContainer_Type) < 0) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +    if (PyType_Ready(&ScalarMapContainer_Type) < 0) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  PyModule_AddObject(m, "ScalarMapContainer",
 | 
	
		
			
				|  |  | -                     reinterpret_cast<PyObject*>(&ScalarMapContainer_Type));
 | 
	
		
			
				|  |  | +    PyModule_AddObject(m, "ScalarMapContainer",
 | 
	
		
			
				|  |  | +                       reinterpret_cast<PyObject*>(&ScalarMapContainer_Type));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (PyType_Ready(&ScalarMapIterator_Type) < 0) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +    if (PyType_Ready(&ScalarMapIterator_Type) < 0) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  PyModule_AddObject(m, "ScalarMapIterator",
 | 
	
		
			
				|  |  | -                     reinterpret_cast<PyObject*>(&ScalarMapIterator_Type));
 | 
	
		
			
				|  |  | +    PyModule_AddObject(m, "ScalarMapIterator",
 | 
	
		
			
				|  |  | +                       reinterpret_cast<PyObject*>(&ScalarMapIterator_Type));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  Py_INCREF(mutable_mapping);
 | 
	
		
			
				|  |  | -  MessageMapContainer_Type.tp_base =
 | 
	
		
			
				|  |  | -      reinterpret_cast<PyTypeObject*>(mutable_mapping);
 | 
	
		
			
				|  |  | +    Py_INCREF(mutable_mapping);
 | 
	
		
			
				|  |  | +    MessageMapContainer_Type.tp_base =
 | 
	
		
			
				|  |  | +        reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (PyType_Ready(&MessageMapContainer_Type) < 0) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +    if (PyType_Ready(&MessageMapContainer_Type) < 0) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  PyModule_AddObject(m, "MessageMapContainer",
 | 
	
		
			
				|  |  | -                     reinterpret_cast<PyObject*>(&MessageMapContainer_Type));
 | 
	
		
			
				|  |  | +    PyModule_AddObject(m, "MessageMapContainer",
 | 
	
		
			
				|  |  | +                       reinterpret_cast<PyObject*>(&MessageMapContainer_Type));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (PyType_Ready(&MessageMapIterator_Type) < 0) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +    if (PyType_Ready(&MessageMapIterator_Type) < 0) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  PyModule_AddObject(m, "MessageMapIterator",
 | 
	
		
			
				|  |  | -                     reinterpret_cast<PyObject*>(&MessageMapIterator_Type));
 | 
	
		
			
				|  |  | +    PyModule_AddObject(m, "MessageMapIterator",
 | 
	
		
			
				|  |  | +                       reinterpret_cast<PyObject*>(&MessageMapIterator_Type));
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented;
 | 
	
		
			
				|  |  |    if (PyType_Ready(&ExtensionDict_Type) < 0) {
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |    PyModule_AddObject(
 | 
	
		
			
				|  |  |        m, "ExtensionDict",
 | 
	
		
			
				|  |  |        reinterpret_cast<PyObject*>(&ExtensionDict_Type));
 | 
	
	
		
			
				|  | @@ -2751,6 +2942,7 @@ bool InitProto2MessageModule(PyObject *m) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    EncodeError_class = PyObject_GetAttrString(message_module, "EncodeError");
 | 
	
		
			
				|  |  |    DecodeError_class = PyObject_GetAttrString(message_module, "DecodeError");
 | 
	
		
			
				|  |  | +  PythonMessage_class = PyObject_GetAttrString(message_module, "Message");
 | 
	
		
			
				|  |  |    Py_DECREF(message_module);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    PyObject* pickle_module = PyImport_ImportModule("pickle");
 |