33 #include <unordered_map>
35 #define PY_SSIZE_T_CLEAN
38 #include <google/protobuf/descriptor.pb.h>
39 #include <google/protobuf/pyext/descriptor.h>
40 #include <google/protobuf/pyext/descriptor_database.h>
41 #include <google/protobuf/pyext/descriptor_pool.h>
42 #include <google/protobuf/pyext/message.h>
43 #include <google/protobuf/pyext/message_factory.h>
44 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
45 #include <google/protobuf/stubs/hash.h>
47 #define PyString_AsStringAndSize(ob, charpp, sizep) \
48 (PyUnicode_Check(ob) ? ((*(charpp) = const_cast<char*>( \
49 PyUnicode_AsUTF8AndSize(ob, (sizep)))) == NULL \
52 : PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
60 static std::unordered_map<const DescriptorPool*, PyDescriptorPool*>*
63 namespace cdescriptor_pool {
67 class BuildFileErrorCollector :
public DescriptorPool::ErrorCollector {
78 (
"Invalid proto descriptor for file \"" +
filename +
"\":\n");
121 PyObject_GC_Track(cpool);
143 std::make_pair(cpool->
pool, cpool)).second) {
145 PyErr_SetString(PyExc_ValueError,
"DescriptorPool already registered");
171 PyErr_SetString(PyExc_ValueError,
"DescriptorPool already registered");
180 PyObject*
args, PyObject* kwargs) {
181 static const char* kwlist[] = {
"descriptor_db", 0};
182 PyObject* py_database = NULL;
183 if (!PyArg_ParseTupleAndKeywords(
args, kwargs,
"|O",
184 const_cast<char**
>(kwlist), &py_database)) {
188 if (py_database && py_database != Py_None) {
191 return reinterpret_cast<PyObject*
>(
198 Py_CLEAR(
self->py_message_factory);
200 self->descriptor_options->begin();
201 it !=
self->descriptor_options->end(); ++
it) {
202 Py_DECREF(
it->second);
204 delete self->descriptor_options;
205 delete self->database;
206 if (
self->is_owned) {
209 delete self->error_collector;
215 Py_VISIT(
self->py_message_factory);
221 Py_CLEAR(
self->py_message_factory);
226 const char*
name,
const char* error_type) {
229 if (error_collector && !error_collector->error_message.empty()) {
230 PyErr_Format(PyExc_KeyError,
"Couldn't build file for %s %.200s\n%s",
231 error_type,
name, error_collector->error_message.c_str());
232 error_collector->Clear();
235 PyErr_Format(PyExc_KeyError,
"Couldn't find %s %.200s", error_type,
name);
240 Py_ssize_t name_size;
250 if (message_descriptor == NULL) {
264 Py_ssize_t name_size;
274 if (file_descriptor == NULL) {
281 Py_ssize_t name_size;
289 if (field_descriptor == NULL) {
302 Py_ssize_t name_size;
310 if (field_descriptor == NULL) {
324 Py_ssize_t name_size;
345 Py_ssize_t name_size;
353 if (oneof_descriptor == NULL) {
366 Py_ssize_t name_size;
375 if (service_descriptor == NULL) {
386 Py_ssize_t name_size;
395 if (method_descriptor == NULL) {
406 Py_ssize_t name_size;
415 if (file_descriptor == NULL) {
426 PyObject* message_descriptor;
428 if (!PyArg_ParseTuple(
args,
"Oi", &message_descriptor, &
number)) {
440 if (extension_descriptor == NULL) {
444 if (error_collector && !error_collector->error_message.empty()) {
445 PyErr_Format(PyExc_KeyError,
"Couldn't build file for Extension %.d\n%s",
446 number, error_collector->error_message.c_str());
447 error_collector->Clear();
450 PyErr_Format(PyExc_KeyError,
"Couldn't find Extension %d",
number);
464 std::vector<const FieldDescriptor*>
extensions;
494 if (!file_descriptor) {
497 if (file_descriptor !=
499 file_descriptor->
name())) {
500 PyErr_Format(PyExc_ValueError,
501 "The file descriptor %s does not belong to this pool",
502 file_descriptor->
name().c_str());
511 if (!message_descriptor) {
514 if (message_descriptor !=
517 PyErr_Format(PyExc_ValueError,
518 "The message descriptor %s does not belong to this pool",
519 message_descriptor->
full_name().c_str());
534 PyErr_Format(PyExc_ValueError,
535 "The enum descriptor %s does not belong to this pool",
545 if (!extension_descriptor) {
548 if (extension_descriptor !=
551 PyErr_Format(PyExc_ValueError,
552 "The extension descriptor %s does not belong to this pool",
553 extension_descriptor->
full_name().c_str());
562 if (!service_descriptor) {
565 if (service_descriptor !=
568 PyErr_Format(PyExc_ValueError,
569 "The service descriptor %s does not belong to this pool",
570 service_descriptor->
full_name().c_str());
580 Py_ssize_t message_len;
582 if (
self->database != NULL) {
585 "Cannot call Add on a DescriptorPool that uses a DescriptorDatabase. "
586 "Add your file to the underlying database.");
589 if (!
self->is_mutable) {
592 "This DescriptorPool is not mutable and cannot add new definitions.");
596 if (PyBytes_AsStringAndSize(serialized_pb, &
message_type, &message_len) < 0) {
601 if (!file_proto.ParseFromArray(
message_type, message_len)) {
602 PyErr_SetString(PyExc_TypeError,
"Couldn't parse file content!");
609 if (
self->underlay) {
610 generated_file =
self->underlay->FindFileByName(file_proto.
name());
612 if (generated_file != NULL) {
614 generated_file, serialized_pb);
621 ->BuildFileCollectingErrors(file_proto, &error_collector);
623 PyErr_Format(PyExc_TypeError,
624 "Couldn't build proto file into descriptor pool!\n%s",
625 error_collector.error_message.c_str());
634 static PyObject*
Add(PyObject*
self, PyObject* file_descriptor_proto) {
636 PyObject_CallMethod(file_descriptor_proto,
"SerializeToString", NULL));
637 if (serialized_pb == NULL) {
644 {
"Add",
Add, METH_O,
645 "Adds the FileDescriptorProto and its types to this pool." },
647 "Adds a serialized FileDescriptorProto to this pool." },
652 "No-op. Add() must have been called before." },
654 "No-op. Add() must have been called before." },
656 "No-op. Add() must have been called before." },
658 "No-op. Add() must have been called before." },
660 "No-op. Add() must have been called before." },
663 "Searches for a file descriptor by its .proto name." },
665 "Searches for a message descriptor by full name." },
667 "Searches for a field descriptor by full name." },
669 "Searches for extension descriptor by full name." },
671 "Searches for enum type descriptor by full name." },
673 "Searches for oneof descriptor by full name." },
675 "Searches for service descriptor by full name." },
677 "Searches for method descriptor by full name." },
680 "Gets the FileDescriptor containing the specified symbol." },
682 "Gets the extension descriptor for the given number." },
684 "Gets all known extensions of the given message descriptor." },
710 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
728 cdescriptor_pool::
New,
744 new std::unordered_map<const DescriptorPool*, PyDescriptorPool*>;
777 PyErr_SetString(PyExc_KeyError,
"Unknown descriptor pool");
785 if (existing_pool !=
nullptr) {
786 Py_INCREF(existing_pool);
787 return reinterpret_cast<PyObject*
>(existing_pool);
793 if (cpool ==
nullptr) {
803 PyErr_SetString(PyExc_ValueError,
"DescriptorPool already registered");
807 return reinterpret_cast<PyObject*
>(cpool);