Index: third_party/protobuf/python/google/protobuf/pyext/descriptor_pool.cc |
diff --git a/third_party/protobuf/python/google/protobuf/pyext/descriptor_pool.cc b/third_party/protobuf/python/google/protobuf/pyext/descriptor_pool.cc |
index 1faff96bc2e44c40a3aa8da0550f947cd67b40df..fa66bf9ace7091c59d36db93f463d27c8a3557e8 100644 |
--- a/third_party/protobuf/python/google/protobuf/pyext/descriptor_pool.cc |
+++ b/third_party/protobuf/python/google/protobuf/pyext/descriptor_pool.cc |
@@ -33,11 +33,11 @@ |
#include <Python.h> |
#include <google/protobuf/descriptor.pb.h> |
-#include <google/protobuf/dynamic_message.h> |
#include <google/protobuf/pyext/descriptor.h> |
#include <google/protobuf/pyext/descriptor_database.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 |
@@ -73,18 +73,16 @@ static PyDescriptorPool* _CreateDescriptorPool() { |
cpool->underlay = NULL; |
cpool->database = NULL; |
- DynamicMessageFactory* message_factory = new DynamicMessageFactory(); |
- // This option might be the default some day. |
- message_factory->SetDelegateToGeneratedFactory(true); |
- cpool->message_factory = message_factory; |
- |
- // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same |
- // storage. |
- cpool->classes_by_descriptor = |
- new PyDescriptorPool::ClassesByMessageMap(); |
cpool->descriptor_options = |
new hash_map<const void*, PyObject *>(); |
+ cpool->py_message_factory = message_factory::NewMessageFactory( |
+ &PyMessageFactory_Type, cpool); |
+ if (cpool->py_message_factory == NULL) { |
+ Py_DECREF(cpool); |
+ return NULL; |
+ } |
+ |
return cpool; |
} |
@@ -151,20 +149,14 @@ static PyObject* New(PyTypeObject* type, |
} |
static void Dealloc(PyDescriptorPool* self) { |
- typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; |
descriptor_pool_map.erase(self->pool); |
- for (iterator it = self->classes_by_descriptor->begin(); |
- it != self->classes_by_descriptor->end(); ++it) { |
- Py_DECREF(it->second); |
- } |
- delete self->classes_by_descriptor; |
+ Py_CLEAR(self->py_message_factory); |
for (hash_map<const void*, PyObject*>::iterator it = |
self->descriptor_options->begin(); |
it != self->descriptor_options->end(); ++it) { |
Py_DECREF(it->second); |
} |
delete self->descriptor_options; |
- delete self->message_factory; |
delete self->database; |
delete self->pool; |
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); |
@@ -188,35 +180,8 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) { |
return PyMessageDescriptor_FromDescriptor(message_descriptor); |
} |
-// Add a message class to our database. |
-int RegisterMessageClass(PyDescriptorPool* self, |
- const Descriptor* message_descriptor, |
- CMessageClass* message_class) { |
- Py_INCREF(message_class); |
- typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; |
- std::pair<iterator, bool> ret = self->classes_by_descriptor->insert( |
- std::make_pair(message_descriptor, message_class)); |
- if (!ret.second) { |
- // Update case: DECREF the previous value. |
- Py_DECREF(ret.first->second); |
- ret.first->second = message_class; |
- } |
- return 0; |
-} |
-// Retrieve the message class added to our database. |
-CMessageClass* GetMessageClass(PyDescriptorPool* self, |
- const Descriptor* message_descriptor) { |
- typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; |
- iterator ret = self->classes_by_descriptor->find(message_descriptor); |
- if (ret == self->classes_by_descriptor->end()) { |
- PyErr_Format(PyExc_TypeError, "No message class registered for '%s'", |
- message_descriptor->full_name().c_str()); |
- return NULL; |
- } else { |
- return ret->second; |
- } |
-} |
+ |
PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) { |
Py_ssize_t name_size; |
@@ -228,11 +193,9 @@ PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) { |
const FileDescriptor* file_descriptor = |
self->pool->FindFileByName(string(name, name_size)); |
if (file_descriptor == NULL) { |
- PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s", |
- name); |
+ PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s", name); |
return NULL; |
} |
- |
return PyFileDescriptor_FromDescriptor(file_descriptor); |
} |
@@ -305,6 +268,40 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) { |
return PyOneofDescriptor_FromDescriptor(oneof_descriptor); |
} |
+PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) { |
+ Py_ssize_t name_size; |
+ char* name; |
+ if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { |
+ return NULL; |
+ } |
+ |
+ const ServiceDescriptor* service_descriptor = |
+ self->pool->FindServiceByName(string(name, name_size)); |
+ if (service_descriptor == NULL) { |
+ PyErr_Format(PyExc_KeyError, "Couldn't find service %.200s", name); |
+ return NULL; |
+ } |
+ |
+ return PyServiceDescriptor_FromDescriptor(service_descriptor); |
+} |
+ |
+PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) { |
+ Py_ssize_t name_size; |
+ char* name; |
+ if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { |
+ return NULL; |
+ } |
+ |
+ const MethodDescriptor* method_descriptor = |
+ self->pool->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); |
+} |
+ |
PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) { |
Py_ssize_t name_size; |
char* name; |
@@ -322,6 +319,51 @@ PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) { |
return PyFileDescriptor_FromDescriptor(file_descriptor); |
} |
+PyObject* FindExtensionByNumber(PyDescriptorPool* self, PyObject* args) { |
+ PyObject* message_descriptor; |
+ int number; |
+ if (!PyArg_ParseTuple(args, "Oi", &message_descriptor, &number)) { |
+ return NULL; |
+ } |
+ const Descriptor* descriptor = PyMessageDescriptor_AsDescriptor( |
+ message_descriptor); |
+ if (descriptor == NULL) { |
+ return NULL; |
+ } |
+ |
+ const FieldDescriptor* extension_descriptor = |
+ self->pool->FindExtensionByNumber(descriptor, number); |
+ if (extension_descriptor == NULL) { |
+ PyErr_Format(PyExc_KeyError, "Couldn't find extension %d", number); |
+ return NULL; |
+ } |
+ |
+ return PyFieldDescriptor_FromDescriptor(extension_descriptor); |
+} |
+ |
+PyObject* FindAllExtensions(PyDescriptorPool* self, PyObject* arg) { |
+ const Descriptor* descriptor = PyMessageDescriptor_AsDescriptor(arg); |
+ if (descriptor == NULL) { |
+ return NULL; |
+ } |
+ |
+ std::vector<const FieldDescriptor*> extensions; |
+ self->pool->FindAllExtensions(descriptor, &extensions); |
+ |
+ ScopedPyObjectPtr result(PyList_New(extensions.size())); |
+ if (result == NULL) { |
+ return NULL; |
+ } |
+ for (int i = 0; i < extensions.size(); i++) { |
+ PyObject* extension = PyFieldDescriptor_FromDescriptor(extensions[i]); |
+ if (extension == NULL) { |
+ return NULL; |
+ } |
+ PyList_SET_ITEM(result.get(), i, extension); // Steals the reference. |
+ } |
+ return result.release(); |
+} |
+ |
// These functions should not exist -- the only valid way to create |
// descriptors is to call Add() or AddSerializedFile(). |
// But these AddDescriptor() functions were created in Python and some people |
@@ -379,6 +421,22 @@ PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) { |
Py_RETURN_NONE; |
} |
+PyObject* AddExtensionDescriptor(PyDescriptorPool* self, PyObject* descriptor) { |
+ const FieldDescriptor* extension_descriptor = |
+ PyFieldDescriptor_AsDescriptor(descriptor); |
+ if (!extension_descriptor) { |
+ return NULL; |
+ } |
+ if (extension_descriptor != |
+ self->pool->FindExtensionByName(extension_descriptor->full_name())) { |
+ PyErr_Format(PyExc_ValueError, |
+ "The extension descriptor %s does not belong to this pool", |
+ extension_descriptor->full_name().c_str()); |
+ return NULL; |
+ } |
+ Py_RETURN_NONE; |
+} |
+ |
// The code below loads new Descriptors from a serialized FileDescriptorProto. |
@@ -478,6 +536,8 @@ static PyMethodDef Methods[] = { |
"No-op. Add() must have been called before." }, |
{ "AddEnumDescriptor", (PyCFunction)AddEnumDescriptor, METH_O, |
"No-op. Add() must have been called before." }, |
+ { "AddExtensionDescriptor", (PyCFunction)AddExtensionDescriptor, METH_O, |
+ "No-op. Add() must have been called before." }, |
{ "FindFileByName", (PyCFunction)FindFileByName, METH_O, |
"Searches for a file descriptor by its .proto name." }, |
@@ -491,9 +551,17 @@ static PyMethodDef Methods[] = { |
"Searches for enum type descriptor by full name." }, |
{ "FindOneofByName", (PyCFunction)FindOneofByName, METH_O, |
"Searches for oneof descriptor by full name." }, |
+ { "FindServiceByName", (PyCFunction)FindServiceByName, METH_O, |
+ "Searches for service descriptor by full name." }, |
+ { "FindMethodByName", (PyCFunction)FindMethodByName, METH_O, |
+ "Searches for method descriptor by full name." }, |
{ "FindFileContainingSymbol", (PyCFunction)FindFileContainingSymbol, METH_O, |
"Gets the FileDescriptor containing the specified symbol." }, |
+ { "FindExtensionByNumber", (PyCFunction)FindExtensionByNumber, METH_VARARGS, |
+ "Gets the extension descriptor for the given number." }, |
+ { "FindAllExtensions", (PyCFunction)FindAllExtensions, METH_O, |
+ "Gets all known extensions of the given message descriptor." }, |
{NULL} |
}; |