From 0400cca3236de1ca303af38bf81eab332d042b7c Mon Sep 17 00:00:00 2001 From: Adam Cozzette Date: Tue, 13 Mar 2018 16:37:29 -0700 Subject: Integrated internal changes from Google --- python/google/protobuf/pyext/descriptor.cc | 80 ++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 21 deletions(-) (limited to 'python/google/protobuf/pyext/descriptor.cc') diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index 9634ea05..bacaaf31 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -188,38 +188,35 @@ const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) { // Always returns a new reference. template static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { - // Options (and their extensions) are completely resolved in the proto file - // containing the descriptor. - PyDescriptorPool* pool = GetDescriptorPool_FromPool( + // Options are cached in the pool that owns the descriptor. + // First search in the cache. + PyDescriptorPool* caching_pool = GetDescriptorPool_FromPool( GetFileDescriptor(descriptor)->pool()); - hash_map* descriptor_options = - pool->descriptor_options; - // First search in the cache. + caching_pool->descriptor_options; if (descriptor_options->find(descriptor) != descriptor_options->end()) { PyObject *value = (*descriptor_options)[descriptor]; Py_INCREF(value); return value; } + // Similar to the C++ implementation, we return an Options object from the + // default (generated) factory, so that client code know that they can use + // extensions from generated files: + // d.GetOptions().Extensions[some_pb2.extension] + // + // The consequence is that extensions not defined in the default pool won't + // be available. If needed, we could add an optional 'message_factory' + // parameter to the GetOptions() function. + PyMessageFactory* message_factory = + GetDefaultDescriptorPool()->py_message_factory; + // Build the Options object: get its Python class, and make a copy of the C++ // read-only instance. const Message& options(descriptor->options()); const Descriptor *message_type = options.GetDescriptor(); - PyMessageFactory* message_factory = pool->py_message_factory; - CMessageClass* message_class = message_factory::GetMessageClass( + CMessageClass* message_class = message_factory::GetOrCreateMessageClass( message_factory, message_type); - if (message_class == NULL) { - // The Options message was not found in the current DescriptorPool. - // This means that the pool cannot contain any extensions to the Options - // message either, so falling back to the basic pool we can only increase - // the chances of successfully parsing the options. - PyErr_Clear(); - pool = GetDefaultDescriptorPool(); - message_factory = pool->py_message_factory; - message_class = message_factory::GetMessageClass( - message_factory, message_type); - } if (message_class == NULL) { PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s", message_type->full_name().c_str()); @@ -248,7 +245,8 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { options.SerializeToString(&serialized); io::CodedInputStream input( reinterpret_cast(serialized.c_str()), serialized.size()); - input.SetExtensionRegistry(pool->pool, message_factory->message_factory); + input.SetExtensionRegistry(message_factory->pool->pool, + message_factory->message_factory); bool success = cmsg->message->MergePartialFromCodedStream(&input); if (!success) { PyErr_Format(PyExc_ValueError, "Error parsing Options message"); @@ -564,6 +562,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { return CopyToPythonProto(_GetDescriptor(self), target); } @@ -623,6 +626,8 @@ static PyGetSetDef Getters[] = { { "is_extendable", (getter)IsExtendable, (setter)NULL}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"}, {NULL} }; @@ -785,7 +790,7 @@ static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) { break; } case FieldDescriptor::CPPTYPE_STRING: { - string value = _GetDescriptor(self)->default_value_string(); + const string& value = _GetDescriptor(self)->default_value_string(); result = ToStringObject(_GetDescriptor(self), value); break; } @@ -897,6 +902,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} static PyGetSetDef Getters[] = { { "full_name", (getter)GetFullName, NULL, "Full name"}, @@ -926,6 +935,8 @@ static PyGetSetDef Getters[] = { "Containing oneof"}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, {NULL} }; @@ -1055,6 +1066,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { return CopyToPythonProto(_GetDescriptor(self), target); } @@ -1079,6 +1095,8 @@ static PyGetSetDef Getters[] = { "Containing type"}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, {NULL} }; @@ -1179,6 +1197,10 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} static PyGetSetDef Getters[] = { { "name", (getter)GetName, NULL, "name"}, @@ -1188,6 +1210,8 @@ static PyGetSetDef Getters[] = { { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, {NULL} }; @@ -1330,6 +1354,11 @@ static int SetOptions(PyFileDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyFileDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) { return PyString_InternFromString( FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax())); @@ -1355,6 +1384,8 @@ static PyGetSetDef Getters[] = { { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"}, {NULL} }; @@ -1500,6 +1531,11 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, return CheckCalledFromGeneratedFile("_options"); } +static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_serialized_options"); +} + static PyGetSetDef Getters[] = { { "name", (getter)GetName, NULL, "Name"}, { "full_name", (getter)GetFullName, NULL, "Full name"}, @@ -1508,6 +1544,8 @@ static PyGetSetDef Getters[] = { { "containing_type", (getter)GetContainingType, NULL, "Containing type"}, { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "_serialized_options", (getter)NULL, (setter)SetSerializedOptions, + "Serialized Options"}, { "fields", (getter)GetFields, NULL, "Fields"}, {NULL} }; -- cgit v1.2.3