| Index: third_party/protobuf/python/google/protobuf/pyext/descriptor.cc
|
| diff --git a/third_party/protobuf/python/google/protobuf/pyext/descriptor.cc b/third_party/protobuf/python/google/protobuf/pyext/descriptor.cc
|
| index 235575389a5f0cdfa529113d65867c6bd2d6d0b4..924ae0b9cd87487e5950e152d31beb772b9ed63d 100644
|
| --- a/third_party/protobuf/python/google/protobuf/pyext/descriptor.cc
|
| +++ b/third_party/protobuf/python/google/protobuf/pyext/descriptor.cc
|
| @@ -41,6 +41,7 @@
|
| #include <google/protobuf/pyext/descriptor_containers.h>
|
| #include <google/protobuf/pyext/descriptor_pool.h>
|
| #include <google/protobuf/pyext/message.h>
|
| +#include <google/protobuf/pyext/message_factory.h>
|
| #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
|
|
|
| #if PY_MAJOR_VERSION >= 3
|
| @@ -172,12 +173,16 @@ template<>
|
| const FileDescriptor* GetFileDescriptor(const OneofDescriptor* descriptor) {
|
| return descriptor->containing_type()->file();
|
| }
|
| +template<>
|
| +const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) {
|
| + return descriptor->service()->file();
|
| +}
|
|
|
| // Converts options into a Python protobuf, and cache the result.
|
| //
|
| // This is a bit tricky because options can contain extension fields defined in
|
| // the same proto file. In this case the options parsed from the serialized_pb
|
| -// have unkown fields, and we need to parse them again.
|
| +// have unknown fields, and we need to parse them again.
|
| //
|
| // Always returns a new reference.
|
| template<class DescriptorClass>
|
| @@ -200,15 +205,19 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
|
| // read-only instance.
|
| const Message& options(descriptor->options());
|
| const Descriptor *message_type = options.GetDescriptor();
|
| - CMessageClass* message_class(
|
| - cdescriptor_pool::GetMessageClass(pool, message_type));
|
| + PyMessageFactory* message_factory = pool->py_message_factory;
|
| + CMessageClass* message_class = message_factory::GetMessageClass(
|
| + message_factory, message_type);
|
| if (message_class == NULL) {
|
| // The Options message was not found in the current DescriptorPool.
|
| - // In this case, there cannot be extensions to these options, and we can
|
| - // try to use the basic pool instead.
|
| + // 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();
|
| - message_class = cdescriptor_pool::GetMessageClass(
|
| - GetDefaultDescriptorPool(), message_type);
|
| + 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",
|
| @@ -238,7 +247,7 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
|
| options.SerializeToString(&serialized);
|
| io::CodedInputStream input(
|
| reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
|
| - input.SetExtensionRegistry(pool->pool, pool->message_factory);
|
| + input.SetExtensionRegistry(pool->pool, message_factory->message_factory);
|
| bool success = cmsg->message->MergePartialFromCodedStream(&input);
|
| if (!success) {
|
| PyErr_Format(PyExc_ValueError, "Error parsing Options message");
|
| @@ -248,7 +257,7 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
|
|
|
| // Cache the result.
|
| Py_INCREF(value.get());
|
| - (*pool->descriptor_options)[descriptor] = value.get();
|
| + (*descriptor_options)[descriptor] = value.get();
|
|
|
| return value.release();
|
| }
|
| @@ -434,8 +443,9 @@ static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
|
| // which contains this descriptor.
|
| // This might not be the one you expect! For example the returned object does
|
| // not know about extensions defined in a custom pool.
|
| - CMessageClass* concrete_class(cdescriptor_pool::GetMessageClass(
|
| - GetDescriptorPool_FromPool(_GetDescriptor(self)->file()->pool()),
|
| + CMessageClass* concrete_class(message_factory::GetMessageClass(
|
| + GetDescriptorPool_FromPool(
|
| + _GetDescriptor(self)->file()->pool())->py_message_factory,
|
| _GetDescriptor(self)));
|
| Py_XINCREF(concrete_class);
|
| return concrete_class->AsPyObject();
|
| @@ -694,6 +704,10 @@ static PyObject* GetCamelcaseName(PyBaseDescriptor* self, void *closure) {
|
| return PyString_FromCppString(_GetDescriptor(self)->camelcase_name());
|
| }
|
|
|
| +static PyObject* GetJsonName(PyBaseDescriptor* self, void *closure) {
|
| + return PyString_FromCppString(_GetDescriptor(self)->json_name());
|
| +}
|
| +
|
| static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
|
| return PyInt_FromLong(_GetDescriptor(self)->type());
|
| }
|
| @@ -883,6 +897,7 @@ static PyGetSetDef Getters[] = {
|
| { "full_name", (getter)GetFullName, NULL, "Full name"},
|
| { "name", (getter)GetName, NULL, "Unqualified name"},
|
| { "camelcase_name", (getter)GetCamelcaseName, NULL, "Camelcase name"},
|
| + { "json_name", (getter)GetJsonName, NULL, "Json name"},
|
| { "type", (getter)GetType, NULL, "C++ Type"},
|
| { "cpp_type", (getter)GetCppType, NULL, "C++ Type"},
|
| { "label", (getter)GetLabel, NULL, "Label"},
|
| @@ -1091,7 +1106,7 @@ PyTypeObject PyEnumDescriptor_Type = {
|
| 0, // tp_weaklistoffset
|
| 0, // tp_iter
|
| 0, // tp_iternext
|
| - enum_descriptor::Methods, // tp_getset
|
| + enum_descriptor::Methods, // tp_methods
|
| 0, // tp_members
|
| enum_descriptor::Getters, // tp_getset
|
| &descriptor::PyBaseDescriptor_Type, // tp_base
|
| @@ -1275,6 +1290,10 @@ static PyObject* GetExtensionsByName(PyFileDescriptor* self, void *closure) {
|
| return NewFileExtensionsByName(_GetDescriptor(self));
|
| }
|
|
|
| +static PyObject* GetServicesByName(PyFileDescriptor* self, void *closure) {
|
| + return NewFileServicesByName(_GetDescriptor(self));
|
| +}
|
| +
|
| static PyObject* GetDependencies(PyFileDescriptor* self, void *closure) {
|
| return NewFileDependencies(_GetDescriptor(self));
|
| }
|
| @@ -1324,6 +1343,7 @@ static PyGetSetDef Getters[] = {
|
| { "enum_types_by_name", (getter)GetEnumTypesByName, NULL, "Enums by name"},
|
| { "extensions_by_name", (getter)GetExtensionsByName, NULL,
|
| "Extensions by name"},
|
| + { "services_by_name", (getter)GetServicesByName, NULL, "Services by name"},
|
| { "dependencies", (getter)GetDependencies, NULL, "Dependencies"},
|
| { "public_dependencies", (getter)GetPublicDependencies, NULL, "Dependencies"},
|
|
|
| @@ -1452,16 +1472,45 @@ static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
|
| }
|
| }
|
|
|
| +static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
|
| + const OneofOptions& options(_GetDescriptor(self)->options());
|
| + if (&options != &OneofOptions::default_instance()) {
|
| + Py_RETURN_TRUE;
|
| + } else {
|
| + Py_RETURN_FALSE;
|
| + }
|
| +}
|
| +static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
|
| + void *closure) {
|
| + return CheckCalledFromGeneratedFile("has_options");
|
| +}
|
| +
|
| +static PyObject* GetOptions(PyBaseDescriptor *self) {
|
| + return GetOrBuildOptions(_GetDescriptor(self));
|
| +}
|
| +
|
| +static int SetOptions(PyBaseDescriptor *self, PyObject *value,
|
| + void *closure) {
|
| + return CheckCalledFromGeneratedFile("_options");
|
| +}
|
| +
|
| static PyGetSetDef Getters[] = {
|
| { "name", (getter)GetName, NULL, "Name"},
|
| { "full_name", (getter)GetFullName, NULL, "Full name"},
|
| { "index", (getter)GetIndex, NULL, "Index"},
|
|
|
| { "containing_type", (getter)GetContainingType, NULL, "Containing type"},
|
| + { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
|
| + { "_options", (getter)NULL, (setter)SetOptions, "Options"},
|
| { "fields", (getter)GetFields, NULL, "Fields"},
|
| {NULL}
|
| };
|
|
|
| +static PyMethodDef Methods[] = {
|
| + { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS },
|
| + {NULL}
|
| +};
|
| +
|
| } // namespace oneof_descriptor
|
|
|
| PyTypeObject PyOneofDescriptor_Type = {
|
| @@ -1492,7 +1541,7 @@ PyTypeObject PyOneofDescriptor_Type = {
|
| 0, // tp_weaklistoffset
|
| 0, // tp_iter
|
| 0, // tp_iternext
|
| - 0, // tp_methods
|
| + oneof_descriptor::Methods, // tp_methods
|
| 0, // tp_members
|
| oneof_descriptor::Getters, // tp_getset
|
| &descriptor::PyBaseDescriptor_Type, // tp_base
|
| @@ -1504,6 +1553,222 @@ PyObject* PyOneofDescriptor_FromDescriptor(
|
| &PyOneofDescriptor_Type, oneof_descriptor, NULL);
|
| }
|
|
|
| +namespace service_descriptor {
|
| +
|
| +// Unchecked accessor to the C++ pointer.
|
| +static const ServiceDescriptor* _GetDescriptor(
|
| + PyBaseDescriptor *self) {
|
| + return reinterpret_cast<const ServiceDescriptor*>(self->descriptor);
|
| +}
|
| +
|
| +static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
|
| + return PyString_FromCppString(_GetDescriptor(self)->name());
|
| +}
|
| +
|
| +static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
|
| + return PyString_FromCppString(_GetDescriptor(self)->full_name());
|
| +}
|
| +
|
| +static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
|
| + return PyInt_FromLong(_GetDescriptor(self)->index());
|
| +}
|
| +
|
| +static PyObject* GetMethods(PyBaseDescriptor* self, void *closure) {
|
| + return NewServiceMethodsSeq(_GetDescriptor(self));
|
| +}
|
| +
|
| +static PyObject* GetMethodsByName(PyBaseDescriptor* self, void *closure) {
|
| + return NewServiceMethodsByName(_GetDescriptor(self));
|
| +}
|
| +
|
| +static PyObject* FindMethodByName(PyBaseDescriptor *self, PyObject* arg) {
|
| + Py_ssize_t name_size;
|
| + char* name;
|
| + if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
|
| + return NULL;
|
| + }
|
| +
|
| + const MethodDescriptor* method_descriptor =
|
| + _GetDescriptor(self)->FindMethodByName(string(name, name_size));
|
| + if (method_descriptor == NULL) {
|
| + PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name);
|
| + return NULL;
|
| + }
|
| +
|
| + return PyMethodDescriptor_FromDescriptor(method_descriptor);
|
| +}
|
| +
|
| +static PyObject* GetOptions(PyBaseDescriptor *self) {
|
| + return GetOrBuildOptions(_GetDescriptor(self));
|
| +}
|
| +
|
| +static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
|
| + return CopyToPythonProto<ServiceDescriptorProto>(_GetDescriptor(self),
|
| + target);
|
| +}
|
| +
|
| +static PyGetSetDef Getters[] = {
|
| + { "name", (getter)GetName, NULL, "Name", NULL},
|
| + { "full_name", (getter)GetFullName, NULL, "Full name", NULL},
|
| + { "index", (getter)GetIndex, NULL, "Index", NULL},
|
| +
|
| + { "methods", (getter)GetMethods, NULL, "Methods", NULL},
|
| + { "methods_by_name", (getter)GetMethodsByName, NULL, "Methods by name", NULL},
|
| + {NULL}
|
| +};
|
| +
|
| +static PyMethodDef Methods[] = {
|
| + { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS },
|
| + { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
|
| + { "FindMethodByName", (PyCFunction)FindMethodByName, METH_O },
|
| + {NULL}
|
| +};
|
| +
|
| +} // namespace service_descriptor
|
| +
|
| +PyTypeObject PyServiceDescriptor_Type = {
|
| + PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
| + FULL_MODULE_NAME ".ServiceDescriptor", // tp_name
|
| + sizeof(PyBaseDescriptor), // tp_basicsize
|
| + 0, // tp_itemsize
|
| + 0, // tp_dealloc
|
| + 0, // tp_print
|
| + 0, // tp_getattr
|
| + 0, // tp_setattr
|
| + 0, // tp_compare
|
| + 0, // tp_repr
|
| + 0, // tp_as_number
|
| + 0, // tp_as_sequence
|
| + 0, // tp_as_mapping
|
| + 0, // tp_hash
|
| + 0, // tp_call
|
| + 0, // tp_str
|
| + 0, // tp_getattro
|
| + 0, // tp_setattro
|
| + 0, // tp_as_buffer
|
| + Py_TPFLAGS_DEFAULT, // tp_flags
|
| + "A Service Descriptor", // tp_doc
|
| + 0, // tp_traverse
|
| + 0, // tp_clear
|
| + 0, // tp_richcompare
|
| + 0, // tp_weaklistoffset
|
| + 0, // tp_iter
|
| + 0, // tp_iternext
|
| + service_descriptor::Methods, // tp_methods
|
| + 0, // tp_members
|
| + service_descriptor::Getters, // tp_getset
|
| + &descriptor::PyBaseDescriptor_Type, // tp_base
|
| +};
|
| +
|
| +PyObject* PyServiceDescriptor_FromDescriptor(
|
| + const ServiceDescriptor* service_descriptor) {
|
| + return descriptor::NewInternedDescriptor(
|
| + &PyServiceDescriptor_Type, service_descriptor, NULL);
|
| +}
|
| +
|
| +namespace method_descriptor {
|
| +
|
| +// Unchecked accessor to the C++ pointer.
|
| +static const MethodDescriptor* _GetDescriptor(
|
| + PyBaseDescriptor *self) {
|
| + return reinterpret_cast<const MethodDescriptor*>(self->descriptor);
|
| +}
|
| +
|
| +static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
|
| + return PyString_FromCppString(_GetDescriptor(self)->name());
|
| +}
|
| +
|
| +static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
|
| + return PyString_FromCppString(_GetDescriptor(self)->full_name());
|
| +}
|
| +
|
| +static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
|
| + return PyInt_FromLong(_GetDescriptor(self)->index());
|
| +}
|
| +
|
| +static PyObject* GetContainingService(PyBaseDescriptor *self, void *closure) {
|
| + const ServiceDescriptor* containing_service =
|
| + _GetDescriptor(self)->service();
|
| + return PyServiceDescriptor_FromDescriptor(containing_service);
|
| +}
|
| +
|
| +static PyObject* GetInputType(PyBaseDescriptor *self, void *closure) {
|
| + const Descriptor* input_type = _GetDescriptor(self)->input_type();
|
| + return PyMessageDescriptor_FromDescriptor(input_type);
|
| +}
|
| +
|
| +static PyObject* GetOutputType(PyBaseDescriptor *self, void *closure) {
|
| + const Descriptor* output_type = _GetDescriptor(self)->output_type();
|
| + return PyMessageDescriptor_FromDescriptor(output_type);
|
| +}
|
| +
|
| +static PyObject* GetOptions(PyBaseDescriptor *self) {
|
| + return GetOrBuildOptions(_GetDescriptor(self));
|
| +}
|
| +
|
| +static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
|
| + return CopyToPythonProto<MethodDescriptorProto>(_GetDescriptor(self), target);
|
| +}
|
| +
|
| +static PyGetSetDef Getters[] = {
|
| + { "name", (getter)GetName, NULL, "Name", NULL},
|
| + { "full_name", (getter)GetFullName, NULL, "Full name", NULL},
|
| + { "index", (getter)GetIndex, NULL, "Index", NULL},
|
| + { "containing_service", (getter)GetContainingService, NULL,
|
| + "Containing service", NULL},
|
| + { "input_type", (getter)GetInputType, NULL, "Input type", NULL},
|
| + { "output_type", (getter)GetOutputType, NULL, "Output type", NULL},
|
| + {NULL}
|
| +};
|
| +
|
| +static PyMethodDef Methods[] = {
|
| + { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
|
| + { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
|
| + {NULL}
|
| +};
|
| +
|
| +} // namespace method_descriptor
|
| +
|
| +PyTypeObject PyMethodDescriptor_Type = {
|
| + PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
| + FULL_MODULE_NAME ".MethodDescriptor", // tp_name
|
| + sizeof(PyBaseDescriptor), // tp_basicsize
|
| + 0, // tp_itemsize
|
| + 0, // tp_dealloc
|
| + 0, // tp_print
|
| + 0, // tp_getattr
|
| + 0, // tp_setattr
|
| + 0, // tp_compare
|
| + 0, // tp_repr
|
| + 0, // tp_as_number
|
| + 0, // tp_as_sequence
|
| + 0, // tp_as_mapping
|
| + 0, // tp_hash
|
| + 0, // tp_call
|
| + 0, // tp_str
|
| + 0, // tp_getattro
|
| + 0, // tp_setattro
|
| + 0, // tp_as_buffer
|
| + Py_TPFLAGS_DEFAULT, // tp_flags
|
| + "A Method Descriptor", // tp_doc
|
| + 0, // tp_traverse
|
| + 0, // tp_clear
|
| + 0, // tp_richcompare
|
| + 0, // tp_weaklistoffset
|
| + 0, // tp_iter
|
| + 0, // tp_iternext
|
| + method_descriptor::Methods, // tp_methods
|
| + 0, // tp_members
|
| + method_descriptor::Getters, // tp_getset
|
| + &descriptor::PyBaseDescriptor_Type, // tp_base
|
| +};
|
| +
|
| +PyObject* PyMethodDescriptor_FromDescriptor(
|
| + const MethodDescriptor* method_descriptor) {
|
| + return descriptor::NewInternedDescriptor(
|
| + &PyMethodDescriptor_Type, method_descriptor, NULL);
|
| +}
|
| +
|
| // Add a enum values to a type dictionary.
|
| static bool AddEnumValues(PyTypeObject *type,
|
| const EnumDescriptor* enum_descriptor) {
|
| @@ -1573,6 +1838,12 @@ bool InitDescriptor() {
|
| if (PyType_Ready(&PyOneofDescriptor_Type) < 0)
|
| return false;
|
|
|
| + if (PyType_Ready(&PyServiceDescriptor_Type) < 0)
|
| + return false;
|
| +
|
| + if (PyType_Ready(&PyMethodDescriptor_Type) < 0)
|
| + return false;
|
| +
|
| if (!InitDescriptorMappingTypes())
|
| return false;
|
|
|
|
|