diff --git a/python/descriptor.c b/python/descriptor.c index 7c8254baeba29..da78bf4b47462 100644 --- a/python/descriptor.c +++ b/python/descriptor.c @@ -1527,6 +1527,12 @@ static PyObject* PyUpb_MethodDescriptor_GetServerStreaming(PyObject* self, return PyBool_FromLong(upb_MethodDef_ServerStreaming(m) ? 1 : 0); } +static PyObject* PyUpb_MethodDescriptor_GetHasOptions(PyObject* _self, + void* closure) { + PyUpb_DescriptorBase* self = (void*)_self; + return PyBool_FromLong(upb_MethodDef_HasOptions(self->def)); +} + static PyObject* PyUpb_MethodDescriptor_GetOptions(PyObject* _self, PyObject* args) { PyUpb_DescriptorBase* self = (void*)_self; @@ -1565,6 +1571,8 @@ static PyGetSetDef PyUpb_MethodDescriptor_Getters[] = { "Client streaming", NULL}, {"server_streaming", PyUpb_MethodDescriptor_GetServerStreaming, NULL, "Server streaming", NULL}, + {"has_options", PyUpb_MethodDescriptor_GetHasOptions, NULL, "Has Options"}, + {NULL}}; static PyMethodDef PyUpb_MethodDescriptor_Methods[] = { @@ -1754,6 +1762,12 @@ static PyObject* PyUpb_ServiceDescriptor_GetMethodsByName(PyObject* _self, return PyUpb_ByNameMap_New(&funcs, self->def, self->pool); } +static PyObject* PyUpb_ServiceDescriptor_GetHasOptions(PyObject* _self, + void* closure) { + PyUpb_DescriptorBase* self = (void*)_self; + return PyBool_FromLong(upb_ServiceDef_HasOptions(self->def)); +} + static PyObject* PyUpb_ServiceDescriptor_GetOptions(PyObject* _self, PyObject* args) { PyUpb_DescriptorBase* self = (void*)_self; @@ -1799,6 +1813,7 @@ static PyGetSetDef PyUpb_ServiceDescriptor_Getters[] = { {"methods", PyUpb_ServiceDescriptor_GetMethods, NULL, "Methods", NULL}, {"methods_by_name", PyUpb_ServiceDescriptor_GetMethodsByName, NULL, "Methods by name", NULL}, + {"has_options", PyUpb_ServiceDescriptor_GetHasOptions, NULL, "Has Options"}, {NULL}}; static PyMethodDef PyUpb_ServiceDescriptor_Methods[] = { diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py index ff0181345b0c4..222a936d26ba3 100755 --- a/python/google/protobuf/internal/descriptor_test.py +++ b/python/google/protobuf/internal/descriptor_test.py @@ -289,6 +289,7 @@ def testSimpleCustomOptions(self): service_options = service_descriptor.GetOptions() service_opt1 = unittest_custom_options_pb2.service_opt1 self.assertEqual(-9876543210, service_options.Extensions[service_opt1]) + self.assertTrue(method_descriptor.has_options) method_options = method_descriptor.GetOptions() method_opt1 = unittest_custom_options_pb2.method_opt1 self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2, @@ -792,6 +793,7 @@ def testServiceDescriptor(self): self.assertIs(service_descriptor.file, unittest_pb2.DESCRIPTOR) self.assertEqual(service_descriptor.index, 0) self.CheckDescriptorMapping(service_descriptor.methods_by_name) + self.assertFalse(service_descriptor.has_options) def testOneofDescriptor(self): message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index 767a86f0a0209..490c762a95b5e 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -1832,6 +1832,15 @@ static PyObject* FindMethodByName(PyBaseDescriptor *self, PyObject* arg) { return PyMethodDescriptor_FromDescriptor(method_descriptor); } +static PyObject* GetHasOptions(PyBaseDescriptor* self, void* closure) { + const ServiceOptions& options = _GetDescriptor(self)->options(); + if (&options != &ServiceOptions::default_instance()) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + static PyObject* GetOptions(PyBaseDescriptor *self) { return GetOrBuildOptions(_GetDescriptor(self)); } @@ -1853,6 +1862,7 @@ static PyGetSetDef Getters[] = { {"methods", (getter)GetMethods, nullptr, "Methods", nullptr}, {"methods_by_name", (getter)GetMethodsByName, nullptr, "Methods by name", nullptr}, + {"has_options", (getter)GetHasOptions, nullptr}, {nullptr}, }; @@ -1963,6 +1973,15 @@ static PyObject* GetServerStreaming(PyBaseDescriptor* self, void* closure) { return PyBool_FromLong(_GetDescriptor(self)->server_streaming() ? 1 : 0); } +static PyObject* GetHasOptions(PyBaseDescriptor* self, void* closure) { + const MethodOptions& options = _GetDescriptor(self)->options(); + if (&options != &MethodOptions::default_instance()) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + static PyObject* GetOptions(PyBaseDescriptor *self) { return GetOrBuildOptions(_GetDescriptor(self)); } @@ -1987,6 +2006,7 @@ static PyGetSetDef Getters[] = { "Client streaming", nullptr}, {"server_streaming", (getter)GetServerStreaming, nullptr, "Server streaming", nullptr}, + {"has_options", (getter)GetHasOptions, nullptr}, {nullptr}, };