Index: third_party/protobuf/python/google/protobuf/pyext/message.cc |
diff --git a/third_party/protobuf/python/google/protobuf/pyext/message.cc b/third_party/protobuf/python/google/protobuf/pyext/message.cc |
deleted file mode 100644 |
index a4843e8d3d1a1c6ad4e440abe07b23165003ef0a..0000000000000000000000000000000000000000 |
--- a/third_party/protobuf/python/google/protobuf/pyext/message.cc |
+++ /dev/null |
@@ -1,2815 +0,0 @@ |
-// Protocol Buffers - Google's data interchange format |
-// Copyright 2008 Google Inc. All rights reserved. |
-// https://developers.google.com/protocol-buffers/ |
-// |
-// Redistribution and use in source and binary forms, with or without |
-// modification, are permitted provided that the following conditions are |
-// met: |
-// |
-// * Redistributions of source code must retain the above copyright |
-// notice, this list of conditions and the following disclaimer. |
-// * Redistributions in binary form must reproduce the above |
-// copyright notice, this list of conditions and the following disclaimer |
-// in the documentation and/or other materials provided with the |
-// distribution. |
-// * Neither the name of Google Inc. nor the names of its |
-// contributors may be used to endorse or promote products derived from |
-// this software without specific prior written permission. |
-// |
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- |
-// Author: anuraag@google.com (Anuraag Agrawal) |
-// Author: tibell@google.com (Johan Tibell) |
- |
-#include <google/protobuf/pyext/message.h> |
- |
-#include <memory> |
-#ifndef _SHARED_PTR_H |
-#include <google/protobuf/stubs/shared_ptr.h> |
-#endif |
-#include <string> |
-#include <vector> |
-#include <structmember.h> // A Python header file. |
- |
-#ifndef PyVarObject_HEAD_INIT |
-#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, |
-#endif |
-#ifndef Py_TYPE |
-#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) |
-#endif |
-#include <google/protobuf/descriptor.pb.h> |
-#include <google/protobuf/stubs/common.h> |
-#include <google/protobuf/io/coded_stream.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> |
-#include <google/protobuf/pyext/descriptor_pool.h> |
-#include <google/protobuf/pyext/extension_dict.h> |
-#include <google/protobuf/pyext/repeated_composite_container.h> |
-#include <google/protobuf/pyext/repeated_scalar_container.h> |
-#include <google/protobuf/pyext/message_map_container.h> |
-#include <google/protobuf/pyext/scalar_map_container.h> |
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h> |
-#include <google/protobuf/stubs/strutil.h> |
- |
-#if PY_MAJOR_VERSION >= 3 |
- #define PyInt_Check PyLong_Check |
- #define PyInt_AsLong PyLong_AsLong |
- #define PyInt_FromLong PyLong_FromLong |
- #define PyInt_FromSize_t PyLong_FromSize_t |
- #define PyString_Check PyUnicode_Check |
- #define PyString_FromString PyUnicode_FromString |
- #define PyString_FromStringAndSize PyUnicode_FromStringAndSize |
- #if PY_VERSION_HEX < 0x03030000 |
- #error "Python 3.0 - 3.2 are not supported." |
- #else |
- #define PyString_AsString(ob) \ |
- (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob)) |
- #define PyString_AsStringAndSize(ob, charpp, sizep) \ |
- (PyUnicode_Check(ob)? \ |
- ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ |
- PyBytes_AsStringAndSize(ob, (charpp), (sizep))) |
- #endif |
-#endif |
- |
-namespace google { |
-namespace protobuf { |
-namespace python { |
- |
-// 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, |
- PyObject* composite_field); |
-} // namespace cmessage |
- |
-// --------------------------------------------------------------------- |
-// Visiting the composite children of a CMessage |
- |
-struct ChildVisitor { |
- // Returns 0 on success, -1 on failure. |
- int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { |
- return 0; |
- } |
- |
- // Returns 0 on success, -1 on failure. |
- int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { |
- return 0; |
- } |
- |
- // Returns 0 on success, -1 on failure. |
- int VisitCMessage(CMessage* cmessage, |
- const FieldDescriptor* field_descriptor) { |
- return 0; |
- } |
-}; |
- |
-// Apply a function to a composite field. Does nothing if child is of |
-// non-composite type. |
-template<class Visitor> |
-static int VisitCompositeField(const FieldDescriptor* descriptor, |
- PyObject* child, |
- Visitor visitor) { |
- if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { |
- if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- if (descriptor->is_map()) { |
- const Descriptor* entry_type = descriptor->message_type(); |
- const FieldDescriptor* value_type = |
- entry_type->FindFieldByName("value"); |
- if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- MessageMapContainer* container = |
- reinterpret_cast<MessageMapContainer*>(child); |
- if (visitor.VisitMessageMapContainer(container) == -1) { |
- return -1; |
- } |
- } else { |
- ScalarMapContainer* container = |
- reinterpret_cast<ScalarMapContainer*>(child); |
- if (visitor.VisitScalarMapContainer(container) == -1) { |
- return -1; |
- } |
- } |
- } else { |
- RepeatedCompositeContainer* container = |
- reinterpret_cast<RepeatedCompositeContainer*>(child); |
- if (visitor.VisitRepeatedCompositeContainer(container) == -1) |
- return -1; |
- } |
- } else { |
- RepeatedScalarContainer* container = |
- reinterpret_cast<RepeatedScalarContainer*>(child); |
- if (visitor.VisitRepeatedScalarContainer(container) == -1) |
- return -1; |
- } |
- } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- CMessage* cmsg = reinterpret_cast<CMessage*>(child); |
- if (visitor.VisitCMessage(cmsg, descriptor) == -1) |
- return -1; |
- } |
- // The ExtensionDict might contain non-composite fields, which we |
- // skip here. |
- return 0; |
-} |
- |
-// Visit each composite field and extension field of this CMessage. |
-// Returns -1 on error and 0 on success. |
-template<class Visitor> |
-int ForEachCompositeField(CMessage* self, Visitor visitor) { |
- Py_ssize_t pos = 0; |
- PyObject* key; |
- PyObject* field; |
- |
- // Visit normal fields. |
- 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)); |
- while (PyDict_Next(self->composite_fields, &pos, &key, &field)) { |
- Py_ssize_t key_str_size; |
- char *key_str_data; |
- if (PyString_AsStringAndSize(key, &key_str_data, &key_str_size) != 0) |
- return -1; |
- const string key_str(key_str_data, key_str_size); |
- const FieldDescriptor* descriptor = |
- message_descriptor->FindFieldByName(key_str); |
- if (descriptor != NULL) { |
- if (VisitCompositeField(descriptor, field, visitor) == -1) |
- return -1; |
- } |
- } |
- } |
- |
- // Visit extension fields. |
- if (self->extensions != NULL) { |
- pos = 0; |
- while (PyDict_Next(self->extensions->values, &pos, &key, &field)) { |
- const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key); |
- if (descriptor == NULL) |
- return -1; |
- if (VisitCompositeField(descriptor, field, visitor) == -1) |
- return -1; |
- } |
- } |
- |
- return 0; |
-} |
- |
-// --------------------------------------------------------------------- |
- |
-static DynamicMessageFactory* message_factory; |
- |
-// Constants used for integer type range checking. |
-PyObject* kPythonZero; |
-PyObject* kint32min_py; |
-PyObject* kint32max_py; |
-PyObject* kuint32max_py; |
-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) { |
- PyObject* repr = PyObject_Repr(arg); |
- if (repr) { |
- PyErr_Format(PyExc_TypeError, |
- "%.100s has type %.100s, but expected one of: %s", |
- PyString_AsString(repr), |
- Py_TYPE(arg)->tp_name, |
- expected_types); |
- Py_DECREF(repr); |
- } |
-} |
- |
-template<class T> |
-bool CheckAndGetInteger( |
- PyObject* arg, T* value, PyObject* min, PyObject* max) { |
- bool is_long = PyLong_Check(arg); |
-#if PY_MAJOR_VERSION < 3 |
- if (!PyInt_Check(arg) && !is_long) { |
- FormatTypeError(arg, "int, long"); |
- return false; |
- } |
- if (PyObject_Compare(min, arg) > 0 || PyObject_Compare(max, arg) < 0) { |
-#else |
- if (!is_long) { |
- FormatTypeError(arg, "int"); |
- return false; |
- } |
- if (PyObject_RichCompareBool(min, arg, Py_LE) != 1 || |
- PyObject_RichCompareBool(max, arg, Py_GE) != 1) { |
-#endif |
- PyObject *s = PyObject_Str(arg); |
- if (s) { |
- PyErr_Format(PyExc_ValueError, |
- "Value out of range: %s", |
- PyString_AsString(s)); |
- Py_DECREF(s); |
- } |
- return false; |
- } |
-#if PY_MAJOR_VERSION < 3 |
- if (!is_long) { |
- *value = static_cast<T>(PyInt_AsLong(arg)); |
- } else // NOLINT |
-#endif |
- { |
- if (min == kPythonZero) { |
- *value = static_cast<T>(PyLong_AsUnsignedLongLong(arg)); |
- } else { |
- *value = static_cast<T>(PyLong_AsLongLong(arg)); |
- } |
- } |
- return true; |
-} |
- |
-// These are referenced by repeated_scalar_container, and must |
-// be explicitly instantiated. |
-template bool CheckAndGetInteger<int32>( |
- PyObject*, int32*, PyObject*, PyObject*); |
-template bool CheckAndGetInteger<int64>( |
- PyObject*, int64*, PyObject*, PyObject*); |
-template bool CheckAndGetInteger<uint32>( |
- PyObject*, uint32*, PyObject*, PyObject*); |
-template bool CheckAndGetInteger<uint64>( |
- PyObject*, uint64*, PyObject*, PyObject*); |
- |
-bool CheckAndGetDouble(PyObject* arg, double* value) { |
- if (!PyInt_Check(arg) && !PyLong_Check(arg) && |
- !PyFloat_Check(arg)) { |
- FormatTypeError(arg, "int, long, float"); |
- return false; |
- } |
- *value = PyFloat_AsDouble(arg); |
- return true; |
-} |
- |
-bool CheckAndGetFloat(PyObject* arg, float* value) { |
- double double_value; |
- if (!CheckAndGetDouble(arg, &double_value)) { |
- return false; |
- } |
- *value = static_cast<float>(double_value); |
- return true; |
-} |
- |
-bool CheckAndGetBool(PyObject* arg, bool* value) { |
- if (!PyInt_Check(arg) && !PyBool_Check(arg) && !PyLong_Check(arg)) { |
- FormatTypeError(arg, "int, long, bool"); |
- return false; |
- } |
- *value = static_cast<bool>(PyInt_AsLong(arg)); |
- return true; |
-} |
- |
-bool CheckAndSetString( |
- PyObject* arg, Message* message, |
- const FieldDescriptor* descriptor, |
- const Reflection* reflection, |
- bool append, |
- int index) { |
- GOOGLE_DCHECK(descriptor->type() == FieldDescriptor::TYPE_STRING || |
- descriptor->type() == FieldDescriptor::TYPE_BYTES); |
- if (descriptor->type() == FieldDescriptor::TYPE_STRING) { |
- if (!PyBytes_Check(arg) && !PyUnicode_Check(arg)) { |
- FormatTypeError(arg, "bytes, unicode"); |
- return false; |
- } |
- |
- if (PyBytes_Check(arg)) { |
- PyObject* unicode = PyUnicode_FromEncodedObject(arg, "utf-8", NULL); |
- if (unicode == NULL) { |
- PyObject* repr = PyObject_Repr(arg); |
- PyErr_Format(PyExc_ValueError, |
- "%s has type str, but isn't valid UTF-8 " |
- "encoding. Non-UTF-8 strings must be converted to " |
- "unicode objects before being added.", |
- PyString_AsString(repr)); |
- Py_DECREF(repr); |
- return false; |
- } else { |
- Py_DECREF(unicode); |
- } |
- } |
- } else if (!PyBytes_Check(arg)) { |
- FormatTypeError(arg, "bytes"); |
- return false; |
- } |
- |
- PyObject* encoded_string = NULL; |
- if (descriptor->type() == FieldDescriptor::TYPE_STRING) { |
- if (PyBytes_Check(arg)) { |
- // The bytes were already validated as correctly encoded UTF-8 above. |
- encoded_string = arg; // Already encoded. |
- Py_INCREF(encoded_string); |
- } else { |
- encoded_string = PyUnicode_AsEncodedObject(arg, "utf-8", NULL); |
- } |
- } else { |
- // In this case field type is "bytes". |
- encoded_string = arg; |
- Py_INCREF(encoded_string); |
- } |
- |
- if (encoded_string == NULL) { |
- return false; |
- } |
- |
- char* value; |
- Py_ssize_t value_len; |
- if (PyBytes_AsStringAndSize(encoded_string, &value, &value_len) < 0) { |
- Py_DECREF(encoded_string); |
- return false; |
- } |
- |
- string value_string(value, value_len); |
- if (append) { |
- reflection->AddString(message, descriptor, value_string); |
- } else if (index < 0) { |
- reflection->SetString(message, descriptor, value_string); |
- } else { |
- reflection->SetRepeatedString(message, descriptor, index, value_string); |
- } |
- Py_DECREF(encoded_string); |
- return true; |
-} |
- |
-PyObject* ToStringObject(const FieldDescriptor* descriptor, string value) { |
- if (descriptor->type() != FieldDescriptor::TYPE_STRING) { |
- return PyBytes_FromStringAndSize(value.c_str(), value.length()); |
- } |
- |
- PyObject* result = PyUnicode_DecodeUTF8(value.c_str(), value.length(), NULL); |
- // If the string can't be decoded in UTF-8, just return a string object that |
- // contains the raw bytes. This can't happen if the value was assigned using |
- // the members of the Python message object, but can happen if the values were |
- // parsed from the wire (binary). |
- if (result == NULL) { |
- PyErr_Clear(); |
- result = PyBytes_FromStringAndSize(value.c_str(), value.length()); |
- } |
- return result; |
-} |
- |
-bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor, |
- const Message* message) { |
- if (message->GetDescriptor() == field_descriptor->containing_type()) { |
- return true; |
- } |
- PyErr_Format(PyExc_KeyError, "Field '%s' does not belong to message '%s'", |
- field_descriptor->full_name().c_str(), |
- message->GetDescriptor()->full_name().c_str()); |
- return false; |
-} |
- |
-namespace cmessage { |
- |
-DynamicMessageFactory* GetMessageFactory() { |
- return message_factory; |
-} |
- |
-static int MaybeReleaseOverlappingOneofField( |
- CMessage* cmessage, |
- const FieldDescriptor* field) { |
-#ifdef GOOGLE_PROTOBUF_HAS_ONEOF |
- Message* message = cmessage->message; |
- const Reflection* reflection = message->GetReflection(); |
- if (!field->containing_oneof() || |
- !reflection->HasOneof(*message, field->containing_oneof()) || |
- reflection->HasField(*message, field)) { |
- // No other field in this oneof, no need to release. |
- return 0; |
- } |
- |
- const OneofDescriptor* oneof = field->containing_oneof(); |
- const FieldDescriptor* existing_field = |
- reflection->GetOneofFieldDescriptor(*message, oneof); |
- if (existing_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { |
- // Non-message fields don't need to be released. |
- return 0; |
- } |
- const char* field_name = existing_field->name().c_str(); |
- PyObject* child_message = cmessage->composite_fields ? |
- PyDict_GetItemString(cmessage->composite_fields, field_name) : NULL; |
- if (child_message == NULL) { |
- // No python reference to this field so no need to release. |
- return 0; |
- } |
- |
- if (InternalReleaseFieldByDescriptor( |
- cmessage, existing_field, child_message) < 0) { |
- return -1; |
- } |
- return PyDict_DelItemString(cmessage->composite_fields, field_name); |
-#else |
- return 0; |
-#endif |
-} |
- |
-// --------------------------------------------------------------------- |
-// Making a message writable |
- |
-static Message* GetMutableMessage( |
- CMessage* parent, |
- const FieldDescriptor* parent_field) { |
- Message* parent_message = parent->message; |
- const Reflection* reflection = parent_message->GetReflection(); |
- if (MaybeReleaseOverlappingOneofField(parent, parent_field) < 0) { |
- return NULL; |
- } |
- return reflection->MutableMessage( |
- parent_message, parent_field, message_factory); |
-} |
- |
-struct FixupMessageReference : public ChildVisitor { |
- // message must outlive this object. |
- explicit FixupMessageReference(Message* message) : |
- message_(message) {} |
- |
- int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { |
- container->message = message_; |
- return 0; |
- } |
- |
- int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { |
- container->message = message_; |
- return 0; |
- } |
- |
- int VisitScalarMapContainer(ScalarMapContainer* container) { |
- container->message = message_; |
- return 0; |
- } |
- |
- int VisitMessageMapContainer(MessageMapContainer* container) { |
- container->message = message_; |
- return 0; |
- } |
- |
- private: |
- Message* message_; |
-}; |
- |
-int AssureWritable(CMessage* self) { |
- if (self == NULL || !self->read_only) { |
- return 0; |
- } |
- |
- if (self->parent == NULL) { |
- // 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()); |
- self->message = prototype->New(); |
- self->owner.reset(self->message); |
- // Cascade the new owner to eventual children: even if this message is |
- // empty, some submessages or repeated containers might exist already. |
- SetOwner(self, self->owner); |
- } else { |
- // Otherwise, we need a mutable child message. |
- if (AssureWritable(self->parent) == -1) |
- return -1; |
- |
- // Make self->message writable. |
- Message* parent_message = self->parent->message; |
- Message* mutable_message = GetMutableMessage( |
- self->parent, |
- self->parent_field_descriptor); |
- if (mutable_message == NULL) { |
- return -1; |
- } |
- self->message = mutable_message; |
- } |
- self->read_only = false; |
- |
- // When a CMessage is made writable its Message pointer is updated |
- // to point to a new mutable Message. When that happens we need to |
- // update any references to the old, read-only CMessage. There are |
- // five places such references occur: RepeatedScalarContainer, |
- // RepeatedCompositeContainer, ScalarMapContainer, MessageMapContainer, |
- // and ExtensionDict. |
- if (self->extensions != NULL) |
- self->extensions->message = self->message; |
- if (ForEachCompositeField(self, FixupMessageReference(self->message)) == -1) |
- return -1; |
- |
- return 0; |
-} |
- |
-// --- 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 |
-// handling is not consistent. |
-static const FieldDescriptor* GetFieldDescriptor( |
- CMessage* self, PyObject* name) { |
- const Descriptor *message_descriptor = self->message->GetDescriptor(); |
- char* field_name; |
- Py_ssize_t size; |
- if (PyString_AsStringAndSize(name, &field_name, &size) < 0) { |
- return NULL; |
- } |
- const FieldDescriptor *field_descriptor = |
- message_descriptor->FindFieldByName(string(field_name, size)); |
- if (field_descriptor == NULL) { |
- // Note: No exception is set! |
- return NULL; |
- } |
- return field_descriptor; |
-} |
- |
-// Retrieve a C++ FieldDescriptor for an extension handle. |
-const FieldDescriptor* GetExtensionDescriptor(PyObject* extension) { |
- ScopedPyObjectPtr cdescriptor; |
- if (!PyObject_TypeCheck(extension, &PyFieldDescriptor_Type)) { |
- // Most callers consider extensions as a plain dictionary. We should |
- // allow input which is not a field descriptor, and simply pretend it does |
- // not exist. |
- PyErr_SetObject(PyExc_KeyError, extension); |
- return NULL; |
- } |
- return PyFieldDescriptor_AsDescriptor(extension); |
-} |
- |
-// If value is a string, convert it into an enum value based on the labels in |
-// descriptor, otherwise simply return value. Always returns a new reference. |
-static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor, |
- PyObject* value) { |
- if (PyString_Check(value) || PyUnicode_Check(value)) { |
- const EnumDescriptor* enum_descriptor = descriptor.enum_type(); |
- if (enum_descriptor == NULL) { |
- PyErr_SetString(PyExc_TypeError, "not an enum field"); |
- return NULL; |
- } |
- char* enum_label; |
- Py_ssize_t size; |
- if (PyString_AsStringAndSize(value, &enum_label, &size) < 0) { |
- return NULL; |
- } |
- const EnumValueDescriptor* enum_value_descriptor = |
- enum_descriptor->FindValueByName(string(enum_label, size)); |
- if (enum_value_descriptor == NULL) { |
- PyErr_SetString(PyExc_ValueError, "unknown enum label"); |
- return NULL; |
- } |
- return PyInt_FromLong(enum_value_descriptor->number()); |
- } |
- Py_INCREF(value); |
- return value; |
-} |
- |
-// If cmessage_list is not NULL, this function releases values into the |
-// container CMessages instead of just removing. Repeated composite container |
-// needs to do this to make sure CMessages stay alive if they're still |
-// referenced after deletion. Repeated scalar container doesn't need to worry. |
-int InternalDeleteRepeatedField( |
- CMessage* self, |
- const FieldDescriptor* field_descriptor, |
- PyObject* slice, |
- PyObject* cmessage_list) { |
- Message* message = self->message; |
- Py_ssize_t length, from, to, step, slice_length; |
- const Reflection* reflection = message->GetReflection(); |
- int min, max; |
- length = reflection->FieldSize(*message, field_descriptor); |
- |
- if (PyInt_Check(slice) || PyLong_Check(slice)) { |
- from = to = PyLong_AsLong(slice); |
- if (from < 0) { |
- from = to = length + from; |
- } |
- step = 1; |
- min = max = from; |
- |
- // Range check. |
- if (from < 0 || from >= length) { |
- PyErr_Format(PyExc_IndexError, "list assignment index out of range"); |
- return -1; |
- } |
- } else if (PySlice_Check(slice)) { |
- from = to = step = slice_length = 0; |
- PySlice_GetIndicesEx( |
-#if PY_MAJOR_VERSION < 3 |
- reinterpret_cast<PySliceObject*>(slice), |
-#else |
- slice, |
-#endif |
- length, &from, &to, &step, &slice_length); |
- if (from < to) { |
- min = from; |
- max = to - 1; |
- } else { |
- min = to + 1; |
- max = from; |
- } |
- } else { |
- PyErr_SetString(PyExc_TypeError, "list indices must be integers"); |
- return -1; |
- } |
- |
- Py_ssize_t i = from; |
- std::vector<bool> to_delete(length, false); |
- while (i >= min && i <= max) { |
- to_delete[i] = true; |
- i += step; |
- } |
- |
- to = 0; |
- for (i = 0; i < length; ++i) { |
- if (!to_delete[i]) { |
- if (i != to) { |
- reflection->SwapElements(message, field_descriptor, i, to); |
- if (cmessage_list != NULL) { |
- // If a list of cmessages is passed in (i.e. from a repeated |
- // composite container), swap those as well to correspond to the |
- // swaps in the underlying message so they're in the right order |
- // when we start releasing. |
- PyObject* tmp = PyList_GET_ITEM(cmessage_list, i); |
- PyList_SET_ITEM(cmessage_list, i, |
- PyList_GET_ITEM(cmessage_list, to)); |
- PyList_SET_ITEM(cmessage_list, to, tmp); |
- } |
- } |
- ++to; |
- } |
- } |
- |
- while (i > to) { |
- if (cmessage_list == NULL) { |
- reflection->RemoveLast(message, field_descriptor); |
- } else { |
- CMessage* last_cmessage = reinterpret_cast<CMessage*>( |
- PyList_GET_ITEM(cmessage_list, PyList_GET_SIZE(cmessage_list) - 1)); |
- repeated_composite_container::ReleaseLastTo( |
- self, field_descriptor, last_cmessage); |
- if (PySequence_DelItem(cmessage_list, -1) < 0) { |
- return -1; |
- } |
- } |
- --i; |
- } |
- |
- return 0; |
-} |
- |
-// Initializes fields of a message. Used in constructors. |
-int InitAttributes(CMessage* self, PyObject* kwargs) { |
- if (kwargs == NULL) { |
- return 0; |
- } |
- |
- Py_ssize_t pos = 0; |
- PyObject* name; |
- PyObject* value; |
- while (PyDict_Next(kwargs, &pos, &name, &value)) { |
- if (!PyString_Check(name)) { |
- PyErr_SetString(PyExc_ValueError, "Field name must be a string"); |
- return -1; |
- } |
- const FieldDescriptor* descriptor = GetFieldDescriptor(self, name); |
- if (descriptor == NULL) { |
- PyErr_Format(PyExc_ValueError, "Protocol message has no \"%s\" field.", |
- PyString_AsString(name)); |
- return -1; |
- } |
- if (descriptor->is_map()) { |
- ScopedPyObjectPtr map(GetAttr(self, name)); |
- const FieldDescriptor* value_descriptor = |
- descriptor->message_type()->FindFieldByName("value"); |
- if (value_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- Py_ssize_t map_pos = 0; |
- PyObject* map_key; |
- PyObject* map_value; |
- while (PyDict_Next(value, &map_pos, &map_key, &map_value)) { |
- ScopedPyObjectPtr function_return; |
- function_return.reset(PyObject_GetItem(map.get(), map_key)); |
- if (function_return.get() == NULL) { |
- return -1; |
- } |
- ScopedPyObjectPtr ok(PyObject_CallMethod( |
- function_return.get(), "MergeFrom", "O", map_value)); |
- if (ok.get() == NULL) { |
- return -1; |
- } |
- } |
- } else { |
- ScopedPyObjectPtr function_return; |
- function_return.reset( |
- PyObject_CallMethod(map.get(), "update", "O", value)); |
- if (function_return.get() == NULL) { |
- return -1; |
- } |
- } |
- } else if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { |
- ScopedPyObjectPtr container(GetAttr(self, name)); |
- if (container == NULL) { |
- return -1; |
- } |
- if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- RepeatedCompositeContainer* rc_container = |
- reinterpret_cast<RepeatedCompositeContainer*>(container.get()); |
- ScopedPyObjectPtr iter(PyObject_GetIter(value)); |
- if (iter == NULL) { |
- PyErr_SetString(PyExc_TypeError, "Value must be iterable"); |
- return -1; |
- } |
- ScopedPyObjectPtr next; |
- while ((next.reset(PyIter_Next(iter))) != NULL) { |
- PyObject* kwargs = (PyDict_Check(next) ? next.get() : NULL); |
- ScopedPyObjectPtr new_msg( |
- repeated_composite_container::Add(rc_container, NULL, kwargs)); |
- if (new_msg == NULL) { |
- return -1; |
- } |
- if (kwargs == NULL) { |
- // next was not a dict, it's a message we need to merge |
- ScopedPyObjectPtr merged( |
- MergeFrom(reinterpret_cast<CMessage*>(new_msg.get()), next)); |
- if (merged == NULL) { |
- return -1; |
- } |
- } |
- } |
- if (PyErr_Occurred()) { |
- // Check to see how PyIter_Next() exited. |
- return -1; |
- } |
- } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { |
- RepeatedScalarContainer* rs_container = |
- reinterpret_cast<RepeatedScalarContainer*>(container.get()); |
- ScopedPyObjectPtr iter(PyObject_GetIter(value)); |
- if (iter == NULL) { |
- PyErr_SetString(PyExc_TypeError, "Value must be iterable"); |
- return -1; |
- } |
- ScopedPyObjectPtr next; |
- while ((next.reset(PyIter_Next(iter))) != NULL) { |
- ScopedPyObjectPtr enum_value(GetIntegerEnumValue(*descriptor, next)); |
- if (enum_value == NULL) { |
- return -1; |
- } |
- ScopedPyObjectPtr new_msg( |
- repeated_scalar_container::Append(rs_container, enum_value)); |
- if (new_msg == NULL) { |
- return -1; |
- } |
- } |
- if (PyErr_Occurred()) { |
- // Check to see how PyIter_Next() exited. |
- return -1; |
- } |
- } else { |
- if (repeated_scalar_container::Extend( |
- reinterpret_cast<RepeatedScalarContainer*>(container.get()), |
- value) == |
- NULL) { |
- return -1; |
- } |
- } |
- } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- ScopedPyObjectPtr message(GetAttr(self, name)); |
- if (message == NULL) { |
- return -1; |
- } |
- CMessage* cmessage = reinterpret_cast<CMessage*>(message.get()); |
- if (PyDict_Check(value)) { |
- if (InitAttributes(cmessage, value) < 0) { |
- return -1; |
- } |
- } else { |
- ScopedPyObjectPtr merged(MergeFrom(cmessage, value)); |
- if (merged == NULL) { |
- return -1; |
- } |
- } |
- } else { |
- ScopedPyObjectPtr new_val; |
- if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { |
- new_val.reset(GetIntegerEnumValue(*descriptor, value)); |
- if (new_val == NULL) { |
- return -1; |
- } |
- } |
- if (SetAttr(self, name, (new_val == NULL) ? value : new_val) < 0) { |
- return -1; |
- } |
- } |
- } |
- return 0; |
-} |
- |
-// Allocates an incomplete Python Message: the caller must fill self->message, |
-// self->owner and eventually self->parent. |
-CMessage* NewEmptyMessage(PyObject* type, const Descriptor *descriptor) { |
- CMessage* self = reinterpret_cast<CMessage*>( |
- PyType_GenericAlloc(reinterpret_cast<PyTypeObject*>(type), 0)); |
- if (self == NULL) { |
- return NULL; |
- } |
- |
- self->message = NULL; |
- self->parent = NULL; |
- self->parent_field_descriptor = NULL; |
- self->read_only = false; |
- self->extensions = NULL; |
- |
- self->composite_fields = NULL; |
- |
- // If there are extension_ranges, the message is "extendable". Allocate a |
- // dictionary to store the extension fields. |
- if (descriptor->extension_range_count() > 0) { |
- // TODO(amauryfa): Delay the construction of this dict until extensions are |
- // really used on the object. |
- ExtensionDict* extension_dict = extension_dict::NewExtensionDict(self); |
- if (extension_dict == NULL) { |
- return NULL; |
- } |
- self->extensions = extension_dict; |
- } |
- |
- return self; |
-} |
- |
-// The __new__ method of Message classes. |
-// Creates a new C++ message and takes ownership. |
-static PyObject* New(PyTypeObject* type, |
- PyObject* unused_args, PyObject* unused_kwargs) { |
- // Retrieve the message descriptor and the default instance (=prototype). |
- const Descriptor* message_descriptor = GetMessageDescriptor(type); |
- if (message_descriptor == NULL) { |
- return NULL; |
- } |
- const Message* default_message = |
- message_factory->GetPrototype(message_descriptor); |
- if (default_message == NULL) { |
- PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str()); |
- return NULL; |
- } |
- |
- CMessage* self = NewEmptyMessage(reinterpret_cast<PyObject*>(type), |
- message_descriptor); |
- if (self == NULL) { |
- return NULL; |
- } |
- self->message = default_message->New(); |
- self->owner.reset(self->message); |
- return reinterpret_cast<PyObject*>(self); |
-} |
- |
-// The __init__ method of Message classes. |
-// It initializes fields from keywords passed to the constructor. |
-static int Init(CMessage* self, PyObject* args, PyObject* kwargs) { |
- if (PyTuple_Size(args) != 0) { |
- PyErr_SetString(PyExc_TypeError, "No positional arguments allowed"); |
- return -1; |
- } |
- |
- return InitAttributes(self, kwargs); |
-} |
- |
-// --------------------------------------------------------------------- |
-// Deallocating a CMessage |
-// |
-// Deallocating a CMessage requires that we clear any weak references |
-// from children to the message being deallocated. |
- |
-// Clear the weak reference from the child to the parent. |
-struct ClearWeakReferences : public ChildVisitor { |
- int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { |
- container->parent = NULL; |
- // The elements in the container have the same parent as the |
- // container itself, so NULL out that pointer as well. |
- const Py_ssize_t n = PyList_GET_SIZE(container->child_messages); |
- for (Py_ssize_t i = 0; i < n; ++i) { |
- CMessage* child_cmessage = reinterpret_cast<CMessage*>( |
- PyList_GET_ITEM(container->child_messages, i)); |
- child_cmessage->parent = NULL; |
- } |
- return 0; |
- } |
- |
- int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { |
- container->parent = NULL; |
- return 0; |
- } |
- |
- int VisitScalarMapContainer(ScalarMapContainer* container) { |
- container->parent = NULL; |
- return 0; |
- } |
- |
- int VisitMessageMapContainer(MessageMapContainer* container) { |
- container->parent = NULL; |
- return 0; |
- } |
- |
- int VisitCMessage(CMessage* cmessage, |
- const FieldDescriptor* field_descriptor) { |
- cmessage->parent = NULL; |
- return 0; |
- } |
-}; |
- |
-static void Dealloc(CMessage* self) { |
- // Null out all weak references from children to this message. |
- GOOGLE_CHECK_EQ(0, ForEachCompositeField(self, ClearWeakReferences())); |
- |
- Py_CLEAR(self->extensions); |
- Py_CLEAR(self->composite_fields); |
- self->owner.reset(); |
- Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); |
-} |
- |
-// --------------------------------------------------------------------- |
- |
- |
-PyObject* IsInitialized(CMessage* self, PyObject* args) { |
- PyObject* errors = NULL; |
- if (PyArg_ParseTuple(args, "|O", &errors) < 0) { |
- return NULL; |
- } |
- if (self->message->IsInitialized()) { |
- Py_RETURN_TRUE; |
- } |
- if (errors != NULL) { |
- ScopedPyObjectPtr initialization_errors( |
- FindInitializationErrors(self)); |
- if (initialization_errors == NULL) { |
- return NULL; |
- } |
- ScopedPyObjectPtr extend_name(PyString_FromString("extend")); |
- if (extend_name == NULL) { |
- return NULL; |
- } |
- ScopedPyObjectPtr result(PyObject_CallMethodObjArgs( |
- errors, |
- extend_name.get(), |
- initialization_errors.get(), |
- NULL)); |
- if (result == NULL) { |
- return NULL; |
- } |
- } |
- Py_RETURN_FALSE; |
-} |
- |
-PyObject* HasFieldByDescriptor( |
- CMessage* self, const FieldDescriptor* field_descriptor) { |
- Message* message = self->message; |
- if (!CheckFieldBelongsToMessage(field_descriptor, message)) { |
- return NULL; |
- } |
- if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { |
- PyErr_SetString(PyExc_KeyError, |
- "Field is repeated. A singular method is required."); |
- return NULL; |
- } |
- bool has_field = |
- message->GetReflection()->HasField(*message, field_descriptor); |
- return PyBool_FromLong(has_field ? 1 : 0); |
-} |
- |
-const FieldDescriptor* FindFieldWithOneofs( |
- const Message* message, const string& field_name, bool* in_oneof) { |
- *in_oneof = false; |
- const Descriptor* descriptor = message->GetDescriptor(); |
- const FieldDescriptor* field_descriptor = |
- descriptor->FindFieldByName(field_name); |
- if (field_descriptor != NULL) { |
- return field_descriptor; |
- } |
- const OneofDescriptor* oneof_desc = |
- descriptor->FindOneofByName(field_name); |
- if (oneof_desc != NULL) { |
- *in_oneof = true; |
- return message->GetReflection()->GetOneofFieldDescriptor(*message, |
- oneof_desc); |
- } |
- return NULL; |
-} |
- |
-bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) { |
- if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { |
- PyErr_Format(PyExc_ValueError, |
- "Protocol message has no singular \"%s\" field.", |
- field_descriptor->name().c_str()); |
- return false; |
- } |
- |
- if (field_descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { |
- // HasField() for a oneof *itself* isn't supported. |
- if (in_oneof) { |
- PyErr_Format(PyExc_ValueError, |
- "Can't test oneof field \"%s\" for presence in proto3, use " |
- "WhichOneof instead.", |
- field_descriptor->containing_oneof()->name().c_str()); |
- return false; |
- } |
- |
- // ...but HasField() for fields *in* a oneof is supported. |
- if (field_descriptor->containing_oneof() != NULL) { |
- return true; |
- } |
- |
- if (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { |
- PyErr_Format( |
- PyExc_ValueError, |
- "Can't test non-submessage field \"%s\" for presence in proto3.", |
- field_descriptor->name().c_str()); |
- return false; |
- } |
- } |
- |
- return true; |
-} |
- |
-PyObject* HasField(CMessage* self, PyObject* arg) { |
- char* field_name; |
- Py_ssize_t size; |
-#if PY_MAJOR_VERSION < 3 |
- if (PyString_AsStringAndSize(arg, &field_name, &size) < 0) { |
- return NULL; |
- } |
-#else |
- field_name = PyUnicode_AsUTF8AndSize(arg, &size); |
- if (!field_name) { |
- return NULL; |
- } |
-#endif |
- |
- Message* message = self->message; |
- bool is_in_oneof; |
- const FieldDescriptor* field_descriptor = |
- FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof); |
- if (field_descriptor == NULL) { |
- if (!is_in_oneof) { |
- PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name); |
- return NULL; |
- } else { |
- Py_RETURN_FALSE; |
- } |
- } |
- |
- if (!CheckHasPresence(field_descriptor, is_in_oneof)) { |
- return NULL; |
- } |
- |
- if (message->GetReflection()->HasField(*message, field_descriptor)) { |
- Py_RETURN_TRUE; |
- } |
- if (!message->GetReflection()->SupportsUnknownEnumValues() && |
- field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { |
- // Special case: Python HasField() differs in semantics from C++ |
- // slightly: we return HasField('enum_field') == true if there is |
- // an unknown enum value present. To implement this we have to |
- // look in the UnknownFieldSet. |
- const UnknownFieldSet& unknown_field_set = |
- message->GetReflection()->GetUnknownFields(*message); |
- for (int i = 0; i < unknown_field_set.field_count(); ++i) { |
- if (unknown_field_set.field(i).number() == field_descriptor->number()) { |
- Py_RETURN_TRUE; |
- } |
- } |
- } |
- Py_RETURN_FALSE; |
-} |
- |
-PyObject* ClearExtension(CMessage* self, PyObject* arg) { |
- if (self->extensions != NULL) { |
- return extension_dict::ClearExtension(self->extensions, arg); |
- } |
- PyErr_SetString(PyExc_TypeError, "Message is not extendable"); |
- return NULL; |
-} |
- |
-PyObject* HasExtension(CMessage* self, PyObject* arg) { |
- if (self->extensions != NULL) { |
- return extension_dict::HasExtension(self->extensions, arg); |
- } |
- PyErr_SetString(PyExc_TypeError, "Message is not extendable"); |
- return NULL; |
-} |
- |
-// --------------------------------------------------------------------- |
-// Releasing messages |
-// |
-// The Python API's ClearField() and Clear() methods behave |
-// differently than their C++ counterparts. While the C++ versions |
-// clears the children the Python versions detaches the children, |
-// without touching their content. This impedance mismatch causes |
-// some complexity in the implementation, which is captured in this |
-// section. |
-// |
-// When a CMessage field is cleared we need to: |
-// |
-// * Release the Message used as the backing store for the CMessage |
-// from its parent. |
-// |
-// * Change the owner field of the released CMessage and all of its |
-// children to point to the newly released Message. |
-// |
-// * Clear the weak references from the released CMessage to the |
-// parent. |
-// |
-// When a RepeatedCompositeContainer field is cleared we need to: |
-// |
-// * Release all the Message used as the backing store for the |
-// CMessages stored in the container. |
-// |
-// * Change the owner field of all the released CMessage and all of |
-// their children to point to the newly released Messages. |
-// |
-// * Clear the weak references from the released container to the |
-// parent. |
- |
-struct SetOwnerVisitor : public ChildVisitor { |
- // new_owner must outlive this object. |
- explicit SetOwnerVisitor(const shared_ptr<Message>& new_owner) |
- : new_owner_(new_owner) {} |
- |
- int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { |
- repeated_composite_container::SetOwner(container, new_owner_); |
- return 0; |
- } |
- |
- int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { |
- repeated_scalar_container::SetOwner(container, new_owner_); |
- return 0; |
- } |
- |
- int VisitScalarMapContainer(ScalarMapContainer* container) { |
- scalar_map_container::SetOwner(container, new_owner_); |
- return 0; |
- } |
- |
- int VisitMessageMapContainer(MessageMapContainer* container) { |
- message_map_container::SetOwner(container, new_owner_); |
- return 0; |
- } |
- |
- int VisitCMessage(CMessage* cmessage, |
- const FieldDescriptor* field_descriptor) { |
- return SetOwner(cmessage, new_owner_); |
- } |
- |
- private: |
- const shared_ptr<Message>& new_owner_; |
-}; |
- |
-// Change the owner of this CMessage and all its children, recursively. |
-int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner) { |
- self->owner = new_owner; |
- if (ForEachCompositeField(self, SetOwnerVisitor(new_owner)) == -1) |
- return -1; |
- return 0; |
-} |
- |
-// Releases the message specified by 'field' and returns the |
-// pointer. If the field does not exist a new message is created using |
-// 'descriptor'. The caller takes ownership of the returned pointer. |
-Message* ReleaseMessage(CMessage* self, |
- const Descriptor* descriptor, |
- const FieldDescriptor* field_descriptor) { |
- Message* released_message = self->message->GetReflection()->ReleaseMessage( |
- self->message, field_descriptor, message_factory); |
- // 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 = message_factory->GetPrototype(descriptor); |
- GOOGLE_DCHECK(prototype != NULL); |
- released_message = prototype->New(); |
- } |
- |
- return released_message; |
-} |
- |
-int ReleaseSubMessage(CMessage* self, |
- const FieldDescriptor* field_descriptor, |
- CMessage* child_cmessage) { |
- // Release the Message |
- shared_ptr<Message> released_message(ReleaseMessage( |
- self, child_cmessage->message->GetDescriptor(), field_descriptor)); |
- child_cmessage->message = released_message.get(); |
- child_cmessage->owner.swap(released_message); |
- child_cmessage->parent = NULL; |
- child_cmessage->parent_field_descriptor = NULL; |
- child_cmessage->read_only = false; |
- return ForEachCompositeField(child_cmessage, |
- SetOwnerVisitor(child_cmessage->owner)); |
-} |
- |
-struct ReleaseChild : public ChildVisitor { |
- // message must outlive this object. |
- explicit ReleaseChild(CMessage* parent) : |
- parent_(parent) {} |
- |
- int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { |
- return repeated_composite_container::Release( |
- reinterpret_cast<RepeatedCompositeContainer*>(container)); |
- } |
- |
- int VisitRepeatedScalarContainer(RepeatedScalarContainer* container) { |
- return repeated_scalar_container::Release( |
- reinterpret_cast<RepeatedScalarContainer*>(container)); |
- } |
- |
- int VisitScalarMapContainer(ScalarMapContainer* container) { |
- return scalar_map_container::Release( |
- reinterpret_cast<ScalarMapContainer*>(container)); |
- } |
- |
- int VisitMessageMapContainer(MessageMapContainer* container) { |
- return message_map_container::Release( |
- reinterpret_cast<MessageMapContainer*>(container)); |
- } |
- |
- int VisitCMessage(CMessage* cmessage, |
- const FieldDescriptor* field_descriptor) { |
- return ReleaseSubMessage(parent_, field_descriptor, |
- reinterpret_cast<CMessage*>(cmessage)); |
- } |
- |
- CMessage* parent_; |
-}; |
- |
-int InternalReleaseFieldByDescriptor( |
- CMessage* self, |
- const FieldDescriptor* field_descriptor, |
- PyObject* composite_field) { |
- return VisitCompositeField( |
- field_descriptor, |
- composite_field, |
- ReleaseChild(self)); |
-} |
- |
-PyObject* ClearFieldByDescriptor( |
- CMessage* self, |
- const FieldDescriptor* descriptor) { |
- if (!CheckFieldBelongsToMessage(descriptor, self->message)) { |
- return NULL; |
- } |
- AssureWritable(self); |
- self->message->GetReflection()->ClearField(self->message, descriptor); |
- Py_RETURN_NONE; |
-} |
- |
-PyObject* ClearField(CMessage* self, PyObject* arg) { |
- if (!PyString_Check(arg)) { |
- PyErr_SetString(PyExc_TypeError, "field name must be a string"); |
- return NULL; |
- } |
-#if PY_MAJOR_VERSION < 3 |
- const char* field_name = PyString_AS_STRING(arg); |
- Py_ssize_t size = PyString_GET_SIZE(arg); |
-#else |
- Py_ssize_t size; |
- const char* field_name = PyUnicode_AsUTF8AndSize(arg, &size); |
-#endif |
- AssureWritable(self); |
- Message* message = self->message; |
- ScopedPyObjectPtr arg_in_oneof; |
- bool is_in_oneof; |
- const FieldDescriptor* field_descriptor = |
- FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof); |
- if (field_descriptor == NULL) { |
- if (!is_in_oneof) { |
- PyErr_Format(PyExc_ValueError, |
- "Protocol message has no \"%s\" field.", field_name); |
- return NULL; |
- } else { |
- Py_RETURN_NONE; |
- } |
- } else if (is_in_oneof) { |
- const string& name = field_descriptor->name(); |
- arg_in_oneof.reset(PyString_FromStringAndSize(name.c_str(), name.size())); |
- arg = arg_in_oneof.get(); |
- } |
- |
- PyObject* composite_field = self->composite_fields ? |
- PyDict_GetItem(self->composite_fields, arg) : NULL; |
- |
- // Only release the field if there's a possibility that there are |
- // references to it. |
- if (composite_field != NULL) { |
- if (InternalReleaseFieldByDescriptor(self, field_descriptor, |
- composite_field) < 0) { |
- return NULL; |
- } |
- PyDict_DelItem(self->composite_fields, arg); |
- } |
- message->GetReflection()->ClearField(message, field_descriptor); |
- if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && |
- !message->GetReflection()->SupportsUnknownEnumValues()) { |
- UnknownFieldSet* unknown_field_set = |
- message->GetReflection()->MutableUnknownFields(message); |
- unknown_field_set->DeleteByNumber(field_descriptor->number()); |
- } |
- |
- Py_RETURN_NONE; |
-} |
- |
-PyObject* Clear(CMessage* self) { |
- AssureWritable(self); |
- if (ForEachCompositeField(self, ReleaseChild(self)) == -1) |
- return NULL; |
- |
- // The old ExtensionDict still aliases this CMessage, but all its |
- // fields have been released. |
- if (self->extensions != NULL) { |
- Py_CLEAR(self->extensions); |
- ExtensionDict* extension_dict = extension_dict::NewExtensionDict(self); |
- if (extension_dict == NULL) { |
- return NULL; |
- } |
- self->extensions = extension_dict; |
- } |
- if (self->composite_fields) { |
- PyDict_Clear(self->composite_fields); |
- } |
- self->message->Clear(); |
- Py_RETURN_NONE; |
-} |
- |
-// --------------------------------------------------------------------- |
- |
-static string GetMessageName(CMessage* self) { |
- if (self->parent_field_descriptor != NULL) { |
- return self->parent_field_descriptor->full_name(); |
- } else { |
- return self->message->GetDescriptor()->full_name(); |
- } |
-} |
- |
-static PyObject* SerializeToString(CMessage* self, PyObject* args) { |
- if (!self->message->IsInitialized()) { |
- ScopedPyObjectPtr errors(FindInitializationErrors(self)); |
- if (errors == NULL) { |
- return NULL; |
- } |
- ScopedPyObjectPtr comma(PyString_FromString(",")); |
- if (comma == NULL) { |
- return NULL; |
- } |
- ScopedPyObjectPtr joined( |
- PyObject_CallMethod(comma.get(), "join", "O", errors.get())); |
- if (joined == NULL) { |
- return NULL; |
- } |
- |
- // TODO(haberman): this is a (hopefully temporary) hack. The unit testing |
- // infrastructure reloads all pure-Python modules for every test, but not |
- // C++ modules (because that's generally impossible: |
- // http://bugs.python.org/issue1144263). But if we cache EncodeError, we'll |
- // return the EncodeError from a previous load of the module, which won't |
- // match a user's attempt to catch EncodeError. So we have to look it up |
- // again every time. |
- ScopedPyObjectPtr message_module(PyImport_ImportModule( |
- "google.protobuf.message")); |
- if (message_module.get() == NULL) { |
- return NULL; |
- } |
- |
- ScopedPyObjectPtr encode_error( |
- PyObject_GetAttrString(message_module, "EncodeError")); |
- if (encode_error.get() == NULL) { |
- return NULL; |
- } |
- PyErr_Format(encode_error.get(), |
- "Message %s is missing required fields: %s", |
- GetMessageName(self).c_str(), PyString_AsString(joined)); |
- return NULL; |
- } |
- int size = self->message->ByteSize(); |
- if (size <= 0) { |
- return PyBytes_FromString(""); |
- } |
- PyObject* result = PyBytes_FromStringAndSize(NULL, size); |
- if (result == NULL) { |
- return NULL; |
- } |
- char* buffer = PyBytes_AS_STRING(result); |
- self->message->SerializeWithCachedSizesToArray( |
- reinterpret_cast<uint8*>(buffer)); |
- return result; |
-} |
- |
-static PyObject* SerializePartialToString(CMessage* self) { |
- string contents; |
- self->message->SerializePartialToString(&contents); |
- return PyBytes_FromStringAndSize(contents.c_str(), contents.size()); |
-} |
- |
-// Formats proto fields for ascii dumps using python formatting functions where |
-// 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. |
- // |
- // 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(); |
-#if PY_MAJOR_VERSION < 3 |
- char *cstr = PyBytes_AS_STRING(static_cast<PyObject*>(s)); |
-#else |
- char *cstr = PyUnicode_AsUTF8(s); |
-#endif |
- return string(cstr); |
- } |
- |
- 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) { |
- TextFormat::Printer printer; |
- // Passes ownership |
- printer.SetDefaultFieldValuePrinter(new PythonFieldValuePrinter()); |
- printer.SetHideUnknownFields(true); |
- string output; |
- if (!printer.PrintToString(*self->message, &output)) { |
- PyErr_SetString(PyExc_ValueError, "Unable to convert message to str"); |
- return NULL; |
- } |
- return PyString_FromString(output.c_str()); |
-} |
- |
-PyObject* MergeFrom(CMessage* self, PyObject* arg) { |
- CMessage* other_message; |
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg), &CMessage_Type)) { |
- PyErr_SetString(PyExc_TypeError, "Must be a message"); |
- return NULL; |
- } |
- |
- other_message = reinterpret_cast<CMessage*>(arg); |
- if (other_message->message->GetDescriptor() != |
- self->message->GetDescriptor()) { |
- PyErr_Format(PyExc_TypeError, |
- "Tried to merge from a message with a different type. " |
- "to: %s, from: %s", |
- self->message->GetDescriptor()->full_name().c_str(), |
- other_message->message->GetDescriptor()->full_name().c_str()); |
- return NULL; |
- } |
- AssureWritable(self); |
- |
- // TODO(tibell): Message::MergeFrom might turn some child Messages |
- // into mutable messages, invalidating the message field in the |
- // corresponding CMessages. We should run a FixupMessageReferences |
- // pass here. |
- |
- self->message->MergeFrom(*other_message->message); |
- Py_RETURN_NONE; |
-} |
- |
-static PyObject* CopyFrom(CMessage* self, PyObject* arg) { |
- CMessage* other_message; |
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg), &CMessage_Type)) { |
- PyErr_SetString(PyExc_TypeError, "Must be a message"); |
- return NULL; |
- } |
- |
- other_message = reinterpret_cast<CMessage*>(arg); |
- |
- if (self == other_message) { |
- Py_RETURN_NONE; |
- } |
- |
- if (other_message->message->GetDescriptor() != |
- self->message->GetDescriptor()) { |
- PyErr_Format(PyExc_TypeError, |
- "Tried to copy from a message with a different type. " |
- "to: %s, from: %s", |
- self->message->GetDescriptor()->full_name().c_str(), |
- other_message->message->GetDescriptor()->full_name().c_str()); |
- return NULL; |
- } |
- |
- AssureWritable(self); |
- |
- // 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); |
- |
- self->message->CopyFrom(*other_message->message); |
- |
- Py_RETURN_NONE; |
-} |
- |
-static PyObject* MergeFromString(CMessage* self, PyObject* arg) { |
- const void* data; |
- Py_ssize_t data_length; |
- if (PyObject_AsReadBuffer(arg, &data, &data_length) < 0) { |
- return NULL; |
- } |
- |
- AssureWritable(self); |
- io::CodedInputStream input( |
- reinterpret_cast<const uint8*>(data), data_length); |
- input.SetExtensionRegistry(GetDescriptorPool()->pool, message_factory); |
- bool success = self->message->MergePartialFromCodedStream(&input); |
- if (success) { |
- return PyInt_FromLong(input.CurrentPosition()); |
- } else { |
- PyErr_Format(DecodeError_class, "Error parsing message"); |
- return NULL; |
- } |
-} |
- |
-static PyObject* ParseFromString(CMessage* self, PyObject* arg) { |
- if (Clear(self) == NULL) { |
- return NULL; |
- } |
- return MergeFromString(self, arg); |
-} |
- |
-static PyObject* ByteSize(CMessage* self, PyObject* args) { |
- return PyLong_FromLong(self->message->ByteSize()); |
-} |
- |
-static PyObject* RegisterExtension(PyObject* cls, |
- PyObject* extension_handle) { |
- ScopedPyObjectPtr message_descriptor(PyObject_GetAttr(cls, kDESCRIPTOR)); |
- if (message_descriptor == NULL) { |
- return NULL; |
- } |
- |
- const FieldDescriptor* descriptor = |
- GetExtensionDescriptor(extension_handle); |
- if (descriptor == NULL) { |
- return NULL; |
- } |
- const Descriptor* cmessage_descriptor = GetMessageDescriptor( |
- reinterpret_cast<PyTypeObject*>(cls)); |
- |
- if (cmessage_descriptor != descriptor->containing_type()) { |
- if (PyObject_SetAttrString(extension_handle, "containing_type", |
- message_descriptor) < 0) { |
- return NULL; |
- } |
- } |
- |
- ScopedPyObjectPtr extensions_by_name( |
- PyObject_GetAttr(cls, k_extensions_by_name)); |
- if (extensions_by_name == NULL) { |
- PyErr_SetString(PyExc_TypeError, "no extensions_by_name on class"); |
- return NULL; |
- } |
- ScopedPyObjectPtr full_name(PyObject_GetAttr(extension_handle, kfull_name)); |
- if (full_name == NULL) { |
- return NULL; |
- } |
- |
- // If the extension was already registered, check that it is the same. |
- PyObject* existing_extension = PyDict_GetItem(extensions_by_name, full_name); |
- if (existing_extension != NULL) { |
- const FieldDescriptor* existing_extension_descriptor = |
- GetExtensionDescriptor(existing_extension); |
- if (existing_extension_descriptor != descriptor) { |
- PyErr_SetString(PyExc_ValueError, "Double registration of Extensions"); |
- return NULL; |
- } |
- // Nothing else to do. |
- Py_RETURN_NONE; |
- } |
- |
- if (PyDict_SetItem(extensions_by_name, full_name, extension_handle) < 0) { |
- return NULL; |
- } |
- |
- // Also store a mapping from extension number to implementing class. |
- ScopedPyObjectPtr extensions_by_number( |
- PyObject_GetAttr(cls, k_extensions_by_number)); |
- if (extensions_by_number == NULL) { |
- PyErr_SetString(PyExc_TypeError, "no extensions_by_number on class"); |
- return NULL; |
- } |
- ScopedPyObjectPtr number(PyObject_GetAttrString(extension_handle, "number")); |
- if (number == NULL) { |
- return NULL; |
- } |
- if (PyDict_SetItem(extensions_by_number, number, extension_handle) < 0) { |
- return NULL; |
- } |
- |
- // Check if it's a message set |
- if (descriptor->is_extension() && |
- descriptor->containing_type()->options().message_set_wire_format() && |
- descriptor->type() == FieldDescriptor::TYPE_MESSAGE && |
- descriptor->message_type() == descriptor->extension_scope() && |
- descriptor->label() == FieldDescriptor::LABEL_OPTIONAL) { |
- ScopedPyObjectPtr message_name(PyString_FromStringAndSize( |
- descriptor->message_type()->full_name().c_str(), |
- descriptor->message_type()->full_name().size())); |
- if (message_name == NULL) { |
- return NULL; |
- } |
- PyDict_SetItem(extensions_by_name, message_name, extension_handle); |
- } |
- |
- Py_RETURN_NONE; |
-} |
- |
-static PyObject* SetInParent(CMessage* self, PyObject* args) { |
- AssureWritable(self); |
- Py_RETURN_NONE; |
-} |
- |
-static PyObject* WhichOneof(CMessage* self, PyObject* arg) { |
- Py_ssize_t name_size; |
- char *name_data; |
- if (PyString_AsStringAndSize(arg, &name_data, &name_size) < 0) |
- return NULL; |
- string oneof_name = string(name_data, name_size); |
- const OneofDescriptor* oneof_desc = |
- self->message->GetDescriptor()->FindOneofByName(oneof_name); |
- if (oneof_desc == NULL) { |
- PyErr_Format(PyExc_ValueError, |
- "Protocol message has no oneof \"%s\" field.", |
- oneof_name.c_str()); |
- return NULL; |
- } |
- const FieldDescriptor* field_in_oneof = |
- self->message->GetReflection()->GetOneofFieldDescriptor( |
- *self->message, oneof_desc); |
- if (field_in_oneof == NULL) { |
- Py_RETURN_NONE; |
- } else { |
- const string& name = field_in_oneof->name(); |
- return PyString_FromStringAndSize(name.c_str(), name.size()); |
- } |
-} |
- |
-static PyObject* ListFields(CMessage* self) { |
- vector<const FieldDescriptor*> fields; |
- self->message->GetReflection()->ListFields(*self->message, &fields); |
- |
- // Normally, the list will be exactly the size of the fields. |
- ScopedPyObjectPtr all_fields(PyList_New(fields.size())); |
- if (all_fields == NULL) { |
- return NULL; |
- } |
- |
- // When there are unknown extensions, the py list will *not* contain |
- // the field information. Thus the actual size of the py list will be |
- // smaller than the size of fields. Set the actual size at the end. |
- Py_ssize_t actual_size = 0; |
- for (Py_ssize_t i = 0; i < fields.size(); ++i) { |
- ScopedPyObjectPtr t(PyTuple_New(2)); |
- if (t == NULL) { |
- return NULL; |
- } |
- |
- if (fields[i]->is_extension()) { |
- ScopedPyObjectPtr extension_field( |
- PyFieldDescriptor_FromDescriptor(fields[i])); |
- if (extension_field == NULL) { |
- return NULL; |
- } |
- // With C++ descriptors, the field can always be retrieved, but for |
- // unknown extensions which have not been imported in Python code, there |
- // is no message class and we cannot retrieve the value. |
- // TODO(amauryfa): consider building the class on the fly! |
- if (fields[i]->message_type() != NULL && |
- cdescriptor_pool::GetMessageClass( |
- GetDescriptorPool(), fields[i]->message_type()) == NULL) { |
- PyErr_Clear(); |
- continue; |
- } |
- PyObject* extensions = reinterpret_cast<PyObject*>(self->extensions); |
- if (extensions == NULL) { |
- return NULL; |
- } |
- // 'extension' reference later stolen by PyTuple_SET_ITEM. |
- PyObject* extension = PyObject_GetItem(extensions, extension_field); |
- if (extension == NULL) { |
- return NULL; |
- } |
- PyTuple_SET_ITEM(t.get(), 0, extension_field.release()); |
- // Steals reference to 'extension' |
- PyTuple_SET_ITEM(t.get(), 1, extension); |
- } else { |
- const string& field_name = fields[i]->name(); |
- ScopedPyObjectPtr py_field_name(PyString_FromStringAndSize( |
- field_name.c_str(), field_name.length())); |
- if (py_field_name == NULL) { |
- PyErr_SetString(PyExc_ValueError, "bad string"); |
- return NULL; |
- } |
- ScopedPyObjectPtr field_descriptor( |
- PyFieldDescriptor_FromDescriptor(fields[i])); |
- if (field_descriptor == NULL) { |
- return NULL; |
- } |
- |
- PyObject* field_value = GetAttr(self, py_field_name); |
- if (field_value == NULL) { |
- PyErr_SetObject(PyExc_ValueError, py_field_name); |
- return NULL; |
- } |
- PyTuple_SET_ITEM(t.get(), 0, field_descriptor.release()); |
- PyTuple_SET_ITEM(t.get(), 1, field_value); |
- } |
- PyList_SET_ITEM(all_fields.get(), actual_size, t.release()); |
- ++actual_size; |
- } |
- Py_SIZE(all_fields.get()) = actual_size; |
- return all_fields.release(); |
-} |
- |
-PyObject* FindInitializationErrors(CMessage* self) { |
- Message* message = self->message; |
- vector<string> errors; |
- message->FindInitializationErrors(&errors); |
- |
- PyObject* error_list = PyList_New(errors.size()); |
- if (error_list == NULL) { |
- return NULL; |
- } |
- for (Py_ssize_t i = 0; i < errors.size(); ++i) { |
- const string& error = errors[i]; |
- PyObject* error_string = PyString_FromStringAndSize( |
- error.c_str(), error.length()); |
- if (error_string == NULL) { |
- Py_DECREF(error_list); |
- return NULL; |
- } |
- PyList_SET_ITEM(error_list, i, error_string); |
- } |
- return error_list; |
-} |
- |
-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 { |
- Py_INCREF(Py_NotImplemented); |
- return Py_NotImplemented; |
- } |
-} |
- |
-PyObject* InternalGetScalar(const Message* message, |
- const FieldDescriptor* field_descriptor) { |
- const Reflection* reflection = message->GetReflection(); |
- |
- if (!CheckFieldBelongsToMessage(field_descriptor, message)) { |
- return NULL; |
- } |
- |
- PyObject* result = NULL; |
- switch (field_descriptor->cpp_type()) { |
- case FieldDescriptor::CPPTYPE_INT32: { |
- int32 value = reflection->GetInt32(*message, field_descriptor); |
- result = PyInt_FromLong(value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_INT64: { |
- int64 value = reflection->GetInt64(*message, field_descriptor); |
- result = PyLong_FromLongLong(value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_UINT32: { |
- uint32 value = reflection->GetUInt32(*message, field_descriptor); |
- result = PyInt_FromSize_t(value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_UINT64: { |
- uint64 value = reflection->GetUInt64(*message, field_descriptor); |
- result = PyLong_FromUnsignedLongLong(value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_FLOAT: { |
- float value = reflection->GetFloat(*message, field_descriptor); |
- result = PyFloat_FromDouble(value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_DOUBLE: { |
- double value = reflection->GetDouble(*message, field_descriptor); |
- result = PyFloat_FromDouble(value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_BOOL: { |
- bool value = reflection->GetBool(*message, field_descriptor); |
- result = PyBool_FromLong(value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_STRING: { |
- string value = reflection->GetString(*message, field_descriptor); |
- result = ToStringObject(field_descriptor, value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_ENUM: { |
- if (!message->GetReflection()->SupportsUnknownEnumValues() && |
- !message->GetReflection()->HasField(*message, field_descriptor)) { |
- // Look for the value in the unknown fields. |
- const UnknownFieldSet& unknown_field_set = |
- message->GetReflection()->GetUnknownFields(*message); |
- for (int i = 0; i < unknown_field_set.field_count(); ++i) { |
- if (unknown_field_set.field(i).number() == |
- field_descriptor->number()) { |
- result = PyInt_FromLong(unknown_field_set.field(i).varint()); |
- break; |
- } |
- } |
- } |
- |
- if (result == NULL) { |
- const EnumValueDescriptor* enum_value = |
- message->GetReflection()->GetEnum(*message, field_descriptor); |
- result = PyInt_FromLong(enum_value->number()); |
- } |
- break; |
- } |
- default: |
- PyErr_Format( |
- PyExc_SystemError, "Getting a value from a field of unknown type %d", |
- field_descriptor->cpp_type()); |
- } |
- |
- return result; |
-} |
- |
-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); |
- |
- PyObject *message_class = cdescriptor_pool::GetMessageClass( |
- GetDescriptorPool(), field_descriptor->message_type()); |
- if (message_class == NULL) { |
- return NULL; |
- } |
- |
- CMessage* cmsg = cmessage::NewEmptyMessage(message_class, |
- sub_message.GetDescriptor()); |
- if (cmsg == NULL) { |
- return NULL; |
- } |
- |
- cmsg->owner = self->owner; |
- cmsg->parent = self; |
- cmsg->parent_field_descriptor = field_descriptor; |
- cmsg->read_only = !reflection->HasField(*self->message, field_descriptor); |
- cmsg->message = const_cast<Message*>(&sub_message); |
- |
- return reinterpret_cast<PyObject*>(cmsg); |
-} |
- |
-int InternalSetNonOneofScalar( |
- Message* message, |
- const FieldDescriptor* field_descriptor, |
- PyObject* arg) { |
- const Reflection* reflection = message->GetReflection(); |
- |
- if (!CheckFieldBelongsToMessage(field_descriptor, message)) { |
- return -1; |
- } |
- |
- switch (field_descriptor->cpp_type()) { |
- case FieldDescriptor::CPPTYPE_INT32: { |
- GOOGLE_CHECK_GET_INT32(arg, value, -1); |
- reflection->SetInt32(message, field_descriptor, value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_INT64: { |
- GOOGLE_CHECK_GET_INT64(arg, value, -1); |
- reflection->SetInt64(message, field_descriptor, value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_UINT32: { |
- GOOGLE_CHECK_GET_UINT32(arg, value, -1); |
- reflection->SetUInt32(message, field_descriptor, value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_UINT64: { |
- GOOGLE_CHECK_GET_UINT64(arg, value, -1); |
- reflection->SetUInt64(message, field_descriptor, value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_FLOAT: { |
- GOOGLE_CHECK_GET_FLOAT(arg, value, -1); |
- reflection->SetFloat(message, field_descriptor, value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_DOUBLE: { |
- GOOGLE_CHECK_GET_DOUBLE(arg, value, -1); |
- reflection->SetDouble(message, field_descriptor, value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_BOOL: { |
- GOOGLE_CHECK_GET_BOOL(arg, value, -1); |
- reflection->SetBool(message, field_descriptor, value); |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_STRING: { |
- if (!CheckAndSetString( |
- arg, message, field_descriptor, reflection, false, -1)) { |
- return -1; |
- } |
- break; |
- } |
- case FieldDescriptor::CPPTYPE_ENUM: { |
- GOOGLE_CHECK_GET_INT32(arg, value, -1); |
- if (reflection->SupportsUnknownEnumValues()) { |
- reflection->SetEnumValue(message, field_descriptor, value); |
- } else { |
- const EnumDescriptor* enum_descriptor = field_descriptor->enum_type(); |
- const EnumValueDescriptor* enum_value = |
- enum_descriptor->FindValueByNumber(value); |
- if (enum_value != NULL) { |
- reflection->SetEnum(message, field_descriptor, enum_value); |
- } else { |
- PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value); |
- return -1; |
- } |
- } |
- break; |
- } |
- default: |
- PyErr_Format( |
- PyExc_SystemError, "Setting value to a field of unknown type %d", |
- field_descriptor->cpp_type()); |
- return -1; |
- } |
- |
- return 0; |
-} |
- |
-int InternalSetScalar( |
- CMessage* self, |
- const FieldDescriptor* field_descriptor, |
- PyObject* arg) { |
- if (!CheckFieldBelongsToMessage(field_descriptor, self->message)) { |
- return -1; |
- } |
- |
- if (MaybeReleaseOverlappingOneofField(self, field_descriptor) < 0) { |
- return -1; |
- } |
- |
- return InternalSetNonOneofScalar(self->message, field_descriptor, arg); |
-} |
- |
-PyObject* FromString(PyTypeObject* cls, PyObject* serialized) { |
- PyObject* py_cmsg = PyObject_CallObject( |
- reinterpret_cast<PyObject*>(cls), NULL); |
- if (py_cmsg == NULL) { |
- return NULL; |
- } |
- CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg); |
- |
- ScopedPyObjectPtr py_length(MergeFromString(cmsg, serialized)); |
- if (py_length == NULL) { |
- Py_DECREF(py_cmsg); |
- return NULL; |
- } |
- |
- 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); |
- if (clone == NULL) { |
- return NULL; |
- } |
- if (!PyObject_TypeCheck(clone, &CMessage_Type)) { |
- Py_DECREF(clone); |
- return NULL; |
- } |
- if (MergeFrom(reinterpret_cast<CMessage*>(clone), |
- reinterpret_cast<PyObject*>(self)) == NULL) { |
- Py_DECREF(clone); |
- return NULL; |
- } |
- return clone; |
-} |
- |
-PyObject* ToUnicode(CMessage* self) { |
- // Lazy import to prevent circular dependencies |
- ScopedPyObjectPtr text_format( |
- PyImport_ImportModule("google.protobuf.text_format")); |
- if (text_format == NULL) { |
- return NULL; |
- } |
- ScopedPyObjectPtr method_name(PyString_FromString("MessageToString")); |
- if (method_name == NULL) { |
- return NULL; |
- } |
- Py_INCREF(Py_True); |
- ScopedPyObjectPtr encoded(PyObject_CallMethodObjArgs(text_format, method_name, |
- self, Py_True, NULL)); |
- Py_DECREF(Py_True); |
- if (encoded == NULL) { |
- return NULL; |
- } |
-#if PY_MAJOR_VERSION < 3 |
- PyObject* decoded = PyString_AsDecodedObject(encoded, "utf-8", NULL); |
-#else |
- PyObject* decoded = PyUnicode_FromEncodedObject(encoded, "utf-8", NULL); |
-#endif |
- if (decoded == NULL) { |
- return NULL; |
- } |
- return decoded; |
-} |
- |
-PyObject* Reduce(CMessage* self) { |
- ScopedPyObjectPtr constructor(reinterpret_cast<PyObject*>(Py_TYPE(self))); |
- constructor.inc(); |
- ScopedPyObjectPtr args(PyTuple_New(0)); |
- if (args == NULL) { |
- return NULL; |
- } |
- ScopedPyObjectPtr state(PyDict_New()); |
- if (state == NULL) { |
- return NULL; |
- } |
- ScopedPyObjectPtr serialized(SerializePartialToString(self)); |
- if (serialized == NULL) { |
- return NULL; |
- } |
- if (PyDict_SetItemString(state, "serialized", serialized) < 0) { |
- return NULL; |
- } |
- return Py_BuildValue("OOO", constructor.get(), args.get(), state.get()); |
-} |
- |
-PyObject* SetState(CMessage* self, PyObject* state) { |
- if (!PyDict_Check(state)) { |
- PyErr_SetString(PyExc_TypeError, "state not a dict"); |
- return NULL; |
- } |
- PyObject* serialized = PyDict_GetItemString(state, "serialized"); |
- if (serialized == NULL) { |
- return NULL; |
- } |
- if (ParseFromString(self, serialized) == NULL) { |
- return NULL; |
- } |
- Py_RETURN_NONE; |
-} |
- |
-// CMessage static methods: |
-PyObject* _CheckCalledFromGeneratedFile(PyObject* unused, |
- PyObject* unused_arg) { |
- if (!_CalledFromGeneratedFile(1)) { |
- PyErr_SetString(PyExc_TypeError, |
- "Descriptors should not be created directly, " |
- "but only retrieved from their parent."); |
- return NULL; |
- } |
- Py_RETURN_NONE; |
-} |
- |
-static PyMemberDef Members[] = { |
- {"Extensions", T_OBJECT_EX, offsetof(CMessage, extensions), 0, |
- "Extension dict"}, |
- {NULL} |
-}; |
- |
-static PyMethodDef Methods[] = { |
- { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, |
- "Makes a deep copy of the class." }, |
- { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, |
- "Outputs picklable representation of the message." }, |
- { "__setstate__", (PyCFunction)SetState, METH_O, |
- "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, |
- "Clears the message." }, |
- { "ClearExtension", (PyCFunction)ClearExtension, METH_O, |
- "Clears a message field." }, |
- { "ClearField", (PyCFunction)ClearField, METH_O, |
- "Clears a message field." }, |
- { "CopyFrom", (PyCFunction)CopyFrom, METH_O, |
- "Copies a protocol message into the current message." }, |
- { "FindInitializationErrors", (PyCFunction)FindInitializationErrors, |
- METH_NOARGS, |
- "Finds unset required fields." }, |
- { "FromString", (PyCFunction)FromString, METH_O | METH_CLASS, |
- "Creates new method instance from given serialized data." }, |
- { "HasExtension", (PyCFunction)HasExtension, METH_O, |
- "Checks if a message field is set." }, |
- { "HasField", (PyCFunction)HasField, METH_O, |
- "Checks if a message field is set." }, |
- { "IsInitialized", (PyCFunction)IsInitialized, METH_VARARGS, |
- "Checks if all required fields of a protocol message are set." }, |
- { "ListFields", (PyCFunction)ListFields, METH_NOARGS, |
- "Lists all set fields of a message." }, |
- { "MergeFrom", (PyCFunction)MergeFrom, METH_O, |
- "Merges a protocol message into the current message." }, |
- { "MergeFromString", (PyCFunction)MergeFromString, METH_O, |
- "Merges a serialized message into the current message." }, |
- { "ParseFromString", (PyCFunction)ParseFromString, METH_O, |
- "Parses a serialized message into the current message." }, |
- { "RegisterExtension", (PyCFunction)RegisterExtension, METH_O | METH_CLASS, |
- "Registers an extension with the current message." }, |
- { "SerializePartialToString", (PyCFunction)SerializePartialToString, |
- METH_NOARGS, |
- "Serializes the message to a string, even if it isn't initialized." }, |
- { "SerializeToString", (PyCFunction)SerializeToString, METH_NOARGS, |
- "Serializes the message to a string, only for initialized messages." }, |
- { "SetInParent", (PyCFunction)SetInParent, METH_NOARGS, |
- "Sets the has bit of the given field in its parent message." }, |
- { "WhichOneof", (PyCFunction)WhichOneof, METH_O, |
- "Returns the name of the field set inside a oneof, " |
- "or None if no field is set." }, |
- |
- // Static Methods. |
- { "_CheckCalledFromGeneratedFile", (PyCFunction)_CheckCalledFromGeneratedFile, |
- METH_NOARGS | METH_STATIC, |
- "Raises TypeError if the caller is not in a _pb2.py file."}, |
- { NULL, NULL} |
-}; |
- |
-static bool SetCompositeField( |
- CMessage* self, PyObject* name, PyObject* value) { |
- if (self->composite_fields == NULL) { |
- self->composite_fields = PyDict_New(); |
- if (self->composite_fields == NULL) { |
- return false; |
- } |
- } |
- return PyDict_SetItem(self->composite_fields, name, value) == 0; |
-} |
- |
-PyObject* GetAttr(CMessage* self, PyObject* name) { |
- PyObject* value = self->composite_fields ? |
- PyDict_GetItem(self->composite_fields, name) : NULL; |
- if (value != NULL) { |
- Py_INCREF(value); |
- return value; |
- } |
- |
- const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name); |
- if (field_descriptor == NULL) { |
- return CMessage_Type.tp_base->tp_getattro( |
- reinterpret_cast<PyObject*>(self), name); |
- } |
- |
- if (field_descriptor->is_map()) { |
- PyObject* py_container = NULL; |
- const Descriptor* entry_type = field_descriptor->message_type(); |
- const FieldDescriptor* value_type = entry_type->FindFieldByName("value"); |
- if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- PyObject* value_class = cdescriptor_pool::GetMessageClass( |
- GetDescriptorPool(), value_type->message_type()); |
- if (value_class == NULL) { |
- return NULL; |
- } |
- py_container = message_map_container::NewContainer(self, field_descriptor, |
- value_class); |
- } else { |
- py_container = scalar_map_container::NewContainer(self, field_descriptor); |
- } |
- if (py_container == NULL) { |
- return NULL; |
- } |
- if (!SetCompositeField(self, name, py_container)) { |
- Py_DECREF(py_container); |
- return NULL; |
- } |
- return py_container; |
- } |
- |
- if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { |
- PyObject* py_container = NULL; |
- if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- PyObject *message_class = cdescriptor_pool::GetMessageClass( |
- GetDescriptorPool(), field_descriptor->message_type()); |
- if (message_class == NULL) { |
- return NULL; |
- } |
- py_container = repeated_composite_container::NewContainer( |
- self, field_descriptor, message_class); |
- } else { |
- py_container = repeated_scalar_container::NewContainer( |
- self, field_descriptor); |
- } |
- if (py_container == NULL) { |
- return NULL; |
- } |
- if (!SetCompositeField(self, name, py_container)) { |
- Py_DECREF(py_container); |
- return NULL; |
- } |
- return py_container; |
- } |
- |
- if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- PyObject* sub_message = InternalGetSubMessage(self, field_descriptor); |
- if (!SetCompositeField(self, name, sub_message)) { |
- Py_DECREF(sub_message); |
- return NULL; |
- } |
- return sub_message; |
- } |
- |
- return InternalGetScalar(self->message, field_descriptor); |
-} |
- |
-int SetAttr(CMessage* self, PyObject* name, PyObject* value) { |
- if (self->composite_fields && PyDict_Contains(self->composite_fields, name)) { |
- PyErr_SetString(PyExc_TypeError, "Can't set composite field"); |
- return -1; |
- } |
- |
- const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name); |
- if (field_descriptor != NULL) { |
- AssureWritable(self); |
- if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { |
- PyErr_Format(PyExc_AttributeError, "Assignment not allowed to repeated " |
- "field \"%s\" in protocol message object.", |
- field_descriptor->name().c_str()); |
- return -1; |
- } else { |
- if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { |
- PyErr_Format(PyExc_AttributeError, "Assignment not allowed to " |
- "field \"%s\" in protocol message object.", |
- field_descriptor->name().c_str()); |
- return -1; |
- } else { |
- return InternalSetScalar(self, field_descriptor, value); |
- } |
- } |
- } |
- |
- PyErr_Format(PyExc_AttributeError, "Assignment not allowed"); |
- return -1; |
-} |
- |
-} // namespace cmessage |
- |
-PyTypeObject CMessage_Type = { |
- PyVarObject_HEAD_INIT(&PyType_Type, 0) |
- FULL_MODULE_NAME ".CMessage", // tp_name |
- sizeof(CMessage), // tp_basicsize |
- 0, // tp_itemsize |
- (destructor)cmessage::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 |
- (reprfunc)cmessage::ToStr, // tp_str |
- (getattrofunc)cmessage::GetAttr, // tp_getattro |
- (setattrofunc)cmessage::SetAttr, // tp_setattro |
- 0, // tp_as_buffer |
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags |
- "A ProtocolMessage", // tp_doc |
- 0, // tp_traverse |
- 0, // tp_clear |
- (richcmpfunc)cmessage::RichCompare, // tp_richcompare |
- 0, // tp_weaklistoffset |
- 0, // tp_iter |
- 0, // tp_iternext |
- cmessage::Methods, // tp_methods |
- cmessage::Members, // tp_members |
- 0, // tp_getset |
- 0, // tp_base |
- 0, // tp_dict |
- 0, // tp_descr_get |
- 0, // tp_descr_set |
- 0, // tp_dictoffset |
- (initproc)cmessage::Init, // tp_init |
- 0, // tp_alloc |
- cmessage::New, // tp_new |
-}; |
- |
-// --- Exposing the C proto living inside Python proto to C code: |
- |
-const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg); |
-Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg); |
- |
-static const Message* GetCProtoInsidePyProtoImpl(PyObject* msg) { |
- if (!PyObject_TypeCheck(msg, &CMessage_Type)) { |
- return NULL; |
- } |
- CMessage* cmsg = reinterpret_cast<CMessage*>(msg); |
- return cmsg->message; |
-} |
- |
-static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) { |
- if (!PyObject_TypeCheck(msg, &CMessage_Type)) { |
- return NULL; |
- } |
- CMessage* cmsg = reinterpret_cast<CMessage*>(msg); |
- if ((cmsg->composite_fields && PyDict_Size(cmsg->composite_fields) != 0) || |
- (cmsg->extensions != NULL && |
- PyDict_Size(cmsg->extensions->values) != 0)) { |
- // There is currently no way of accurately syncing arbitrary changes to |
- // the underlying C++ message back to the CMessage (e.g. removed repeated |
- // composite containers). We only allow direct mutation of the underlying |
- // C++ message if there is no child data in the CMessage. |
- return NULL; |
- } |
- cmessage::AssureWritable(cmsg); |
- return cmsg->message; |
-} |
- |
-static const char module_docstring[] = |
-"python-proto2 is a module that can be used to enhance proto2 Python API\n" |
-"performance.\n" |
-"\n" |
-"It provides access to the protocol buffers C++ reflection API that\n" |
-"implements the basic protocol buffer functions."; |
- |
-void InitGlobals() { |
- // TODO(gps): Check all return values in this function for NULL and propagate |
- // the error (MemoryError) on up to result in an import failure. These should |
- // also be freed and reset to NULL during finalization. |
- kPythonZero = PyInt_FromLong(0); |
- kint32min_py = PyInt_FromLong(kint32min); |
- kint32max_py = PyInt_FromLong(kint32max); |
- kuint32max_py = PyLong_FromLongLong(kuint32max); |
- kint64min_py = PyLong_FromLongLong(kint64min); |
- kint64max_py = PyLong_FromLongLong(kint64max); |
- kuint64max_py = PyLong_FromUnsignedLongLong(kuint64max); |
- |
- kDESCRIPTOR = PyString_FromString("DESCRIPTOR"); |
- k_cdescriptor = PyString_FromString("_cdescriptor"); |
- kfull_name = PyString_FromString("full_name"); |
- 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); |
-} |
- |
-bool InitProto2MessageModule(PyObject *m) { |
- // Initialize types and globals in descriptor.cc |
- if (!InitDescriptor()) { |
- return false; |
- } |
- |
- // Initialize types and globals in descriptor_pool.cc |
- if (!InitDescriptorPool()) { |
- return false; |
- } |
- |
- // Initialize constants defined in this file. |
- InitGlobals(); |
- |
- CMessage_Type.tp_hash = PyObject_HashNotImplemented; |
- if (PyType_Ready(&CMessage_Type) < 0) { |
- return false; |
- } |
- |
- // DESCRIPTOR is set on each protocol buffer message class elsewhere, but set |
- // it here as well to document that subclasses need to set it. |
- PyDict_SetItem(CMessage_Type.tp_dict, kDESCRIPTOR, Py_None); |
- // Subclasses with message extensions will override _extensions_by_name and |
- // _extensions_by_number with fresh mutable dictionaries in AddDescriptors. |
- // All other classes can share this same immutable mapping. |
- ScopedPyObjectPtr empty_dict(PyDict_New()); |
- if (empty_dict == NULL) { |
- return false; |
- } |
- ScopedPyObjectPtr immutable_dict(PyDictProxy_New(empty_dict)); |
- if (immutable_dict == NULL) { |
- return false; |
- } |
- if (PyDict_SetItem(CMessage_Type.tp_dict, |
- k_extensions_by_name, immutable_dict) < 0) { |
- return false; |
- } |
- if (PyDict_SetItem(CMessage_Type.tp_dict, |
- k_extensions_by_number, immutable_dict) < 0) { |
- return false; |
- } |
- |
- PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(&CMessage_Type)); |
- |
- RepeatedScalarContainer_Type.tp_hash = |
- PyObject_HashNotImplemented; |
- if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) { |
- return false; |
- } |
- |
- PyModule_AddObject(m, "RepeatedScalarContainer", |
- reinterpret_cast<PyObject*>( |
- &RepeatedScalarContainer_Type)); |
- |
- RepeatedCompositeContainer_Type.tp_hash = PyObject_HashNotImplemented; |
- 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; |
- } |
- |
- PyObject* mutable_mapping = |
- PyObject_GetAttrString(containers, "MutableMapping"); |
- Py_DECREF(containers); |
- |
- if (mutable_mapping == NULL) { |
- return false; |
- } |
- |
- if (!PyObject_TypeCheck(mutable_mapping, &PyType_Type)) { |
- Py_DECREF(mutable_mapping); |
- return false; |
- } |
- |
- ScalarMapContainer_Type.tp_base = |
- reinterpret_cast<PyTypeObject*>(mutable_mapping); |
- |
- if (PyType_Ready(&ScalarMapContainer_Type) < 0) { |
- return false; |
- } |
- |
- PyModule_AddObject(m, "ScalarMapContainer", |
- reinterpret_cast<PyObject*>(&ScalarMapContainer_Type)); |
- |
- if (PyType_Ready(&ScalarMapIterator_Type) < 0) { |
- return false; |
- } |
- |
- PyModule_AddObject(m, "ScalarMapIterator", |
- reinterpret_cast<PyObject*>(&ScalarMapIterator_Type)); |
- |
- Py_INCREF(mutable_mapping); |
- MessageMapContainer_Type.tp_base = |
- reinterpret_cast<PyTypeObject*>(mutable_mapping); |
- |
- if (PyType_Ready(&MessageMapContainer_Type) < 0) { |
- return false; |
- } |
- |
- PyModule_AddObject(m, "MessageMapContainer", |
- reinterpret_cast<PyObject*>(&MessageMapContainer_Type)); |
- |
- if (PyType_Ready(&MessageMapIterator_Type) < 0) { |
- return false; |
- } |
- |
- 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)); |
- |
- // Expose the DescriptorPool used to hold all descriptors added from generated |
- // pb2.py files. |
- Py_INCREF(GetDescriptorPool()); // PyModule_AddObject steals a reference. |
- PyModule_AddObject( |
- m, "default_pool", reinterpret_cast<PyObject*>(GetDescriptorPool())); |
- |
- // This implementation provides full Descriptor types, we advertise it so that |
- // descriptor.py can use them in replacement of the Python classes. |
- PyModule_AddIntConstant(m, "_USE_C_DESCRIPTORS", 1); |
- |
- PyModule_AddObject(m, "Descriptor", reinterpret_cast<PyObject*>( |
- &PyMessageDescriptor_Type)); |
- PyModule_AddObject(m, "FieldDescriptor", reinterpret_cast<PyObject*>( |
- &PyFieldDescriptor_Type)); |
- PyModule_AddObject(m, "EnumDescriptor", reinterpret_cast<PyObject*>( |
- &PyEnumDescriptor_Type)); |
- PyModule_AddObject(m, "EnumValueDescriptor", reinterpret_cast<PyObject*>( |
- &PyEnumValueDescriptor_Type)); |
- PyModule_AddObject(m, "FileDescriptor", reinterpret_cast<PyObject*>( |
- &PyFileDescriptor_Type)); |
- PyModule_AddObject(m, "OneofDescriptor", reinterpret_cast<PyObject*>( |
- &PyOneofDescriptor_Type)); |
- |
- PyObject* enum_type_wrapper = PyImport_ImportModule( |
- "google.protobuf.internal.enum_type_wrapper"); |
- if (enum_type_wrapper == NULL) { |
- return false; |
- } |
- EnumTypeWrapper_class = |
- PyObject_GetAttrString(enum_type_wrapper, "EnumTypeWrapper"); |
- Py_DECREF(enum_type_wrapper); |
- |
- PyObject* message_module = PyImport_ImportModule( |
- "google.protobuf.message"); |
- if (message_module == NULL) { |
- return false; |
- } |
- EncodeError_class = PyObject_GetAttrString(message_module, "EncodeError"); |
- DecodeError_class = PyObject_GetAttrString(message_module, "DecodeError"); |
- Py_DECREF(message_module); |
- |
- PyObject* pickle_module = PyImport_ImportModule("pickle"); |
- if (pickle_module == NULL) { |
- return false; |
- } |
- PickleError_class = PyObject_GetAttrString(pickle_module, "PickleError"); |
- Py_DECREF(pickle_module); |
- |
- // Override {Get,Mutable}CProtoInsidePyProto. |
- GetCProtoInsidePyProtoPtr = GetCProtoInsidePyProtoImpl; |
- MutableCProtoInsidePyProtoPtr = MutableCProtoInsidePyProtoImpl; |
- |
- return true; |
-} |
- |
-} // namespace python |
-} // namespace protobuf |
- |
- |
-#if PY_MAJOR_VERSION >= 3 |
-static struct PyModuleDef _module = { |
- PyModuleDef_HEAD_INIT, |
- "_message", |
- google::protobuf::python::module_docstring, |
- -1, |
- NULL, |
- NULL, |
- NULL, |
- NULL, |
- NULL |
-}; |
-#define INITFUNC PyInit__message |
-#define INITFUNC_ERRORVAL NULL |
-#else // Python 2 |
-#define INITFUNC init_message |
-#define INITFUNC_ERRORVAL |
-#endif |
- |
-extern "C" { |
- PyMODINIT_FUNC INITFUNC(void) { |
- PyObject* m; |
-#if PY_MAJOR_VERSION >= 3 |
- m = PyModule_Create(&_module); |
-#else |
- m = Py_InitModule3("_message", NULL, google::protobuf::python::module_docstring); |
-#endif |
- if (m == NULL) { |
- return INITFUNC_ERRORVAL; |
- } |
- |
- if (!google::protobuf::python::InitProto2MessageModule(m)) { |
- Py_DECREF(m); |
- return INITFUNC_ERRORVAL; |
- } |
- |
-#if PY_MAJOR_VERSION >= 3 |
- return m; |
-#endif |
- } |
-} |
-} // namespace google |