• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Implements the DescriptorPool, which collects all descriptors.
32 
33 #include <Python.h>
34 
35 #include <google/protobuf/descriptor.pb.h>
36 #include <google/protobuf/dynamic_message.h>
37 #include <google/protobuf/pyext/descriptor.h>
38 #include <google/protobuf/pyext/descriptor_database.h>
39 #include <google/protobuf/pyext/descriptor_pool.h>
40 #include <google/protobuf/pyext/message.h>
41 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
42 
43 #if PY_MAJOR_VERSION >= 3
44   #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
45   #if PY_VERSION_HEX < 0x03030000
46     #error "Python 3.0 - 3.2 are not supported."
47   #endif
48   #define PyString_AsStringAndSize(ob, charpp, sizep) \
49     (PyUnicode_Check(ob)? \
50        ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
51        PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
52 #endif
53 
54 namespace google {
55 namespace protobuf {
56 namespace python {
57 
58 // A map to cache Python Pools per C++ pointer.
59 // Pointers are not owned here, and belong to the PyDescriptorPool.
60 static hash_map<const DescriptorPool*, PyDescriptorPool*> descriptor_pool_map;
61 
62 namespace cdescriptor_pool {
63 
64 // Create a Python DescriptorPool object, but does not fill the "pool"
65 // attribute.
_CreateDescriptorPool()66 static PyDescriptorPool* _CreateDescriptorPool() {
67   PyDescriptorPool* cpool = PyObject_New(
68       PyDescriptorPool, &PyDescriptorPool_Type);
69   if (cpool == NULL) {
70     return NULL;
71   }
72 
73   cpool->underlay = NULL;
74   cpool->database = NULL;
75 
76   DynamicMessageFactory* message_factory = new DynamicMessageFactory();
77   // This option might be the default some day.
78   message_factory->SetDelegateToGeneratedFactory(true);
79   cpool->message_factory = message_factory;
80 
81   // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same
82   // storage.
83   cpool->classes_by_descriptor =
84       new PyDescriptorPool::ClassesByMessageMap();
85   cpool->descriptor_options =
86       new hash_map<const void*, PyObject *>();
87 
88   return cpool;
89 }
90 
91 // Create a Python DescriptorPool, using the given pool as an underlay:
92 // new messages will be added to a custom pool, not to the underlay.
93 //
94 // Ownership of the underlay is not transferred, its pointer should
95 // stay alive.
PyDescriptorPool_NewWithUnderlay(const DescriptorPool * underlay)96 static PyDescriptorPool* PyDescriptorPool_NewWithUnderlay(
97     const DescriptorPool* underlay) {
98   PyDescriptorPool* cpool = _CreateDescriptorPool();
99   if (cpool == NULL) {
100     return NULL;
101   }
102   cpool->pool = new DescriptorPool(underlay);
103   cpool->underlay = underlay;
104 
105   if (!descriptor_pool_map.insert(
106       std::make_pair(cpool->pool, cpool)).second) {
107     // Should never happen -- would indicate an internal error / bug.
108     PyErr_SetString(PyExc_ValueError, "DescriptorPool already registered");
109     return NULL;
110   }
111 
112   return cpool;
113 }
114 
PyDescriptorPool_NewWithDatabase(DescriptorDatabase * database)115 static PyDescriptorPool* PyDescriptorPool_NewWithDatabase(
116     DescriptorDatabase* database) {
117   PyDescriptorPool* cpool = _CreateDescriptorPool();
118   if (cpool == NULL) {
119     return NULL;
120   }
121   if (database != NULL) {
122     cpool->pool = new DescriptorPool(database);
123     cpool->database = database;
124   } else {
125     cpool->pool = new DescriptorPool();
126   }
127 
128   if (!descriptor_pool_map.insert(std::make_pair(cpool->pool, cpool)).second) {
129     // Should never happen -- would indicate an internal error / bug.
130     PyErr_SetString(PyExc_ValueError, "DescriptorPool already registered");
131     return NULL;
132   }
133 
134   return cpool;
135 }
136 
137 // The public DescriptorPool constructor.
New(PyTypeObject * type,PyObject * args,PyObject * kwargs)138 static PyObject* New(PyTypeObject* type,
139                      PyObject* args, PyObject* kwargs) {
140   static char* kwlist[] = {"descriptor_db", 0};
141   PyObject* py_database = NULL;
142   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &py_database)) {
143     return NULL;
144   }
145   DescriptorDatabase* database = NULL;
146   if (py_database && py_database != Py_None) {
147     database = new PyDescriptorDatabase(py_database);
148   }
149   return reinterpret_cast<PyObject*>(
150       PyDescriptorPool_NewWithDatabase(database));
151 }
152 
Dealloc(PyDescriptorPool * self)153 static void Dealloc(PyDescriptorPool* self) {
154   typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
155   descriptor_pool_map.erase(self->pool);
156   for (iterator it = self->classes_by_descriptor->begin();
157        it != self->classes_by_descriptor->end(); ++it) {
158     Py_DECREF(it->second);
159   }
160   delete self->classes_by_descriptor;
161   for (hash_map<const void*, PyObject*>::iterator it =
162            self->descriptor_options->begin();
163        it != self->descriptor_options->end(); ++it) {
164     Py_DECREF(it->second);
165   }
166   delete self->descriptor_options;
167   delete self->message_factory;
168   delete self->database;
169   delete self->pool;
170   Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
171 }
172 
FindMessageByName(PyDescriptorPool * self,PyObject * arg)173 PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
174   Py_ssize_t name_size;
175   char* name;
176   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
177     return NULL;
178   }
179 
180   const Descriptor* message_descriptor =
181       self->pool->FindMessageTypeByName(string(name, name_size));
182 
183   if (message_descriptor == NULL) {
184     PyErr_Format(PyExc_KeyError, "Couldn't find message %.200s", name);
185     return NULL;
186   }
187 
188   return PyMessageDescriptor_FromDescriptor(message_descriptor);
189 }
190 
191 // Add a message class to our database.
RegisterMessageClass(PyDescriptorPool * self,const Descriptor * message_descriptor,CMessageClass * message_class)192 int RegisterMessageClass(PyDescriptorPool* self,
193                          const Descriptor* message_descriptor,
194                          CMessageClass* message_class) {
195   Py_INCREF(message_class);
196   typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
197   std::pair<iterator, bool> ret = self->classes_by_descriptor->insert(
198       std::make_pair(message_descriptor, message_class));
199   if (!ret.second) {
200     // Update case: DECREF the previous value.
201     Py_DECREF(ret.first->second);
202     ret.first->second = message_class;
203   }
204   return 0;
205 }
206 
207 // Retrieve the message class added to our database.
GetMessageClass(PyDescriptorPool * self,const Descriptor * message_descriptor)208 CMessageClass* GetMessageClass(PyDescriptorPool* self,
209                                const Descriptor* message_descriptor) {
210   typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
211   iterator ret = self->classes_by_descriptor->find(message_descriptor);
212   if (ret == self->classes_by_descriptor->end()) {
213     PyErr_Format(PyExc_TypeError, "No message class registered for '%s'",
214                  message_descriptor->full_name().c_str());
215     return NULL;
216   } else {
217     return ret->second;
218   }
219 }
220 
FindFileByName(PyDescriptorPool * self,PyObject * arg)221 PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) {
222   Py_ssize_t name_size;
223   char* name;
224   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
225     return NULL;
226   }
227 
228   const FileDescriptor* file_descriptor =
229       self->pool->FindFileByName(string(name, name_size));
230   if (file_descriptor == NULL) {
231     PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s",
232                  name);
233     return NULL;
234   }
235 
236   return PyFileDescriptor_FromDescriptor(file_descriptor);
237 }
238 
FindFieldByName(PyDescriptorPool * self,PyObject * arg)239 PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) {
240   Py_ssize_t name_size;
241   char* name;
242   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
243     return NULL;
244   }
245 
246   const FieldDescriptor* field_descriptor =
247       self->pool->FindFieldByName(string(name, name_size));
248   if (field_descriptor == NULL) {
249     PyErr_Format(PyExc_KeyError, "Couldn't find field %.200s",
250                  name);
251     return NULL;
252   }
253 
254   return PyFieldDescriptor_FromDescriptor(field_descriptor);
255 }
256 
FindExtensionByName(PyDescriptorPool * self,PyObject * arg)257 PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
258   Py_ssize_t name_size;
259   char* name;
260   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
261     return NULL;
262   }
263 
264   const FieldDescriptor* field_descriptor =
265       self->pool->FindExtensionByName(string(name, name_size));
266   if (field_descriptor == NULL) {
267     PyErr_Format(PyExc_KeyError, "Couldn't find extension field %.200s", name);
268     return NULL;
269   }
270 
271   return PyFieldDescriptor_FromDescriptor(field_descriptor);
272 }
273 
FindEnumTypeByName(PyDescriptorPool * self,PyObject * arg)274 PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) {
275   Py_ssize_t name_size;
276   char* name;
277   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
278     return NULL;
279   }
280 
281   const EnumDescriptor* enum_descriptor =
282       self->pool->FindEnumTypeByName(string(name, name_size));
283   if (enum_descriptor == NULL) {
284     PyErr_Format(PyExc_KeyError, "Couldn't find enum %.200s", name);
285     return NULL;
286   }
287 
288   return PyEnumDescriptor_FromDescriptor(enum_descriptor);
289 }
290 
FindOneofByName(PyDescriptorPool * self,PyObject * arg)291 PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
292   Py_ssize_t name_size;
293   char* name;
294   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
295     return NULL;
296   }
297 
298   const OneofDescriptor* oneof_descriptor =
299       self->pool->FindOneofByName(string(name, name_size));
300   if (oneof_descriptor == NULL) {
301     PyErr_Format(PyExc_KeyError, "Couldn't find oneof %.200s", name);
302     return NULL;
303   }
304 
305   return PyOneofDescriptor_FromDescriptor(oneof_descriptor);
306 }
307 
FindServiceByName(PyDescriptorPool * self,PyObject * arg)308 PyObject* FindServiceByName(PyDescriptorPool* self, PyObject* arg) {
309   Py_ssize_t name_size;
310   char* name;
311   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
312     return NULL;
313   }
314 
315   const ServiceDescriptor* service_descriptor =
316       self->pool->FindServiceByName(string(name, name_size));
317   if (service_descriptor == NULL) {
318     PyErr_Format(PyExc_KeyError, "Couldn't find service %.200s", name);
319     return NULL;
320   }
321 
322   return PyServiceDescriptor_FromDescriptor(service_descriptor);
323 }
324 
FindMethodByName(PyDescriptorPool * self,PyObject * arg)325 PyObject* FindMethodByName(PyDescriptorPool* self, PyObject* arg) {
326   Py_ssize_t name_size;
327   char* name;
328   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
329     return NULL;
330   }
331 
332   const MethodDescriptor* method_descriptor =
333       self->pool->FindMethodByName(string(name, name_size));
334   if (method_descriptor == NULL) {
335     PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name);
336     return NULL;
337   }
338 
339   return PyMethodDescriptor_FromDescriptor(method_descriptor);
340 }
341 
FindFileContainingSymbol(PyDescriptorPool * self,PyObject * arg)342 PyObject* FindFileContainingSymbol(PyDescriptorPool* self, PyObject* arg) {
343   Py_ssize_t name_size;
344   char* name;
345   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
346     return NULL;
347   }
348 
349   const FileDescriptor* file_descriptor =
350       self->pool->FindFileContainingSymbol(string(name, name_size));
351   if (file_descriptor == NULL) {
352     PyErr_Format(PyExc_KeyError, "Couldn't find symbol %.200s", name);
353     return NULL;
354   }
355 
356   return PyFileDescriptor_FromDescriptor(file_descriptor);
357 }
358 
359 // These functions should not exist -- the only valid way to create
360 // descriptors is to call Add() or AddSerializedFile().
361 // But these AddDescriptor() functions were created in Python and some people
362 // call them, so we support them for now for compatibility.
363 // However we do check that the existing descriptor already exists in the pool,
364 // which appears to always be true for existing calls -- but then why do people
365 // call a function that will just be a no-op?
366 // TODO(amauryfa): Need to investigate further.
367 
AddFileDescriptor(PyDescriptorPool * self,PyObject * descriptor)368 PyObject* AddFileDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
369   const FileDescriptor* file_descriptor =
370       PyFileDescriptor_AsDescriptor(descriptor);
371   if (!file_descriptor) {
372     return NULL;
373   }
374   if (file_descriptor !=
375       self->pool->FindFileByName(file_descriptor->name())) {
376     PyErr_Format(PyExc_ValueError,
377                  "The file descriptor %s does not belong to this pool",
378                  file_descriptor->name().c_str());
379     return NULL;
380   }
381   Py_RETURN_NONE;
382 }
383 
AddDescriptor(PyDescriptorPool * self,PyObject * descriptor)384 PyObject* AddDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
385   const Descriptor* message_descriptor =
386       PyMessageDescriptor_AsDescriptor(descriptor);
387   if (!message_descriptor) {
388     return NULL;
389   }
390   if (message_descriptor !=
391       self->pool->FindMessageTypeByName(message_descriptor->full_name())) {
392     PyErr_Format(PyExc_ValueError,
393                  "The message descriptor %s does not belong to this pool",
394                  message_descriptor->full_name().c_str());
395     return NULL;
396   }
397   Py_RETURN_NONE;
398 }
399 
AddEnumDescriptor(PyDescriptorPool * self,PyObject * descriptor)400 PyObject* AddEnumDescriptor(PyDescriptorPool* self, PyObject* descriptor) {
401   const EnumDescriptor* enum_descriptor =
402       PyEnumDescriptor_AsDescriptor(descriptor);
403   if (!enum_descriptor) {
404     return NULL;
405   }
406   if (enum_descriptor !=
407       self->pool->FindEnumTypeByName(enum_descriptor->full_name())) {
408     PyErr_Format(PyExc_ValueError,
409                  "The enum descriptor %s does not belong to this pool",
410                  enum_descriptor->full_name().c_str());
411     return NULL;
412   }
413   Py_RETURN_NONE;
414 }
415 
416 // The code below loads new Descriptors from a serialized FileDescriptorProto.
417 
418 
419 // Collects errors that occur during proto file building to allow them to be
420 // propagated in the python exception instead of only living in ERROR logs.
421 class BuildFileErrorCollector : public DescriptorPool::ErrorCollector {
422  public:
BuildFileErrorCollector()423   BuildFileErrorCollector() : error_message(""), had_errors(false) {}
424 
AddError(const string & filename,const string & element_name,const Message * descriptor,ErrorLocation location,const string & message)425   void AddError(const string& filename, const string& element_name,
426                 const Message* descriptor, ErrorLocation location,
427                 const string& message) {
428     // Replicates the logging behavior that happens in the C++ implementation
429     // when an error collector is not passed in.
430     if (!had_errors) {
431       error_message +=
432           ("Invalid proto descriptor for file \"" + filename + "\":\n");
433       had_errors = true;
434     }
435     // As this only happens on failure and will result in the program not
436     // running at all, no effort is made to optimize this string manipulation.
437     error_message += ("  " + element_name + ": " + message + "\n");
438   }
439 
440   string error_message;
441   bool had_errors;
442 };
443 
AddSerializedFile(PyDescriptorPool * self,PyObject * serialized_pb)444 PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) {
445   char* message_type;
446   Py_ssize_t message_len;
447 
448   if (self->database != NULL) {
449     PyErr_SetString(
450         PyExc_ValueError,
451         "Cannot call Add on a DescriptorPool that uses a DescriptorDatabase. "
452         "Add your file to the underlying database.");
453     return NULL;
454   }
455 
456   if (PyBytes_AsStringAndSize(serialized_pb, &message_type, &message_len) < 0) {
457     return NULL;
458   }
459 
460   FileDescriptorProto file_proto;
461   if (!file_proto.ParseFromArray(message_type, message_len)) {
462     PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!");
463     return NULL;
464   }
465 
466   // If the file was already part of a C++ library, all its descriptors are in
467   // the underlying pool.  No need to do anything else.
468   const FileDescriptor* generated_file = NULL;
469   if (self->underlay) {
470     generated_file = self->underlay->FindFileByName(file_proto.name());
471   }
472   if (generated_file != NULL) {
473     return PyFileDescriptor_FromDescriptorWithSerializedPb(
474         generated_file, serialized_pb);
475   }
476 
477   BuildFileErrorCollector error_collector;
478   const FileDescriptor* descriptor =
479       self->pool->BuildFileCollectingErrors(file_proto,
480                                             &error_collector);
481   if (descriptor == NULL) {
482     PyErr_Format(PyExc_TypeError,
483                  "Couldn't build proto file into descriptor pool!\n%s",
484                  error_collector.error_message.c_str());
485     return NULL;
486   }
487 
488   return PyFileDescriptor_FromDescriptorWithSerializedPb(
489       descriptor, serialized_pb);
490 }
491 
Add(PyDescriptorPool * self,PyObject * file_descriptor_proto)492 PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) {
493   ScopedPyObjectPtr serialized_pb(
494       PyObject_CallMethod(file_descriptor_proto, "SerializeToString", NULL));
495   if (serialized_pb == NULL) {
496     return NULL;
497   }
498   return AddSerializedFile(self, serialized_pb.get());
499 }
500 
501 static PyMethodDef Methods[] = {
502   { "Add", (PyCFunction)Add, METH_O,
503     "Adds the FileDescriptorProto and its types to this pool." },
504   { "AddSerializedFile", (PyCFunction)AddSerializedFile, METH_O,
505     "Adds a serialized FileDescriptorProto to this pool." },
506 
507   // TODO(amauryfa): Understand why the Python implementation differs from
508   // this one, ask users to use another API and deprecate these functions.
509   { "AddFileDescriptor", (PyCFunction)AddFileDescriptor, METH_O,
510     "No-op. Add() must have been called before." },
511   { "AddDescriptor", (PyCFunction)AddDescriptor, METH_O,
512     "No-op. Add() must have been called before." },
513   { "AddEnumDescriptor", (PyCFunction)AddEnumDescriptor, METH_O,
514     "No-op. Add() must have been called before." },
515 
516   { "FindFileByName", (PyCFunction)FindFileByName, METH_O,
517     "Searches for a file descriptor by its .proto name." },
518   { "FindMessageTypeByName", (PyCFunction)FindMessageByName, METH_O,
519     "Searches for a message descriptor by full name." },
520   { "FindFieldByName", (PyCFunction)FindFieldByName, METH_O,
521     "Searches for a field descriptor by full name." },
522   { "FindExtensionByName", (PyCFunction)FindExtensionByName, METH_O,
523     "Searches for extension descriptor by full name." },
524   { "FindEnumTypeByName", (PyCFunction)FindEnumTypeByName, METH_O,
525     "Searches for enum type descriptor by full name." },
526   { "FindOneofByName", (PyCFunction)FindOneofByName, METH_O,
527     "Searches for oneof descriptor by full name." },
528   { "FindServiceByName", (PyCFunction)FindServiceByName, METH_O,
529     "Searches for service descriptor by full name." },
530   { "FindMethodByName", (PyCFunction)FindMethodByName, METH_O,
531     "Searches for method descriptor by full name." },
532 
533   { "FindFileContainingSymbol", (PyCFunction)FindFileContainingSymbol, METH_O,
534     "Gets the FileDescriptor containing the specified symbol." },
535   {NULL}
536 };
537 
538 }  // namespace cdescriptor_pool
539 
540 PyTypeObject PyDescriptorPool_Type = {
541   PyVarObject_HEAD_INIT(&PyType_Type, 0)
542   FULL_MODULE_NAME ".DescriptorPool",  // tp_name
543   sizeof(PyDescriptorPool),            // tp_basicsize
544   0,                                   // tp_itemsize
545   (destructor)cdescriptor_pool::Dealloc,  // tp_dealloc
546   0,                                   // tp_print
547   0,                                   // tp_getattr
548   0,                                   // tp_setattr
549   0,                                   // tp_compare
550   0,                                   // tp_repr
551   0,                                   // tp_as_number
552   0,                                   // tp_as_sequence
553   0,                                   // tp_as_mapping
554   0,                                   // tp_hash
555   0,                                   // tp_call
556   0,                                   // tp_str
557   0,                                   // tp_getattro
558   0,                                   // tp_setattro
559   0,                                   // tp_as_buffer
560   Py_TPFLAGS_DEFAULT,                  // tp_flags
561   "A Descriptor Pool",                 // tp_doc
562   0,                                   // tp_traverse
563   0,                                   // tp_clear
564   0,                                   // tp_richcompare
565   0,                                   // tp_weaklistoffset
566   0,                                   // tp_iter
567   0,                                   // tp_iternext
568   cdescriptor_pool::Methods,           // tp_methods
569   0,                                   // tp_members
570   0,                                   // tp_getset
571   0,                                   // tp_base
572   0,                                   // tp_dict
573   0,                                   // tp_descr_get
574   0,                                   // tp_descr_set
575   0,                                   // tp_dictoffset
576   0,                                   // tp_init
577   0,                                   // tp_alloc
578   cdescriptor_pool::New,               // tp_new
579   PyObject_Del,                        // tp_free
580 };
581 
582 // This is the DescriptorPool which contains all the definitions from the
583 // generated _pb2.py modules.
584 static PyDescriptorPool* python_generated_pool = NULL;
585 
InitDescriptorPool()586 bool InitDescriptorPool() {
587   if (PyType_Ready(&PyDescriptorPool_Type) < 0)
588     return false;
589 
590   // The Pool of messages declared in Python libraries.
591   // generated_pool() contains all messages already linked in C++ libraries, and
592   // is used as underlay.
593   python_generated_pool = cdescriptor_pool::PyDescriptorPool_NewWithUnderlay(
594       DescriptorPool::generated_pool());
595   if (python_generated_pool == NULL) {
596     return false;
597   }
598   // Register this pool to be found for C++-generated descriptors.
599   descriptor_pool_map.insert(
600       std::make_pair(DescriptorPool::generated_pool(),
601                      python_generated_pool));
602 
603   return true;
604 }
605 
606 // The default DescriptorPool used everywhere in this module.
607 // Today it's the python_generated_pool.
608 // TODO(amauryfa): Remove all usages of this function: the pool should be
609 // derived from the context.
GetDefaultDescriptorPool()610 PyDescriptorPool* GetDefaultDescriptorPool() {
611   return python_generated_pool;
612 }
613 
GetDescriptorPool_FromPool(const DescriptorPool * pool)614 PyDescriptorPool* GetDescriptorPool_FromPool(const DescriptorPool* pool) {
615   // Fast path for standard descriptors.
616   if (pool == python_generated_pool->pool ||
617       pool == DescriptorPool::generated_pool()) {
618     return python_generated_pool;
619   }
620   hash_map<const DescriptorPool*, PyDescriptorPool*>::iterator it =
621       descriptor_pool_map.find(pool);
622   if (it == descriptor_pool_map.end()) {
623     PyErr_SetString(PyExc_KeyError, "Unknown descriptor pool");
624     return NULL;
625   }
626   return it->second;
627 }
628 
629 }  // namespace python
630 }  // namespace protobuf
631 }  // namespace google
632