• 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 // Author: petar@google.com (Petar Petrov)
32 
33 #include <google/protobuf/pyext/descriptor.h>
34 
35 #define PY_SSIZE_T_CLEAN
36 #include <Python.h>
37 #include <frameobject.h>
38 
39 #include <cstdint>
40 #include <string>
41 #include <unordered_map>
42 
43 #include <google/protobuf/io/coded_stream.h>
44 #include <google/protobuf/descriptor.pb.h>
45 #include <google/protobuf/dynamic_message.h>
46 #include <google/protobuf/pyext/descriptor_containers.h>
47 #include <google/protobuf/pyext/descriptor_pool.h>
48 #include <google/protobuf/pyext/message.h>
49 #include <google/protobuf/pyext/message_factory.h>
50 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
51 #include <google/protobuf/stubs/hash.h>
52 
53 #define PyString_AsStringAndSize(ob, charpp, sizep)              \
54   (PyUnicode_Check(ob)                                           \
55        ? ((*(charpp) = const_cast<char*>(                        \
56                PyUnicode_AsUTF8AndSize(ob, (sizep)))) == nullptr \
57               ? -1                                               \
58               : 0)                                               \
59        : PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
60 
61 namespace google {
62 namespace protobuf {
63 namespace python {
64 
65 // Store interned descriptors, so that the same C++ descriptor yields the same
66 // Python object. Objects are not immortal: this map does not own the
67 // references, and items are deleted when the last reference to the object is
68 // released.
69 // This is enough to support the "is" operator on live objects.
70 // All descriptors are stored here.
71 std::unordered_map<const void*, PyObject*>* interned_descriptors;
72 
PyString_FromCppString(const std::string & str)73 PyObject* PyString_FromCppString(const std::string& str) {
74   return PyUnicode_FromStringAndSize(str.c_str(), str.size());
75 }
76 
77 // Check that the calling Python code is the global scope of a _pb2.py module.
78 // This function is used to support the current code generated by the proto
79 // compiler, which creates descriptors, then update some properties.
80 // For example:
81 //   message_descriptor = Descriptor(
82 //       name='Message',
83 //       fields = [FieldDescriptor(name='field')]
84 //   message_descriptor.fields[0].containing_type = message_descriptor
85 //
86 // This code is still executed, but the descriptors now have no other storage
87 // than the (const) C++ pointer, and are immutable.
88 // So we let this code pass, by simply ignoring the new value.
89 //
90 // From user code, descriptors still look immutable.
91 //
92 // TODO(amauryfa): Change the proto2 compiler to remove the assignments, and
93 // remove this hack.
_CalledFromGeneratedFile(int stacklevel)94 bool _CalledFromGeneratedFile(int stacklevel) {
95 #ifndef PYPY_VERSION
96   // This check is not critical and is somewhat difficult to implement correctly
97   // in PyPy.
98   PyFrameObject* frame = PyEval_GetFrame();
99   if (frame == nullptr) {
100     return false;
101   }
102   while (stacklevel-- > 0) {
103     frame = frame->f_back;
104     if (frame == nullptr) {
105       return false;
106     }
107   }
108 
109   if (frame->f_code->co_filename == nullptr) {
110     return false;
111   }
112   char* filename;
113   Py_ssize_t filename_size;
114   if (PyString_AsStringAndSize(frame->f_code->co_filename,
115                                &filename, &filename_size) < 0) {
116     // filename is not a string.
117     PyErr_Clear();
118     return false;
119   }
120   if ((filename_size < 3) ||
121       (strcmp(&filename[filename_size - 3], ".py") != 0)) {
122     // Cython's stack does not have .py file name and is not at global module
123     // scope.
124     return true;
125   }
126   if (filename_size < 7) {
127     // filename is too short.
128     return false;
129   }
130   if (strcmp(&filename[filename_size - 7], "_pb2.py") != 0) {
131     // Filename is not ending with _pb2.
132     return false;
133   }
134 
135   if (frame->f_globals != frame->f_locals) {
136     // Not at global module scope
137     return false;
138   }
139 #endif
140   return true;
141 }
142 
143 // If the calling code is not a _pb2.py file, raise AttributeError.
144 // To be used in attribute setters.
CheckCalledFromGeneratedFile(const char * attr_name)145 static int CheckCalledFromGeneratedFile(const char* attr_name) {
146   if (_CalledFromGeneratedFile(0)) {
147     return 0;
148   }
149   PyErr_Format(PyExc_AttributeError,
150                "attribute is not writable: %s", attr_name);
151   return -1;
152 }
153 
154 
155 #ifndef PyVarObject_HEAD_INIT
156 #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
157 #endif
158 #ifndef Py_TYPE
159 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
160 #endif
161 
162 
163 // Helper functions for descriptor objects.
164 
165 // A set of templates to retrieve the C++ FileDescriptor of any descriptor.
166 template<class DescriptorClass>
GetFileDescriptor(const DescriptorClass * descriptor)167 const FileDescriptor* GetFileDescriptor(const DescriptorClass* descriptor) {
168   return descriptor->file();
169 }
170 template<>
GetFileDescriptor(const FileDescriptor * descriptor)171 const FileDescriptor* GetFileDescriptor(const FileDescriptor* descriptor) {
172   return descriptor;
173 }
174 template<>
GetFileDescriptor(const EnumValueDescriptor * descriptor)175 const FileDescriptor* GetFileDescriptor(const EnumValueDescriptor* descriptor) {
176   return descriptor->type()->file();
177 }
178 template<>
GetFileDescriptor(const OneofDescriptor * descriptor)179 const FileDescriptor* GetFileDescriptor(const OneofDescriptor* descriptor) {
180   return descriptor->containing_type()->file();
181 }
182 template<>
GetFileDescriptor(const MethodDescriptor * descriptor)183 const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) {
184   return descriptor->service()->file();
185 }
186 
Reparse(PyMessageFactory * message_factory,const Message & from,Message * to)187 bool Reparse(
188     PyMessageFactory* message_factory, const Message& from, Message* to) {
189   // Reparse message.
190   std::string serialized;
191   from.SerializeToString(&serialized);
192   io::CodedInputStream input(
193       reinterpret_cast<const uint8_t*>(serialized.c_str()), serialized.size());
194   input.SetExtensionRegistry(message_factory->pool->pool,
195                              message_factory->message_factory);
196   bool success = to->ParseFromCodedStream(&input);
197   if (!success) {
198     return false;
199   }
200   return true;
201 }
202 // Converts options into a Python protobuf, and cache the result.
203 //
204 // This is a bit tricky because options can contain extension fields defined in
205 // the same proto file. In this case the options parsed from the serialized_pb
206 // have unknown fields, and we need to parse them again.
207 //
208 // Always returns a new reference.
209 template<class DescriptorClass>
GetOrBuildOptions(const DescriptorClass * descriptor)210 static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
211   // Options are cached in the pool that owns the descriptor.
212   // First search in the cache.
213   PyDescriptorPool* caching_pool = GetDescriptorPool_FromPool(
214       GetFileDescriptor(descriptor)->pool());
215   std::unordered_map<const void*, PyObject*>* descriptor_options =
216       caching_pool->descriptor_options;
217   if (descriptor_options->find(descriptor) != descriptor_options->end()) {
218     PyObject *value = (*descriptor_options)[descriptor];
219     Py_INCREF(value);
220     return value;
221   }
222 
223   // Similar to the C++ implementation, we return an Options object from the
224   // default (generated) factory, so that client code know that they can use
225   // extensions from generated files:
226   //    d.GetOptions().Extensions[some_pb2.extension]
227   //
228   // The consequence is that extensions not defined in the default pool won't
229   // be available.  If needed, we could add an optional 'message_factory'
230   // parameter to the GetOptions() function.
231   PyMessageFactory* message_factory =
232       GetDefaultDescriptorPool()->py_message_factory;
233 
234   // Build the Options object: get its Python class, and make a copy of the C++
235   // read-only instance.
236   const Message& options(descriptor->options());
237   const Descriptor *message_type = options.GetDescriptor();
238   CMessageClass* message_class = message_factory::GetOrCreateMessageClass(
239       message_factory, message_type);
240   if (message_class == nullptr) {
241     PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s",
242                  message_type->full_name().c_str());
243     return nullptr;
244   }
245   ScopedPyObjectPtr args(PyTuple_New(0));
246   ScopedPyObjectPtr value(
247       PyObject_Call(message_class->AsPyObject(), args.get(), nullptr));
248   Py_DECREF(message_class);
249   if (value == nullptr) {
250     return nullptr;
251   }
252   if (!PyObject_TypeCheck(value.get(), CMessage_Type)) {
253       PyErr_Format(PyExc_TypeError, "Invalid class for %s: %s",
254                    message_type->full_name().c_str(),
255                    Py_TYPE(value.get())->tp_name);
256       return nullptr;
257   }
258   CMessage* cmsg = reinterpret_cast<CMessage*>(value.get());
259 
260   const Reflection* reflection = options.GetReflection();
261   const UnknownFieldSet& unknown_fields(reflection->GetUnknownFields(options));
262   if (unknown_fields.empty()) {
263     cmsg->message->CopyFrom(options);
264   } else {
265     // Reparse options string!  XXX call cmessage::MergeFromString
266     if (!Reparse(message_factory, options, cmsg->message)) {
267       PyErr_Format(PyExc_ValueError, "Error reparsing Options message");
268       return nullptr;
269     }
270   }
271 
272   // Cache the result.
273   Py_INCREF(value.get());
274   (*descriptor_options)[descriptor] = value.get();
275 
276   return value.release();
277 }
278 
279 // Copy the C++ descriptor to a Python message.
280 // The Python message is an instance of descriptor_pb2.DescriptorProto
281 // or similar.
282 template<class DescriptorProtoClass, class DescriptorClass>
CopyToPythonProto(const DescriptorClass * descriptor,PyObject * target)283 static PyObject* CopyToPythonProto(const DescriptorClass *descriptor,
284                                    PyObject *target) {
285   const Descriptor* self_descriptor =
286       DescriptorProtoClass::default_instance().GetDescriptor();
287   CMessage* message = reinterpret_cast<CMessage*>(target);
288   if (!PyObject_TypeCheck(target, CMessage_Type) ||
289       message->message->GetDescriptor() != self_descriptor) {
290     PyErr_Format(PyExc_TypeError, "Not a %s message",
291                  self_descriptor->full_name().c_str());
292     return nullptr;
293   }
294   cmessage::AssureWritable(message);
295   DescriptorProtoClass* descriptor_message =
296       static_cast<DescriptorProtoClass*>(message->message);
297   descriptor->CopyTo(descriptor_message);
298   // Custom options might in unknown extensions. Reparse
299   // the descriptor_message. Can't skip reparse when options unknown
300   // fields is empty, because they might in sub descriptors' options.
301   PyMessageFactory* message_factory =
302       GetDefaultDescriptorPool()->py_message_factory;
303   if (!Reparse(message_factory, *descriptor_message, descriptor_message)) {
304     PyErr_Format(PyExc_ValueError, "Error reparsing descriptor message");
305     return nullptr;
306   }
307 
308   Py_RETURN_NONE;
309 }
310 
311 // All Descriptors classes share the same memory layout.
312 typedef struct PyBaseDescriptor {
313   PyObject_HEAD
314 
315   // Pointer to the C++ proto2 descriptor.
316   // Like all descriptors, it is owned by the global DescriptorPool.
317   const void* descriptor;
318 
319   // Owned reference to the DescriptorPool, to ensure it is kept alive.
320   PyDescriptorPool* pool;
321 } PyBaseDescriptor;
322 
323 
324 // FileDescriptor structure "inherits" from the base descriptor.
325 typedef struct PyFileDescriptor {
326   PyBaseDescriptor base;
327 
328   // The cached version of serialized pb. Either null, or a Bytes string.
329   // We own the reference.
330   PyObject *serialized_pb;
331 } PyFileDescriptor;
332 
333 
334 namespace descriptor {
335 
336 // Creates or retrieve a Python descriptor of the specified type.
337 // Objects are interned: the same descriptor will return the same object if it
338 // was kept alive.
339 // 'was_created' is an optional pointer to a bool, and is set to true if a new
340 // object was allocated.
341 // Always return a new reference.
342 template<class DescriptorClass>
NewInternedDescriptor(PyTypeObject * type,const DescriptorClass * descriptor,bool * was_created)343 PyObject* NewInternedDescriptor(PyTypeObject* type,
344                                 const DescriptorClass* descriptor,
345                                 bool* was_created) {
346   if (was_created) {
347     *was_created = false;
348   }
349   if (descriptor == nullptr) {
350     PyErr_BadInternalCall();
351     return nullptr;
352   }
353 
354   // See if the object is in the map of interned descriptors
355   std::unordered_map<const void*, PyObject*>::iterator it =
356       interned_descriptors->find(descriptor);
357   if (it != interned_descriptors->end()) {
358     GOOGLE_DCHECK(Py_TYPE(it->second) == type);
359     Py_INCREF(it->second);
360     return it->second;
361   }
362   // Create a new descriptor object
363   PyBaseDescriptor* py_descriptor = PyObject_GC_New(
364       PyBaseDescriptor, type);
365   if (py_descriptor == nullptr) {
366     return nullptr;
367   }
368   py_descriptor->descriptor = descriptor;
369 
370   // and cache it.
371   interned_descriptors->insert(
372       std::make_pair(descriptor, reinterpret_cast<PyObject*>(py_descriptor)));
373 
374   // Ensures that the DescriptorPool stays alive.
375   PyDescriptorPool* pool = GetDescriptorPool_FromPool(
376       GetFileDescriptor(descriptor)->pool());
377   if (pool == nullptr) {
378     // Don't DECREF, the object is not fully initialized.
379     PyObject_Del(py_descriptor);
380     return nullptr;
381   }
382   Py_INCREF(pool);
383   py_descriptor->pool = pool;
384 
385   PyObject_GC_Track(py_descriptor);
386 
387   if (was_created) {
388     *was_created = true;
389   }
390   return reinterpret_cast<PyObject*>(py_descriptor);
391 }
392 
Dealloc(PyObject * pself)393 static void Dealloc(PyObject* pself) {
394   PyBaseDescriptor* self = reinterpret_cast<PyBaseDescriptor*>(pself);
395   // Remove from interned dictionary
396   interned_descriptors->erase(self->descriptor);
397   Py_CLEAR(self->pool);
398   Py_TYPE(self)->tp_free(pself);
399 }
400 
GcTraverse(PyObject * pself,visitproc visit,void * arg)401 static int GcTraverse(PyObject* pself, visitproc visit, void* arg) {
402   PyBaseDescriptor* self = reinterpret_cast<PyBaseDescriptor*>(pself);
403   Py_VISIT(self->pool);
404   return 0;
405 }
406 
GcClear(PyObject * pself)407 static int GcClear(PyObject* pself) {
408   PyBaseDescriptor* self = reinterpret_cast<PyBaseDescriptor*>(pself);
409   Py_CLEAR(self->pool);
410   return 0;
411 }
412 
413 static PyGetSetDef Getters[] = {
414     {nullptr},
415 };
416 
417 PyTypeObject PyBaseDescriptor_Type = {
418     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
419     ".DescriptorBase",         // tp_name
420     sizeof(PyBaseDescriptor),  // tp_basicsize
421     0,                         // tp_itemsize
422     (destructor)Dealloc,       // tp_dealloc
423 #if PY_VERSION_HEX < 0x03080000
424     nullptr,  // tp_print
425 #else
426     0,  // tp_vectorcall_offset
427 #endif
428     nullptr,                                  // tp_getattr
429     nullptr,                                  // tp_setattr
430     nullptr,                                  // tp_compare
431     nullptr,                                  // tp_repr
432     nullptr,                                  // tp_as_number
433     nullptr,                                  // tp_as_sequence
434     nullptr,                                  // tp_as_mapping
435     nullptr,                                  // tp_hash
436     nullptr,                                  // tp_call
437     nullptr,                                  // tp_str
438     nullptr,                                  // tp_getattro
439     nullptr,                                  // tp_setattro
440     nullptr,                                  // tp_as_buffer
441     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,  // tp_flags
442     "Descriptors base class",                 // tp_doc
443     GcTraverse,                               // tp_traverse
444     GcClear,                                  // tp_clear
445     nullptr,                                  // tp_richcompare
446     0,                                        // tp_weaklistoffset
447     nullptr,                                  // tp_iter
448     nullptr,                                  // tp_iternext
449     nullptr,                                  // tp_methods
450     nullptr,                                  // tp_members
451     Getters,                                  // tp_getset
452 };
453 
454 }  // namespace descriptor
455 
PyDescriptor_AsVoidPtr(PyObject * obj)456 const void* PyDescriptor_AsVoidPtr(PyObject* obj) {
457   if (!PyObject_TypeCheck(obj, &descriptor::PyBaseDescriptor_Type)) {
458     PyErr_SetString(PyExc_TypeError, "Not a BaseDescriptor");
459     return nullptr;
460   }
461   return reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor;
462 }
463 
464 namespace message_descriptor {
465 
466 // Unchecked accessor to the C++ pointer.
_GetDescriptor(PyBaseDescriptor * self)467 static const Descriptor* _GetDescriptor(PyBaseDescriptor* self) {
468   return reinterpret_cast<const Descriptor*>(self->descriptor);
469 }
470 
GetName(PyBaseDescriptor * self,void * closure)471 static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
472   return PyString_FromCppString(_GetDescriptor(self)->name());
473 }
474 
GetFullName(PyBaseDescriptor * self,void * closure)475 static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
476   return PyString_FromCppString(_GetDescriptor(self)->full_name());
477 }
478 
GetFile(PyBaseDescriptor * self,void * closure)479 static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
480   return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
481 }
482 
GetConcreteClass(PyBaseDescriptor * self,void * closure)483 static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
484   // Returns the canonical class for the given descriptor.
485   // This is the class that was registered with the primary descriptor pool
486   // which contains this descriptor.
487   // This might not be the one you expect! For example the returned object does
488   // not know about extensions defined in a custom pool.
489   CMessageClass* concrete_class(message_factory::GetMessageClass(
490       GetDescriptorPool_FromPool(
491           _GetDescriptor(self)->file()->pool())->py_message_factory,
492       _GetDescriptor(self)));
493   Py_XINCREF(concrete_class);
494   return concrete_class->AsPyObject();
495 }
496 
GetFieldsByName(PyBaseDescriptor * self,void * closure)497 static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) {
498   return NewMessageFieldsByName(_GetDescriptor(self));
499 }
500 
GetFieldsByCamelcaseName(PyBaseDescriptor * self,void * closure)501 static PyObject* GetFieldsByCamelcaseName(PyBaseDescriptor* self,
502                                           void *closure) {
503   return NewMessageFieldsByCamelcaseName(_GetDescriptor(self));
504 }
505 
GetFieldsByNumber(PyBaseDescriptor * self,void * closure)506 static PyObject* GetFieldsByNumber(PyBaseDescriptor* self, void *closure) {
507   return NewMessageFieldsByNumber(_GetDescriptor(self));
508 }
509 
GetFieldsSeq(PyBaseDescriptor * self,void * closure)510 static PyObject* GetFieldsSeq(PyBaseDescriptor* self, void *closure) {
511   return NewMessageFieldsSeq(_GetDescriptor(self));
512 }
513 
GetNestedTypesByName(PyBaseDescriptor * self,void * closure)514 static PyObject* GetNestedTypesByName(PyBaseDescriptor* self, void *closure) {
515   return NewMessageNestedTypesByName(_GetDescriptor(self));
516 }
517 
GetNestedTypesSeq(PyBaseDescriptor * self,void * closure)518 static PyObject* GetNestedTypesSeq(PyBaseDescriptor* self, void *closure) {
519   return NewMessageNestedTypesSeq(_GetDescriptor(self));
520 }
521 
GetExtensionsByName(PyBaseDescriptor * self,void * closure)522 static PyObject* GetExtensionsByName(PyBaseDescriptor* self, void *closure) {
523   return NewMessageExtensionsByName(_GetDescriptor(self));
524 }
525 
GetExtensions(PyBaseDescriptor * self,void * closure)526 static PyObject* GetExtensions(PyBaseDescriptor* self, void *closure) {
527   return NewMessageExtensionsSeq(_GetDescriptor(self));
528 }
529 
GetEnumsSeq(PyBaseDescriptor * self,void * closure)530 static PyObject* GetEnumsSeq(PyBaseDescriptor* self, void *closure) {
531   return NewMessageEnumsSeq(_GetDescriptor(self));
532 }
533 
GetEnumTypesByName(PyBaseDescriptor * self,void * closure)534 static PyObject* GetEnumTypesByName(PyBaseDescriptor* self, void *closure) {
535   return NewMessageEnumsByName(_GetDescriptor(self));
536 }
537 
GetEnumValuesByName(PyBaseDescriptor * self,void * closure)538 static PyObject* GetEnumValuesByName(PyBaseDescriptor* self, void *closure) {
539   return NewMessageEnumValuesByName(_GetDescriptor(self));
540 }
541 
GetOneofsByName(PyBaseDescriptor * self,void * closure)542 static PyObject* GetOneofsByName(PyBaseDescriptor* self, void *closure) {
543   return NewMessageOneofsByName(_GetDescriptor(self));
544 }
545 
GetOneofsSeq(PyBaseDescriptor * self,void * closure)546 static PyObject* GetOneofsSeq(PyBaseDescriptor* self, void *closure) {
547   return NewMessageOneofsSeq(_GetDescriptor(self));
548 }
549 
IsExtendable(PyBaseDescriptor * self,void * closure)550 static PyObject* IsExtendable(PyBaseDescriptor *self, void *closure) {
551   if (_GetDescriptor(self)->extension_range_count() > 0) {
552     Py_RETURN_TRUE;
553   } else {
554     Py_RETURN_FALSE;
555   }
556 }
557 
GetExtensionRanges(PyBaseDescriptor * self,void * closure)558 static PyObject* GetExtensionRanges(PyBaseDescriptor *self, void *closure) {
559   const Descriptor* descriptor = _GetDescriptor(self);
560   PyObject* range_list = PyList_New(descriptor->extension_range_count());
561 
562   for (int i = 0; i < descriptor->extension_range_count(); i++) {
563     const Descriptor::ExtensionRange* range = descriptor->extension_range(i);
564     PyObject* start = PyLong_FromLong(range->start);
565     PyObject* end = PyLong_FromLong(range->end);
566     PyList_SetItem(range_list, i, PyTuple_Pack(2, start, end));
567   }
568 
569   return range_list;
570 }
571 
GetContainingType(PyBaseDescriptor * self,void * closure)572 static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
573   const Descriptor* containing_type =
574       _GetDescriptor(self)->containing_type();
575   if (containing_type) {
576     return PyMessageDescriptor_FromDescriptor(containing_type);
577   } else {
578     Py_RETURN_NONE;
579   }
580 }
581 
SetContainingType(PyBaseDescriptor * self,PyObject * value,void * closure)582 static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
583                              void *closure) {
584   return CheckCalledFromGeneratedFile("containing_type");
585 }
586 
GetHasOptions(PyBaseDescriptor * self,void * closure)587 static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
588   const MessageOptions& options(_GetDescriptor(self)->options());
589   if (&options != &MessageOptions::default_instance()) {
590     Py_RETURN_TRUE;
591   } else {
592     Py_RETURN_FALSE;
593   }
594 }
SetHasOptions(PyBaseDescriptor * self,PyObject * value,void * closure)595 static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
596                              void *closure) {
597   return CheckCalledFromGeneratedFile("has_options");
598 }
599 
GetOptions(PyBaseDescriptor * self)600 static PyObject* GetOptions(PyBaseDescriptor *self) {
601   return GetOrBuildOptions(_GetDescriptor(self));
602 }
603 
SetOptions(PyBaseDescriptor * self,PyObject * value,void * closure)604 static int SetOptions(PyBaseDescriptor *self, PyObject *value,
605                       void *closure) {
606   return CheckCalledFromGeneratedFile("_options");
607 }
608 
SetSerializedOptions(PyBaseDescriptor * self,PyObject * value,void * closure)609 static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
610                                 void *closure) {
611   return CheckCalledFromGeneratedFile("_serialized_options");
612 }
613 
CopyToProto(PyBaseDescriptor * self,PyObject * target)614 static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
615   return CopyToPythonProto<DescriptorProto>(_GetDescriptor(self), target);
616 }
617 
EnumValueName(PyBaseDescriptor * self,PyObject * args)618 static PyObject* EnumValueName(PyBaseDescriptor *self, PyObject *args) {
619   const char *enum_name;
620   int number;
621   if (!PyArg_ParseTuple(args, "si", &enum_name, &number)) return nullptr;
622   const EnumDescriptor *enum_type =
623       _GetDescriptor(self)->FindEnumTypeByName(enum_name);
624   if (enum_type == nullptr) {
625     PyErr_SetString(PyExc_KeyError, enum_name);
626     return nullptr;
627   }
628   const EnumValueDescriptor *enum_value =
629       enum_type->FindValueByNumber(number);
630   if (enum_value == nullptr) {
631     PyErr_Format(PyExc_KeyError, "%d", number);
632     return nullptr;
633   }
634   return PyString_FromCppString(enum_value->name());
635 }
636 
GetSyntax(PyBaseDescriptor * self,void * closure)637 static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) {
638   return PyUnicode_InternFromString(
639       FileDescriptor::SyntaxName(_GetDescriptor(self)->file()->syntax()));
640 }
641 
642 static PyGetSetDef Getters[] = {
643     {"name", (getter)GetName, nullptr, "Last name"},
644     {"full_name", (getter)GetFullName, nullptr, "Full name"},
645     {"_concrete_class", (getter)GetConcreteClass, nullptr, "concrete class"},
646     {"file", (getter)GetFile, nullptr, "File descriptor"},
647 
648     {"fields", (getter)GetFieldsSeq, nullptr, "Fields sequence"},
649     {"fields_by_name", (getter)GetFieldsByName, nullptr, "Fields by name"},
650     {"fields_by_camelcase_name", (getter)GetFieldsByCamelcaseName, nullptr,
651      "Fields by camelCase name"},
652     {"fields_by_number", (getter)GetFieldsByNumber, nullptr,
653      "Fields by number"},
654     {"nested_types", (getter)GetNestedTypesSeq, nullptr,
655      "Nested types sequence"},
656     {"nested_types_by_name", (getter)GetNestedTypesByName, nullptr,
657      "Nested types by name"},
658     {"extensions", (getter)GetExtensions, nullptr, "Extensions Sequence"},
659     {"extensions_by_name", (getter)GetExtensionsByName, nullptr,
660      "Extensions by name"},
661     {"extension_ranges", (getter)GetExtensionRanges, nullptr,
662      "Extension ranges"},
663     {"enum_types", (getter)GetEnumsSeq, nullptr, "Enum sequence"},
664     {"enum_types_by_name", (getter)GetEnumTypesByName, nullptr,
665      "Enum types by name"},
666     {"enum_values_by_name", (getter)GetEnumValuesByName, nullptr,
667      "Enum values by name"},
668     {"oneofs_by_name", (getter)GetOneofsByName, nullptr, "Oneofs by name"},
669     {"oneofs", (getter)GetOneofsSeq, nullptr, "Oneofs by name"},
670     {"containing_type", (getter)GetContainingType, (setter)SetContainingType,
671      "Containing type"},
672     {"is_extendable", (getter)IsExtendable, (setter) nullptr},
673     {"has_options", (getter)GetHasOptions, (setter)SetHasOptions,
674      "Has Options"},
675     {"_options", (getter) nullptr, (setter)SetOptions, "Options"},
676     {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions,
677      "Serialized Options"},
678     {"syntax", (getter)GetSyntax, (setter) nullptr, "Syntax"},
679     {nullptr},
680 };
681 
682 static PyMethodDef Methods[] = {
683     {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS},
684     {"CopyToProto", (PyCFunction)CopyToProto, METH_O},
685     {"EnumValueName", (PyCFunction)EnumValueName, METH_VARARGS},
686     {nullptr},
687 };
688 
689 }  // namespace message_descriptor
690 
691 PyTypeObject PyMessageDescriptor_Type = {
692     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
693     ".MessageDescriptor",      // tp_name
694     sizeof(PyBaseDescriptor),  // tp_basicsize
695     0,                         // tp_itemsize
696     nullptr,                   // tp_dealloc
697 #if PY_VERSION_HEX < 0x03080000
698     nullptr,  // tp_print
699 #else
700     0,  // tp_vectorcall_offset
701 #endif
702     nullptr,                             // tp_getattr
703     nullptr,                             // tp_setattr
704     nullptr,                             // tp_compare
705     nullptr,                             // tp_repr
706     nullptr,                             // tp_as_number
707     nullptr,                             // tp_as_sequence
708     nullptr,                             // tp_as_mapping
709     nullptr,                             // tp_hash
710     nullptr,                             // tp_call
711     nullptr,                             // tp_str
712     nullptr,                             // tp_getattro
713     nullptr,                             // tp_setattro
714     nullptr,                             // tp_as_buffer
715     Py_TPFLAGS_DEFAULT,                  // tp_flags
716     "A Message Descriptor",              // tp_doc
717     nullptr,                             // tp_traverse
718     nullptr,                             // tp_clear
719     nullptr,                             // tp_richcompare
720     0,                                   // tp_weaklistoffset
721     nullptr,                             // tp_iter
722     nullptr,                             // tp_iternext
723     message_descriptor::Methods,         // tp_methods
724     nullptr,                             // tp_members
725     message_descriptor::Getters,         // tp_getset
726     &descriptor::PyBaseDescriptor_Type,  // tp_base
727 };
728 
PyMessageDescriptor_FromDescriptor(const Descriptor * message_descriptor)729 PyObject* PyMessageDescriptor_FromDescriptor(
730     const Descriptor* message_descriptor) {
731   return descriptor::NewInternedDescriptor(&PyMessageDescriptor_Type,
732                                            message_descriptor, nullptr);
733 }
734 
PyMessageDescriptor_AsDescriptor(PyObject * obj)735 const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj) {
736   if (!PyObject_TypeCheck(obj, &PyMessageDescriptor_Type)) {
737     PyErr_SetString(PyExc_TypeError, "Not a MessageDescriptor");
738     return nullptr;
739   }
740   return reinterpret_cast<const Descriptor*>(
741       reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
742 }
743 
744 namespace field_descriptor {
745 
746 // Unchecked accessor to the C++ pointer.
_GetDescriptor(PyBaseDescriptor * self)747 static const FieldDescriptor* _GetDescriptor(
748     PyBaseDescriptor *self) {
749   return reinterpret_cast<const FieldDescriptor*>(self->descriptor);
750 }
751 
GetFullName(PyBaseDescriptor * self,void * closure)752 static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
753   return PyString_FromCppString(_GetDescriptor(self)->full_name());
754 }
755 
GetName(PyBaseDescriptor * self,void * closure)756 static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
757   return PyString_FromCppString(_GetDescriptor(self)->name());
758 }
759 
GetCamelcaseName(PyBaseDescriptor * self,void * closure)760 static PyObject* GetCamelcaseName(PyBaseDescriptor* self, void *closure) {
761   return PyString_FromCppString(_GetDescriptor(self)->camelcase_name());
762 }
763 
GetJsonName(PyBaseDescriptor * self,void * closure)764 static PyObject* GetJsonName(PyBaseDescriptor* self, void *closure) {
765   return PyString_FromCppString(_GetDescriptor(self)->json_name());
766 }
767 
GetFile(PyBaseDescriptor * self,void * closure)768 static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
769   return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
770 }
771 
GetType(PyBaseDescriptor * self,void * closure)772 static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
773   return PyLong_FromLong(_GetDescriptor(self)->type());
774 }
775 
GetCppType(PyBaseDescriptor * self,void * closure)776 static PyObject* GetCppType(PyBaseDescriptor *self, void *closure) {
777   return PyLong_FromLong(_GetDescriptor(self)->cpp_type());
778 }
779 
GetLabel(PyBaseDescriptor * self,void * closure)780 static PyObject* GetLabel(PyBaseDescriptor *self, void *closure) {
781   return PyLong_FromLong(_GetDescriptor(self)->label());
782 }
783 
GetNumber(PyBaseDescriptor * self,void * closure)784 static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
785   return PyLong_FromLong(_GetDescriptor(self)->number());
786 }
787 
GetIndex(PyBaseDescriptor * self,void * closure)788 static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
789   return PyLong_FromLong(_GetDescriptor(self)->index());
790 }
791 
GetID(PyBaseDescriptor * self,void * closure)792 static PyObject* GetID(PyBaseDescriptor *self, void *closure) {
793   return PyLong_FromVoidPtr(self);
794 }
795 
IsExtension(PyBaseDescriptor * self,void * closure)796 static PyObject* IsExtension(PyBaseDescriptor *self, void *closure) {
797   return PyBool_FromLong(_GetDescriptor(self)->is_extension());
798 }
799 
HasDefaultValue(PyBaseDescriptor * self,void * closure)800 static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) {
801   return PyBool_FromLong(_GetDescriptor(self)->has_default_value());
802 }
803 
GetDefaultValue(PyBaseDescriptor * self,void * closure)804 static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
805   PyObject *result;
806 
807   if (_GetDescriptor(self)->is_repeated()) {
808     return PyList_New(0);
809   }
810 
811 
812   switch (_GetDescriptor(self)->cpp_type()) {
813     case FieldDescriptor::CPPTYPE_INT32: {
814       int32_t value = _GetDescriptor(self)->default_value_int32();
815       result = PyLong_FromLong(value);
816       break;
817     }
818     case FieldDescriptor::CPPTYPE_INT64: {
819       int64_t value = _GetDescriptor(self)->default_value_int64();
820       result = PyLong_FromLongLong(value);
821       break;
822     }
823     case FieldDescriptor::CPPTYPE_UINT32: {
824       uint32_t value = _GetDescriptor(self)->default_value_uint32();
825       result = PyLong_FromSsize_t(value);
826       break;
827     }
828     case FieldDescriptor::CPPTYPE_UINT64: {
829       uint64_t value = _GetDescriptor(self)->default_value_uint64();
830       result = PyLong_FromUnsignedLongLong(value);
831       break;
832     }
833     case FieldDescriptor::CPPTYPE_FLOAT: {
834       float value = _GetDescriptor(self)->default_value_float();
835       result = PyFloat_FromDouble(value);
836       break;
837     }
838     case FieldDescriptor::CPPTYPE_DOUBLE: {
839       double value = _GetDescriptor(self)->default_value_double();
840       result = PyFloat_FromDouble(value);
841       break;
842     }
843     case FieldDescriptor::CPPTYPE_BOOL: {
844       bool value = _GetDescriptor(self)->default_value_bool();
845       result = PyBool_FromLong(value);
846       break;
847     }
848     case FieldDescriptor::CPPTYPE_STRING: {
849       const std::string& value = _GetDescriptor(self)->default_value_string();
850       result = ToStringObject(_GetDescriptor(self), value);
851       break;
852     }
853     case FieldDescriptor::CPPTYPE_ENUM: {
854       const EnumValueDescriptor* value =
855           _GetDescriptor(self)->default_value_enum();
856       result = PyLong_FromLong(value->number());
857       break;
858     }
859     case FieldDescriptor::CPPTYPE_MESSAGE: {
860       Py_RETURN_NONE;
861       break;
862     }
863     default:
864       PyErr_Format(PyExc_NotImplementedError, "default value for %s",
865                    _GetDescriptor(self)->full_name().c_str());
866       return nullptr;
867   }
868   return result;
869 }
870 
GetCDescriptor(PyObject * self,void * closure)871 static PyObject* GetCDescriptor(PyObject *self, void *closure) {
872   Py_INCREF(self);
873   return self;
874 }
875 
GetEnumType(PyBaseDescriptor * self,void * closure)876 static PyObject *GetEnumType(PyBaseDescriptor *self, void *closure) {
877   const EnumDescriptor* enum_type = _GetDescriptor(self)->enum_type();
878   if (enum_type) {
879     return PyEnumDescriptor_FromDescriptor(enum_type);
880   } else {
881     Py_RETURN_NONE;
882   }
883 }
884 
SetEnumType(PyBaseDescriptor * self,PyObject * value,void * closure)885 static int SetEnumType(PyBaseDescriptor *self, PyObject *value, void *closure) {
886   return CheckCalledFromGeneratedFile("enum_type");
887 }
888 
GetMessageType(PyBaseDescriptor * self,void * closure)889 static PyObject *GetMessageType(PyBaseDescriptor *self, void *closure) {
890   const Descriptor* message_type = _GetDescriptor(self)->message_type();
891   if (message_type) {
892     return PyMessageDescriptor_FromDescriptor(message_type);
893   } else {
894     Py_RETURN_NONE;
895   }
896 }
897 
SetMessageType(PyBaseDescriptor * self,PyObject * value,void * closure)898 static int SetMessageType(PyBaseDescriptor *self, PyObject *value,
899                           void *closure) {
900   return CheckCalledFromGeneratedFile("message_type");
901 }
902 
GetContainingType(PyBaseDescriptor * self,void * closure)903 static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
904   const Descriptor* containing_type =
905       _GetDescriptor(self)->containing_type();
906   if (containing_type) {
907     return PyMessageDescriptor_FromDescriptor(containing_type);
908   } else {
909     Py_RETURN_NONE;
910   }
911 }
912 
SetContainingType(PyBaseDescriptor * self,PyObject * value,void * closure)913 static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
914                              void *closure) {
915   return CheckCalledFromGeneratedFile("containing_type");
916 }
917 
GetExtensionScope(PyBaseDescriptor * self,void * closure)918 static PyObject* GetExtensionScope(PyBaseDescriptor *self, void *closure) {
919   const auto* desc = _GetDescriptor(self);
920   const Descriptor* extension_scope =
921       desc->is_extension() ? desc->extension_scope() : nullptr;
922   if (extension_scope) {
923     return PyMessageDescriptor_FromDescriptor(extension_scope);
924   } else {
925     Py_RETURN_NONE;
926   }
927 }
928 
GetContainingOneof(PyBaseDescriptor * self,void * closure)929 static PyObject* GetContainingOneof(PyBaseDescriptor *self, void *closure) {
930   const OneofDescriptor* containing_oneof =
931       _GetDescriptor(self)->containing_oneof();
932   if (containing_oneof) {
933     return PyOneofDescriptor_FromDescriptor(containing_oneof);
934   } else {
935     Py_RETURN_NONE;
936   }
937 }
938 
SetContainingOneof(PyBaseDescriptor * self,PyObject * value,void * closure)939 static int SetContainingOneof(PyBaseDescriptor *self, PyObject *value,
940                               void *closure) {
941   return CheckCalledFromGeneratedFile("containing_oneof");
942 }
943 
GetHasOptions(PyBaseDescriptor * self,void * closure)944 static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
945   const FieldOptions& options(_GetDescriptor(self)->options());
946   if (&options != &FieldOptions::default_instance()) {
947     Py_RETURN_TRUE;
948   } else {
949     Py_RETURN_FALSE;
950   }
951 }
SetHasOptions(PyBaseDescriptor * self,PyObject * value,void * closure)952 static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
953                          void *closure) {
954   return CheckCalledFromGeneratedFile("has_options");
955 }
956 
GetHasPresence(PyBaseDescriptor * self,void * closure)957 static PyObject* GetHasPresence(PyBaseDescriptor* self, void* closure) {
958   if (_GetDescriptor(self)->has_presence()) {
959     Py_RETURN_TRUE;
960   } else {
961     Py_RETURN_FALSE;
962   }
963 }
964 
GetOptions(PyBaseDescriptor * self)965 static PyObject* GetOptions(PyBaseDescriptor *self) {
966   return GetOrBuildOptions(_GetDescriptor(self));
967 }
968 
SetOptions(PyBaseDescriptor * self,PyObject * value,void * closure)969 static int SetOptions(PyBaseDescriptor *self, PyObject *value,
970                       void *closure) {
971   return CheckCalledFromGeneratedFile("_options");
972 }
973 
SetSerializedOptions(PyBaseDescriptor * self,PyObject * value,void * closure)974 static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
975                                 void *closure) {
976   return CheckCalledFromGeneratedFile("_serialized_options");
977 }
978 
979 static PyGetSetDef Getters[] = {
980     {"full_name", (getter)GetFullName, nullptr, "Full name"},
981     {"name", (getter)GetName, nullptr, "Unqualified name"},
982     {"camelcase_name", (getter)GetCamelcaseName, nullptr, "Camelcase name"},
983     {"json_name", (getter)GetJsonName, nullptr, "Json name"},
984     {"file", (getter)GetFile, nullptr, "File Descriptor"},
985     {"type", (getter)GetType, nullptr, "C++ Type"},
986     {"cpp_type", (getter)GetCppType, nullptr, "C++ Type"},
987     {"label", (getter)GetLabel, nullptr, "Label"},
988     {"number", (getter)GetNumber, nullptr, "Number"},
989     {"index", (getter)GetIndex, nullptr, "Index"},
990     {"default_value", (getter)GetDefaultValue, nullptr, "Default Value"},
991     {"has_default_value", (getter)HasDefaultValue},
992     {"is_extension", (getter)IsExtension, nullptr, "ID"},
993     {"id", (getter)GetID, nullptr, "ID"},
994     {"_cdescriptor", (getter)GetCDescriptor, nullptr, "HAACK REMOVE ME"},
995 
996     {"message_type", (getter)GetMessageType, (setter)SetMessageType,
997      "Message type"},
998     {"enum_type", (getter)GetEnumType, (setter)SetEnumType, "Enum type"},
999     {"containing_type", (getter)GetContainingType, (setter)SetContainingType,
1000      "Containing type"},
1001     {"extension_scope", (getter)GetExtensionScope, (setter) nullptr,
1002      "Extension scope"},
1003     {"containing_oneof", (getter)GetContainingOneof, (setter)SetContainingOneof,
1004      "Containing oneof"},
1005     {"has_options", (getter)GetHasOptions, (setter)SetHasOptions,
1006      "Has Options"},
1007     {"has_presence", (getter)GetHasPresence, (setter) nullptr, "Has Presence"},
1008     {"_options", (getter) nullptr, (setter)SetOptions, "Options"},
1009     {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions,
1010      "Serialized Options"},
1011     {nullptr},
1012 };
1013 
1014 static PyMethodDef Methods[] = {
1015     {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS},
1016     {nullptr},
1017 };
1018 
1019 }  // namespace field_descriptor
1020 
1021 PyTypeObject PyFieldDescriptor_Type = {
1022     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
1023     ".FieldDescriptor",        // tp_name
1024     sizeof(PyBaseDescriptor),  // tp_basicsize
1025     0,                         // tp_itemsize
1026     nullptr,                   // tp_dealloc
1027 #if PY_VERSION_HEX < 0x03080000
1028     nullptr,  // tp_print
1029 #else
1030     0,  // tp_vectorcall_offset
1031 #endif
1032     nullptr,                             // tp_getattr
1033     nullptr,                             // tp_setattr
1034     nullptr,                             // tp_compare
1035     nullptr,                             // tp_repr
1036     nullptr,                             // tp_as_number
1037     nullptr,                             // tp_as_sequence
1038     nullptr,                             // tp_as_mapping
1039     nullptr,                             // tp_hash
1040     nullptr,                             // tp_call
1041     nullptr,                             // tp_str
1042     nullptr,                             // tp_getattro
1043     nullptr,                             // tp_setattro
1044     nullptr,                             // tp_as_buffer
1045     Py_TPFLAGS_DEFAULT,                  // tp_flags
1046     "A Field Descriptor",                // tp_doc
1047     nullptr,                             // tp_traverse
1048     nullptr,                             // tp_clear
1049     nullptr,                             // tp_richcompare
1050     0,                                   // tp_weaklistoffset
1051     nullptr,                             // tp_iter
1052     nullptr,                             // tp_iternext
1053     field_descriptor::Methods,           // tp_methods
1054     nullptr,                             // tp_members
1055     field_descriptor::Getters,           // tp_getset
1056     &descriptor::PyBaseDescriptor_Type,  // tp_base
1057 };
1058 
PyFieldDescriptor_FromDescriptor(const FieldDescriptor * field_descriptor)1059 PyObject* PyFieldDescriptor_FromDescriptor(
1060     const FieldDescriptor* field_descriptor) {
1061   return descriptor::NewInternedDescriptor(&PyFieldDescriptor_Type,
1062                                            field_descriptor, nullptr);
1063 }
1064 
PyFieldDescriptor_AsDescriptor(PyObject * obj)1065 const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj) {
1066   if (!PyObject_TypeCheck(obj, &PyFieldDescriptor_Type)) {
1067     PyErr_SetString(PyExc_TypeError, "Not a FieldDescriptor");
1068     return nullptr;
1069   }
1070   return reinterpret_cast<const FieldDescriptor*>(
1071       reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
1072 }
1073 
1074 namespace enum_descriptor {
1075 
1076 // Unchecked accessor to the C++ pointer.
_GetDescriptor(PyBaseDescriptor * self)1077 static const EnumDescriptor* _GetDescriptor(
1078     PyBaseDescriptor *self) {
1079   return reinterpret_cast<const EnumDescriptor*>(self->descriptor);
1080 }
1081 
GetFullName(PyBaseDescriptor * self,void * closure)1082 static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
1083   return PyString_FromCppString(_GetDescriptor(self)->full_name());
1084 }
1085 
GetName(PyBaseDescriptor * self,void * closure)1086 static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
1087   return PyString_FromCppString(_GetDescriptor(self)->name());
1088 }
1089 
GetFile(PyBaseDescriptor * self,void * closure)1090 static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
1091   return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
1092 }
1093 
GetEnumvaluesByName(PyBaseDescriptor * self,void * closure)1094 static PyObject* GetEnumvaluesByName(PyBaseDescriptor* self, void *closure) {
1095   return NewEnumValuesByName(_GetDescriptor(self));
1096 }
1097 
GetEnumvaluesByNumber(PyBaseDescriptor * self,void * closure)1098 static PyObject* GetEnumvaluesByNumber(PyBaseDescriptor* self, void *closure) {
1099   return NewEnumValuesByNumber(_GetDescriptor(self));
1100 }
1101 
GetEnumvaluesSeq(PyBaseDescriptor * self,void * closure)1102 static PyObject* GetEnumvaluesSeq(PyBaseDescriptor* self, void *closure) {
1103   return NewEnumValuesSeq(_GetDescriptor(self));
1104 }
1105 
GetContainingType(PyBaseDescriptor * self,void * closure)1106 static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
1107   const Descriptor* containing_type =
1108       _GetDescriptor(self)->containing_type();
1109   if (containing_type) {
1110     return PyMessageDescriptor_FromDescriptor(containing_type);
1111   } else {
1112     Py_RETURN_NONE;
1113   }
1114 }
1115 
SetContainingType(PyBaseDescriptor * self,PyObject * value,void * closure)1116 static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
1117                              void *closure) {
1118   return CheckCalledFromGeneratedFile("containing_type");
1119 }
1120 
1121 
GetHasOptions(PyBaseDescriptor * self,void * closure)1122 static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
1123   const EnumOptions& options(_GetDescriptor(self)->options());
1124   if (&options != &EnumOptions::default_instance()) {
1125     Py_RETURN_TRUE;
1126   } else {
1127     Py_RETURN_FALSE;
1128   }
1129 }
SetHasOptions(PyBaseDescriptor * self,PyObject * value,void * closure)1130 static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
1131                          void *closure) {
1132   return CheckCalledFromGeneratedFile("has_options");
1133 }
1134 
GetOptions(PyBaseDescriptor * self)1135 static PyObject* GetOptions(PyBaseDescriptor *self) {
1136   return GetOrBuildOptions(_GetDescriptor(self));
1137 }
1138 
SetOptions(PyBaseDescriptor * self,PyObject * value,void * closure)1139 static int SetOptions(PyBaseDescriptor *self, PyObject *value,
1140                       void *closure) {
1141   return CheckCalledFromGeneratedFile("_options");
1142 }
1143 
SetSerializedOptions(PyBaseDescriptor * self,PyObject * value,void * closure)1144 static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
1145                                 void *closure) {
1146   return CheckCalledFromGeneratedFile("_serialized_options");
1147 }
1148 
CopyToProto(PyBaseDescriptor * self,PyObject * target)1149 static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
1150   return CopyToPythonProto<EnumDescriptorProto>(_GetDescriptor(self), target);
1151 }
1152 
1153 static PyMethodDef Methods[] = {
1154     {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS},
1155     {"CopyToProto", (PyCFunction)CopyToProto, METH_O},
1156     {nullptr},
1157 };
1158 
1159 static PyGetSetDef Getters[] = {
1160     {"full_name", (getter)GetFullName, nullptr, "Full name"},
1161     {"name", (getter)GetName, nullptr, "last name"},
1162     {"file", (getter)GetFile, nullptr, "File descriptor"},
1163     {"values", (getter)GetEnumvaluesSeq, nullptr, "values"},
1164     {"values_by_name", (getter)GetEnumvaluesByName, nullptr,
1165      "Enum values by name"},
1166     {"values_by_number", (getter)GetEnumvaluesByNumber, nullptr,
1167      "Enum values by number"},
1168 
1169     {"containing_type", (getter)GetContainingType, (setter)SetContainingType,
1170      "Containing type"},
1171     {"has_options", (getter)GetHasOptions, (setter)SetHasOptions,
1172      "Has Options"},
1173     {"_options", (getter) nullptr, (setter)SetOptions, "Options"},
1174     {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions,
1175      "Serialized Options"},
1176     {nullptr},
1177 };
1178 
1179 }  // namespace enum_descriptor
1180 
1181 PyTypeObject PyEnumDescriptor_Type = {
1182     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
1183     ".EnumDescriptor",         // tp_name
1184     sizeof(PyBaseDescriptor),  // tp_basicsize
1185     0,                         // tp_itemsize
1186     nullptr,                   // tp_dealloc
1187 #if PY_VERSION_HEX < 0x03080000
1188     nullptr,  // tp_print
1189 #else
1190     0,  // tp_vectorcall_offset
1191 #endif
1192     nullptr,                             // tp_getattr
1193     nullptr,                             // tp_setattr
1194     nullptr,                             // tp_compare
1195     nullptr,                             // tp_repr
1196     nullptr,                             // tp_as_number
1197     nullptr,                             // tp_as_sequence
1198     nullptr,                             // tp_as_mapping
1199     nullptr,                             // tp_hash
1200     nullptr,                             // tp_call
1201     nullptr,                             // tp_str
1202     nullptr,                             // tp_getattro
1203     nullptr,                             // tp_setattro
1204     nullptr,                             // tp_as_buffer
1205     Py_TPFLAGS_DEFAULT,                  // tp_flags
1206     "A Enum Descriptor",                 // tp_doc
1207     nullptr,                             // tp_traverse
1208     nullptr,                             // tp_clear
1209     nullptr,                             // tp_richcompare
1210     0,                                   // tp_weaklistoffset
1211     nullptr,                             // tp_iter
1212     nullptr,                             // tp_iternext
1213     enum_descriptor::Methods,            // tp_methods
1214     nullptr,                             // tp_members
1215     enum_descriptor::Getters,            // tp_getset
1216     &descriptor::PyBaseDescriptor_Type,  // tp_base
1217 };
1218 
PyEnumDescriptor_FromDescriptor(const EnumDescriptor * enum_descriptor)1219 PyObject* PyEnumDescriptor_FromDescriptor(
1220     const EnumDescriptor* enum_descriptor) {
1221   return descriptor::NewInternedDescriptor(&PyEnumDescriptor_Type,
1222                                            enum_descriptor, nullptr);
1223 }
1224 
PyEnumDescriptor_AsDescriptor(PyObject * obj)1225 const EnumDescriptor* PyEnumDescriptor_AsDescriptor(PyObject* obj) {
1226   if (!PyObject_TypeCheck(obj, &PyEnumDescriptor_Type)) {
1227     PyErr_SetString(PyExc_TypeError, "Not an EnumDescriptor");
1228     return nullptr;
1229   }
1230   return reinterpret_cast<const EnumDescriptor*>(
1231       reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
1232 }
1233 
1234 namespace enumvalue_descriptor {
1235 
1236 // Unchecked accessor to the C++ pointer.
_GetDescriptor(PyBaseDescriptor * self)1237 static const EnumValueDescriptor* _GetDescriptor(
1238     PyBaseDescriptor *self) {
1239   return reinterpret_cast<const EnumValueDescriptor*>(self->descriptor);
1240 }
1241 
GetName(PyBaseDescriptor * self,void * closure)1242 static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
1243   return PyString_FromCppString(_GetDescriptor(self)->name());
1244 }
1245 
GetNumber(PyBaseDescriptor * self,void * closure)1246 static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
1247   return PyLong_FromLong(_GetDescriptor(self)->number());
1248 }
1249 
GetIndex(PyBaseDescriptor * self,void * closure)1250 static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
1251   return PyLong_FromLong(_GetDescriptor(self)->index());
1252 }
1253 
GetType(PyBaseDescriptor * self,void * closure)1254 static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
1255   return PyEnumDescriptor_FromDescriptor(_GetDescriptor(self)->type());
1256 }
1257 
GetHasOptions(PyBaseDescriptor * self,void * closure)1258 static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
1259   const EnumValueOptions& options(_GetDescriptor(self)->options());
1260   if (&options != &EnumValueOptions::default_instance()) {
1261     Py_RETURN_TRUE;
1262   } else {
1263     Py_RETURN_FALSE;
1264   }
1265 }
SetHasOptions(PyBaseDescriptor * self,PyObject * value,void * closure)1266 static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
1267                          void *closure) {
1268   return CheckCalledFromGeneratedFile("has_options");
1269 }
1270 
GetOptions(PyBaseDescriptor * self)1271 static PyObject* GetOptions(PyBaseDescriptor *self) {
1272   return GetOrBuildOptions(_GetDescriptor(self));
1273 }
1274 
SetOptions(PyBaseDescriptor * self,PyObject * value,void * closure)1275 static int SetOptions(PyBaseDescriptor *self, PyObject *value,
1276                       void *closure) {
1277   return CheckCalledFromGeneratedFile("_options");
1278 }
1279 
SetSerializedOptions(PyBaseDescriptor * self,PyObject * value,void * closure)1280 static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
1281                                 void *closure) {
1282   return CheckCalledFromGeneratedFile("_serialized_options");
1283 }
1284 
1285 static PyGetSetDef Getters[] = {
1286     {"name", (getter)GetName, nullptr, "name"},
1287     {"number", (getter)GetNumber, nullptr, "number"},
1288     {"index", (getter)GetIndex, nullptr, "index"},
1289     {"type", (getter)GetType, nullptr, "index"},
1290 
1291     {"has_options", (getter)GetHasOptions, (setter)SetHasOptions,
1292      "Has Options"},
1293     {"_options", (getter) nullptr, (setter)SetOptions, "Options"},
1294     {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions,
1295      "Serialized Options"},
1296     {nullptr},
1297 };
1298 
1299 static PyMethodDef Methods[] = {
1300     {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS},
1301     {nullptr},
1302 };
1303 
1304 }  // namespace enumvalue_descriptor
1305 
1306 PyTypeObject PyEnumValueDescriptor_Type = {
1307     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
1308     ".EnumValueDescriptor",    // tp_name
1309     sizeof(PyBaseDescriptor),  // tp_basicsize
1310     0,                         // tp_itemsize
1311     nullptr,                   // tp_dealloc
1312 #if PY_VERSION_HEX < 0x03080000
1313     nullptr,  // tp_print
1314 #else
1315     0,  // tp_vectorcall_offset
1316 #endif
1317     nullptr,                             // tp_getattr
1318     nullptr,                             // tp_setattr
1319     nullptr,                             // tp_compare
1320     nullptr,                             // tp_repr
1321     nullptr,                             // tp_as_number
1322     nullptr,                             // tp_as_sequence
1323     nullptr,                             // tp_as_mapping
1324     nullptr,                             // tp_hash
1325     nullptr,                             // tp_call
1326     nullptr,                             // tp_str
1327     nullptr,                             // tp_getattro
1328     nullptr,                             // tp_setattro
1329     nullptr,                             // tp_as_buffer
1330     Py_TPFLAGS_DEFAULT,                  // tp_flags
1331     "A EnumValue Descriptor",            // tp_doc
1332     nullptr,                             // tp_traverse
1333     nullptr,                             // tp_clear
1334     nullptr,                             // tp_richcompare
1335     0,                                   // tp_weaklistoffset
1336     nullptr,                             // tp_iter
1337     nullptr,                             // tp_iternext
1338     enumvalue_descriptor::Methods,       // tp_methods
1339     nullptr,                             // tp_members
1340     enumvalue_descriptor::Getters,       // tp_getset
1341     &descriptor::PyBaseDescriptor_Type,  // tp_base
1342 };
1343 
PyEnumValueDescriptor_FromDescriptor(const EnumValueDescriptor * enumvalue_descriptor)1344 PyObject* PyEnumValueDescriptor_FromDescriptor(
1345     const EnumValueDescriptor* enumvalue_descriptor) {
1346   return descriptor::NewInternedDescriptor(&PyEnumValueDescriptor_Type,
1347                                            enumvalue_descriptor, nullptr);
1348 }
1349 
1350 namespace file_descriptor {
1351 
1352 // Unchecked accessor to the C++ pointer.
_GetDescriptor(PyFileDescriptor * self)1353 static const FileDescriptor* _GetDescriptor(PyFileDescriptor *self) {
1354   return reinterpret_cast<const FileDescriptor*>(self->base.descriptor);
1355 }
1356 
Dealloc(PyFileDescriptor * self)1357 static void Dealloc(PyFileDescriptor* self) {
1358   Py_XDECREF(self->serialized_pb);
1359   descriptor::Dealloc(reinterpret_cast<PyObject*>(self));
1360 }
1361 
GetPool(PyFileDescriptor * self,void * closure)1362 static PyObject* GetPool(PyFileDescriptor *self, void *closure) {
1363   PyObject* pool = reinterpret_cast<PyObject*>(
1364       GetDescriptorPool_FromPool(_GetDescriptor(self)->pool()));
1365   Py_XINCREF(pool);
1366   return pool;
1367 }
1368 
GetName(PyFileDescriptor * self,void * closure)1369 static PyObject* GetName(PyFileDescriptor *self, void *closure) {
1370   return PyString_FromCppString(_GetDescriptor(self)->name());
1371 }
1372 
GetPackage(PyFileDescriptor * self,void * closure)1373 static PyObject* GetPackage(PyFileDescriptor *self, void *closure) {
1374   return PyString_FromCppString(_GetDescriptor(self)->package());
1375 }
1376 
GetSerializedPb(PyFileDescriptor * self,void * closure)1377 static PyObject* GetSerializedPb(PyFileDescriptor *self, void *closure) {
1378   PyObject *serialized_pb = self->serialized_pb;
1379   if (serialized_pb != nullptr) {
1380     Py_INCREF(serialized_pb);
1381     return serialized_pb;
1382   }
1383   FileDescriptorProto file_proto;
1384   _GetDescriptor(self)->CopyTo(&file_proto);
1385   std::string contents;
1386   file_proto.SerializePartialToString(&contents);
1387   self->serialized_pb = PyBytes_FromStringAndSize(
1388       contents.c_str(), contents.size());
1389   if (self->serialized_pb == nullptr) {
1390     return nullptr;
1391   }
1392   Py_INCREF(self->serialized_pb);
1393   return self->serialized_pb;
1394 }
1395 
GetMessageTypesByName(PyFileDescriptor * self,void * closure)1396 static PyObject* GetMessageTypesByName(PyFileDescriptor* self, void *closure) {
1397   return NewFileMessageTypesByName(_GetDescriptor(self));
1398 }
1399 
GetEnumTypesByName(PyFileDescriptor * self,void * closure)1400 static PyObject* GetEnumTypesByName(PyFileDescriptor* self, void *closure) {
1401   return NewFileEnumTypesByName(_GetDescriptor(self));
1402 }
1403 
GetExtensionsByName(PyFileDescriptor * self,void * closure)1404 static PyObject* GetExtensionsByName(PyFileDescriptor* self, void *closure) {
1405   return NewFileExtensionsByName(_GetDescriptor(self));
1406 }
1407 
GetServicesByName(PyFileDescriptor * self,void * closure)1408 static PyObject* GetServicesByName(PyFileDescriptor* self, void *closure) {
1409   return NewFileServicesByName(_GetDescriptor(self));
1410 }
1411 
GetDependencies(PyFileDescriptor * self,void * closure)1412 static PyObject* GetDependencies(PyFileDescriptor* self, void *closure) {
1413   return NewFileDependencies(_GetDescriptor(self));
1414 }
1415 
GetPublicDependencies(PyFileDescriptor * self,void * closure)1416 static PyObject* GetPublicDependencies(PyFileDescriptor* self, void *closure) {
1417   return NewFilePublicDependencies(_GetDescriptor(self));
1418 }
1419 
GetHasOptions(PyFileDescriptor * self,void * closure)1420 static PyObject* GetHasOptions(PyFileDescriptor *self, void *closure) {
1421   const FileOptions& options(_GetDescriptor(self)->options());
1422   if (&options != &FileOptions::default_instance()) {
1423     Py_RETURN_TRUE;
1424   } else {
1425     Py_RETURN_FALSE;
1426   }
1427 }
SetHasOptions(PyFileDescriptor * self,PyObject * value,void * closure)1428 static int SetHasOptions(PyFileDescriptor *self, PyObject *value,
1429                          void *closure) {
1430   return CheckCalledFromGeneratedFile("has_options");
1431 }
1432 
GetDebugString(PyFileDescriptor * self)1433 static PyObject* GetDebugString(PyFileDescriptor* self) {
1434   return PyString_FromCppString(_GetDescriptor(self)->DebugString());
1435 }
1436 
GetOptions(PyFileDescriptor * self)1437 static PyObject* GetOptions(PyFileDescriptor *self) {
1438   return GetOrBuildOptions(_GetDescriptor(self));
1439 }
1440 
SetOptions(PyFileDescriptor * self,PyObject * value,void * closure)1441 static int SetOptions(PyFileDescriptor *self, PyObject *value,
1442                       void *closure) {
1443   return CheckCalledFromGeneratedFile("_options");
1444 }
1445 
SetSerializedOptions(PyFileDescriptor * self,PyObject * value,void * closure)1446 static int SetSerializedOptions(PyFileDescriptor *self, PyObject *value,
1447                                 void *closure) {
1448   return CheckCalledFromGeneratedFile("_serialized_options");
1449 }
1450 
GetSyntax(PyFileDescriptor * self,void * closure)1451 static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) {
1452   return PyUnicode_InternFromString(
1453       FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax()));
1454 }
1455 
CopyToProto(PyFileDescriptor * self,PyObject * target)1456 static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) {
1457   return CopyToPythonProto<FileDescriptorProto>(_GetDescriptor(self), target);
1458 }
1459 
1460 static PyGetSetDef Getters[] = {
1461     {"pool", (getter)GetPool, nullptr, "pool"},
1462     {"name", (getter)GetName, nullptr, "name"},
1463     {"package", (getter)GetPackage, nullptr, "package"},
1464     {"serialized_pb", (getter)GetSerializedPb},
1465     {"message_types_by_name", (getter)GetMessageTypesByName, nullptr,
1466      "Messages by name"},
1467     {"enum_types_by_name", (getter)GetEnumTypesByName, nullptr,
1468      "Enums by name"},
1469     {"extensions_by_name", (getter)GetExtensionsByName, nullptr,
1470      "Extensions by name"},
1471     {"services_by_name", (getter)GetServicesByName, nullptr,
1472      "Services by name"},
1473     {"dependencies", (getter)GetDependencies, nullptr, "Dependencies"},
1474     {"public_dependencies", (getter)GetPublicDependencies, nullptr,
1475      "Dependencies"},
1476 
1477     {"has_options", (getter)GetHasOptions, (setter)SetHasOptions,
1478      "Has Options"},
1479     {"_options", (getter) nullptr, (setter)SetOptions, "Options"},
1480     {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions,
1481      "Serialized Options"},
1482     {"syntax", (getter)GetSyntax, (setter) nullptr, "Syntax"},
1483     {nullptr},
1484 };
1485 
1486 static PyMethodDef Methods[] = {
1487     {"GetDebugString", (PyCFunction)GetDebugString, METH_NOARGS},
1488     {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS},
1489     {"CopyToProto", (PyCFunction)CopyToProto, METH_O},
1490     {nullptr},
1491 };
1492 
1493 }  // namespace file_descriptor
1494 
1495 PyTypeObject PyFileDescriptor_Type = {
1496     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
1497     ".FileDescriptor",                     // tp_name
1498     sizeof(PyFileDescriptor),              // tp_basicsize
1499     0,                                     // tp_itemsize
1500     (destructor)file_descriptor::Dealloc,  // tp_dealloc
1501 #if PY_VERSION_HEX < 0x03080000
1502     nullptr,  // tp_print
1503 #else
1504     0,  // tp_vectorcall_offset
1505 #endif
1506     nullptr,                             // tp_getattr
1507     nullptr,                             // tp_setattr
1508     nullptr,                             // tp_compare
1509     nullptr,                             // tp_repr
1510     nullptr,                             // tp_as_number
1511     nullptr,                             // tp_as_sequence
1512     nullptr,                             // tp_as_mapping
1513     nullptr,                             // tp_hash
1514     nullptr,                             // tp_call
1515     nullptr,                             // tp_str
1516     nullptr,                             // tp_getattro
1517     nullptr,                             // tp_setattro
1518     nullptr,                             // tp_as_buffer
1519     Py_TPFLAGS_DEFAULT,                  // tp_flags
1520     "A File Descriptor",                 // tp_doc
1521     nullptr,                             // tp_traverse
1522     nullptr,                             // tp_clear
1523     nullptr,                             // tp_richcompare
1524     0,                                   // tp_weaklistoffset
1525     nullptr,                             // tp_iter
1526     nullptr,                             // tp_iternext
1527     file_descriptor::Methods,            // tp_methods
1528     nullptr,                             // tp_members
1529     file_descriptor::Getters,            // tp_getset
1530     &descriptor::PyBaseDescriptor_Type,  // tp_base
1531     nullptr,                             // tp_dict
1532     nullptr,                             // tp_descr_get
1533     nullptr,                             // tp_descr_set
1534     0,                                   // tp_dictoffset
1535     nullptr,                             // tp_init
1536     nullptr,                             // tp_alloc
1537     nullptr,                             // tp_new
1538     PyObject_GC_Del,                     // tp_free
1539 };
1540 
PyFileDescriptor_FromDescriptor(const FileDescriptor * file_descriptor)1541 PyObject* PyFileDescriptor_FromDescriptor(
1542     const FileDescriptor* file_descriptor) {
1543   return PyFileDescriptor_FromDescriptorWithSerializedPb(file_descriptor,
1544                                                          nullptr);
1545 }
1546 
PyFileDescriptor_FromDescriptorWithSerializedPb(const FileDescriptor * file_descriptor,PyObject * serialized_pb)1547 PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb(
1548     const FileDescriptor* file_descriptor, PyObject *serialized_pb) {
1549   bool was_created;
1550   PyObject* py_descriptor = descriptor::NewInternedDescriptor(
1551       &PyFileDescriptor_Type, file_descriptor, &was_created);
1552   if (py_descriptor == nullptr) {
1553     return nullptr;
1554   }
1555   if (was_created) {
1556     PyFileDescriptor* cfile_descriptor =
1557         reinterpret_cast<PyFileDescriptor*>(py_descriptor);
1558     Py_XINCREF(serialized_pb);
1559     cfile_descriptor->serialized_pb = serialized_pb;
1560   }
1561   // TODO(amauryfa): In the case of a cached object, check that serialized_pb
1562   // is the same as before.
1563 
1564   return py_descriptor;
1565 }
1566 
PyFileDescriptor_AsDescriptor(PyObject * obj)1567 const FileDescriptor* PyFileDescriptor_AsDescriptor(PyObject* obj) {
1568   if (!PyObject_TypeCheck(obj, &PyFileDescriptor_Type)) {
1569     PyErr_SetString(PyExc_TypeError, "Not a FileDescriptor");
1570     return nullptr;
1571   }
1572   return reinterpret_cast<const FileDescriptor*>(
1573       reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
1574 }
1575 
1576 namespace oneof_descriptor {
1577 
1578 // Unchecked accessor to the C++ pointer.
_GetDescriptor(PyBaseDescriptor * self)1579 static const OneofDescriptor* _GetDescriptor(
1580     PyBaseDescriptor *self) {
1581   return reinterpret_cast<const OneofDescriptor*>(self->descriptor);
1582 }
1583 
GetName(PyBaseDescriptor * self,void * closure)1584 static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
1585   return PyString_FromCppString(_GetDescriptor(self)->name());
1586 }
1587 
GetFullName(PyBaseDescriptor * self,void * closure)1588 static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
1589   return PyString_FromCppString(_GetDescriptor(self)->full_name());
1590 }
1591 
GetIndex(PyBaseDescriptor * self,void * closure)1592 static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
1593   return PyLong_FromLong(_GetDescriptor(self)->index());
1594 }
1595 
GetFields(PyBaseDescriptor * self,void * closure)1596 static PyObject* GetFields(PyBaseDescriptor* self, void *closure) {
1597   return NewOneofFieldsSeq(_GetDescriptor(self));
1598 }
1599 
GetContainingType(PyBaseDescriptor * self,void * closure)1600 static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
1601   const Descriptor* containing_type =
1602       _GetDescriptor(self)->containing_type();
1603   if (containing_type) {
1604     return PyMessageDescriptor_FromDescriptor(containing_type);
1605   } else {
1606     Py_RETURN_NONE;
1607   }
1608 }
1609 
GetHasOptions(PyBaseDescriptor * self,void * closure)1610 static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
1611   const OneofOptions& options(_GetDescriptor(self)->options());
1612   if (&options != &OneofOptions::default_instance()) {
1613     Py_RETURN_TRUE;
1614   } else {
1615     Py_RETURN_FALSE;
1616   }
1617 }
1618 
SetHasOptions(PyBaseDescriptor * self,PyObject * value,void * closure)1619 static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
1620                          void *closure) {
1621   return CheckCalledFromGeneratedFile("has_options");
1622 }
1623 
GetOptions(PyBaseDescriptor * self)1624 static PyObject* GetOptions(PyBaseDescriptor *self) {
1625   return GetOrBuildOptions(_GetDescriptor(self));
1626 }
1627 
SetOptions(PyBaseDescriptor * self,PyObject * value,void * closure)1628 static int SetOptions(PyBaseDescriptor *self, PyObject *value,
1629                       void *closure) {
1630   return CheckCalledFromGeneratedFile("_options");
1631 }
1632 
SetSerializedOptions(PyBaseDescriptor * self,PyObject * value,void * closure)1633 static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value,
1634                                 void *closure) {
1635   return CheckCalledFromGeneratedFile("_serialized_options");
1636 }
1637 
1638 static PyGetSetDef Getters[] = {
1639     {"name", (getter)GetName, nullptr, "Name"},
1640     {"full_name", (getter)GetFullName, nullptr, "Full name"},
1641     {"index", (getter)GetIndex, nullptr, "Index"},
1642 
1643     {"containing_type", (getter)GetContainingType, nullptr, "Containing type"},
1644     {"has_options", (getter)GetHasOptions, (setter)SetHasOptions,
1645      "Has Options"},
1646     {"_options", (getter) nullptr, (setter)SetOptions, "Options"},
1647     {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions,
1648      "Serialized Options"},
1649     {"fields", (getter)GetFields, nullptr, "Fields"},
1650     {nullptr},
1651 };
1652 
1653 static PyMethodDef Methods[] = {
1654     {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS},
1655     {nullptr},
1656 };
1657 
1658 }  // namespace oneof_descriptor
1659 
1660 PyTypeObject PyOneofDescriptor_Type = {
1661     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
1662     ".OneofDescriptor",        // tp_name
1663     sizeof(PyBaseDescriptor),  // tp_basicsize
1664     0,                         // tp_itemsize
1665     nullptr,                   // tp_dealloc
1666 #if PY_VERSION_HEX < 0x03080000
1667     nullptr,  // tp_print
1668 #else
1669     0,  // tp_vectorcall_offset
1670 #endif
1671     nullptr,                             // tp_getattr
1672     nullptr,                             // tp_setattr
1673     nullptr,                             // tp_compare
1674     nullptr,                             // tp_repr
1675     nullptr,                             // tp_as_number
1676     nullptr,                             // tp_as_sequence
1677     nullptr,                             // tp_as_mapping
1678     nullptr,                             // tp_hash
1679     nullptr,                             // tp_call
1680     nullptr,                             // tp_str
1681     nullptr,                             // tp_getattro
1682     nullptr,                             // tp_setattro
1683     nullptr,                             // tp_as_buffer
1684     Py_TPFLAGS_DEFAULT,                  // tp_flags
1685     "A Oneof Descriptor",                // tp_doc
1686     nullptr,                             // tp_traverse
1687     nullptr,                             // tp_clear
1688     nullptr,                             // tp_richcompare
1689     0,                                   // tp_weaklistoffset
1690     nullptr,                             // tp_iter
1691     nullptr,                             // tp_iternext
1692     oneof_descriptor::Methods,           // tp_methods
1693     nullptr,                             // tp_members
1694     oneof_descriptor::Getters,           // tp_getset
1695     &descriptor::PyBaseDescriptor_Type,  // tp_base
1696 };
1697 
PyOneofDescriptor_FromDescriptor(const OneofDescriptor * oneof_descriptor)1698 PyObject* PyOneofDescriptor_FromDescriptor(
1699     const OneofDescriptor* oneof_descriptor) {
1700   return descriptor::NewInternedDescriptor(&PyOneofDescriptor_Type,
1701                                            oneof_descriptor, nullptr);
1702 }
1703 
1704 namespace service_descriptor {
1705 
1706 // Unchecked accessor to the C++ pointer.
_GetDescriptor(PyBaseDescriptor * self)1707 static const ServiceDescriptor* _GetDescriptor(
1708     PyBaseDescriptor *self) {
1709   return reinterpret_cast<const ServiceDescriptor*>(self->descriptor);
1710 }
1711 
GetName(PyBaseDescriptor * self,void * closure)1712 static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
1713   return PyString_FromCppString(_GetDescriptor(self)->name());
1714 }
1715 
GetFullName(PyBaseDescriptor * self,void * closure)1716 static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
1717   return PyString_FromCppString(_GetDescriptor(self)->full_name());
1718 }
1719 
GetFile(PyBaseDescriptor * self,void * closure)1720 static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
1721   return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
1722 }
1723 
GetIndex(PyBaseDescriptor * self,void * closure)1724 static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
1725   return PyLong_FromLong(_GetDescriptor(self)->index());
1726 }
1727 
GetMethods(PyBaseDescriptor * self,void * closure)1728 static PyObject* GetMethods(PyBaseDescriptor* self, void *closure) {
1729   return NewServiceMethodsSeq(_GetDescriptor(self));
1730 }
1731 
GetMethodsByName(PyBaseDescriptor * self,void * closure)1732 static PyObject* GetMethodsByName(PyBaseDescriptor* self, void *closure) {
1733   return NewServiceMethodsByName(_GetDescriptor(self));
1734 }
1735 
FindMethodByName(PyBaseDescriptor * self,PyObject * arg)1736 static PyObject* FindMethodByName(PyBaseDescriptor *self, PyObject* arg) {
1737   Py_ssize_t name_size;
1738   char* name;
1739   if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
1740     return nullptr;
1741   }
1742 
1743   const MethodDescriptor* method_descriptor =
1744       _GetDescriptor(self)->FindMethodByName(StringParam(name, name_size));
1745   if (method_descriptor == nullptr) {
1746     PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name);
1747     return nullptr;
1748   }
1749 
1750   return PyMethodDescriptor_FromDescriptor(method_descriptor);
1751 }
1752 
GetOptions(PyBaseDescriptor * self)1753 static PyObject* GetOptions(PyBaseDescriptor *self) {
1754   return GetOrBuildOptions(_GetDescriptor(self));
1755 }
1756 
CopyToProto(PyBaseDescriptor * self,PyObject * target)1757 static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
1758   return CopyToPythonProto<ServiceDescriptorProto>(_GetDescriptor(self),
1759                                                    target);
1760 }
1761 
1762 static PyGetSetDef Getters[] = {
1763     {"name", (getter)GetName, nullptr, "Name", nullptr},
1764     {"full_name", (getter)GetFullName, nullptr, "Full name", nullptr},
1765     {"file", (getter)GetFile, nullptr, "File descriptor"},
1766     {"index", (getter)GetIndex, nullptr, "Index", nullptr},
1767     {"methods", (getter)GetMethods, nullptr, "Methods", nullptr},
1768     {"methods_by_name", (getter)GetMethodsByName, nullptr, "Methods by name",
1769      nullptr},
1770     {nullptr},
1771 };
1772 
1773 static PyMethodDef Methods[] = {
1774     {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS},
1775     {"CopyToProto", (PyCFunction)CopyToProto, METH_O},
1776     {"FindMethodByName", (PyCFunction)FindMethodByName, METH_O},
1777     {nullptr},
1778 };
1779 
1780 }  // namespace service_descriptor
1781 
1782 PyTypeObject PyServiceDescriptor_Type = {
1783     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
1784     ".ServiceDescriptor",      // tp_name
1785     sizeof(PyBaseDescriptor),  // tp_basicsize
1786     0,                         // tp_itemsize
1787     nullptr,                   // tp_dealloc
1788 #if PY_VERSION_HEX < 0x03080000
1789     nullptr,  // tp_print
1790 #else
1791     0,  // tp_vectorcall_offset
1792 #endif
1793     nullptr,                             // tp_getattr
1794     nullptr,                             // tp_setattr
1795     nullptr,                             // tp_compare
1796     nullptr,                             // tp_repr
1797     nullptr,                             // tp_as_number
1798     nullptr,                             // tp_as_sequence
1799     nullptr,                             // tp_as_mapping
1800     nullptr,                             // tp_hash
1801     nullptr,                             // tp_call
1802     nullptr,                             // tp_str
1803     nullptr,                             // tp_getattro
1804     nullptr,                             // tp_setattro
1805     nullptr,                             // tp_as_buffer
1806     Py_TPFLAGS_DEFAULT,                  // tp_flags
1807     "A Service Descriptor",              // tp_doc
1808     nullptr,                             // tp_traverse
1809     nullptr,                             // tp_clear
1810     nullptr,                             // tp_richcompare
1811     0,                                   // tp_weaklistoffset
1812     nullptr,                             // tp_iter
1813     nullptr,                             // tp_iternext
1814     service_descriptor::Methods,         // tp_methods
1815     nullptr,                             // tp_members
1816     service_descriptor::Getters,         // tp_getset
1817     &descriptor::PyBaseDescriptor_Type,  // tp_base
1818 };
1819 
PyServiceDescriptor_FromDescriptor(const ServiceDescriptor * service_descriptor)1820 PyObject* PyServiceDescriptor_FromDescriptor(
1821     const ServiceDescriptor* service_descriptor) {
1822   return descriptor::NewInternedDescriptor(&PyServiceDescriptor_Type,
1823                                            service_descriptor, nullptr);
1824 }
1825 
PyServiceDescriptor_AsDescriptor(PyObject * obj)1826 const ServiceDescriptor* PyServiceDescriptor_AsDescriptor(PyObject* obj) {
1827   if (!PyObject_TypeCheck(obj, &PyServiceDescriptor_Type)) {
1828     PyErr_SetString(PyExc_TypeError, "Not a ServiceDescriptor");
1829     return nullptr;
1830   }
1831   return reinterpret_cast<const ServiceDescriptor*>(
1832       reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
1833 }
1834 
1835 namespace method_descriptor {
1836 
1837 // Unchecked accessor to the C++ pointer.
_GetDescriptor(PyBaseDescriptor * self)1838 static const MethodDescriptor* _GetDescriptor(
1839     PyBaseDescriptor *self) {
1840   return reinterpret_cast<const MethodDescriptor*>(self->descriptor);
1841 }
1842 
GetName(PyBaseDescriptor * self,void * closure)1843 static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
1844   return PyString_FromCppString(_GetDescriptor(self)->name());
1845 }
1846 
GetFullName(PyBaseDescriptor * self,void * closure)1847 static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
1848   return PyString_FromCppString(_GetDescriptor(self)->full_name());
1849 }
1850 
GetIndex(PyBaseDescriptor * self,void * closure)1851 static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
1852   return PyLong_FromLong(_GetDescriptor(self)->index());
1853 }
1854 
GetContainingService(PyBaseDescriptor * self,void * closure)1855 static PyObject* GetContainingService(PyBaseDescriptor *self, void *closure) {
1856   const ServiceDescriptor* containing_service =
1857       _GetDescriptor(self)->service();
1858   return PyServiceDescriptor_FromDescriptor(containing_service);
1859 }
1860 
GetInputType(PyBaseDescriptor * self,void * closure)1861 static PyObject* GetInputType(PyBaseDescriptor *self, void *closure) {
1862   const Descriptor* input_type = _GetDescriptor(self)->input_type();
1863   return PyMessageDescriptor_FromDescriptor(input_type);
1864 }
1865 
GetOutputType(PyBaseDescriptor * self,void * closure)1866 static PyObject* GetOutputType(PyBaseDescriptor *self, void *closure) {
1867   const Descriptor* output_type = _GetDescriptor(self)->output_type();
1868   return PyMessageDescriptor_FromDescriptor(output_type);
1869 }
1870 
GetClientStreaming(PyBaseDescriptor * self,void * closure)1871 static PyObject* GetClientStreaming(PyBaseDescriptor* self, void* closure) {
1872   return PyBool_FromLong(_GetDescriptor(self)->client_streaming() ? 1 : 0);
1873 }
1874 
GetServerStreaming(PyBaseDescriptor * self,void * closure)1875 static PyObject* GetServerStreaming(PyBaseDescriptor* self, void* closure) {
1876   return PyBool_FromLong(_GetDescriptor(self)->server_streaming() ? 1 : 0);
1877 }
1878 
GetOptions(PyBaseDescriptor * self)1879 static PyObject* GetOptions(PyBaseDescriptor *self) {
1880   return GetOrBuildOptions(_GetDescriptor(self));
1881 }
1882 
CopyToProto(PyBaseDescriptor * self,PyObject * target)1883 static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
1884   return CopyToPythonProto<MethodDescriptorProto>(_GetDescriptor(self), target);
1885 }
1886 
1887 static PyGetSetDef Getters[] = {
1888     {"name", (getter)GetName, nullptr, "Name", nullptr},
1889     {"full_name", (getter)GetFullName, nullptr, "Full name", nullptr},
1890     {"index", (getter)GetIndex, nullptr, "Index", nullptr},
1891     {"containing_service", (getter)GetContainingService, nullptr,
1892      "Containing service", nullptr},
1893     {"input_type", (getter)GetInputType, nullptr, "Input type", nullptr},
1894     {"output_type", (getter)GetOutputType, nullptr, "Output type", nullptr},
1895     {"client_streaming", (getter)GetClientStreaming, nullptr,
1896      "Client streaming", nullptr},
1897     {"server_streaming", (getter)GetServerStreaming, nullptr,
1898      "Server streaming", nullptr},
1899     {nullptr},
1900 };
1901 
1902 static PyMethodDef Methods[] = {
1903     {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS},
1904     {"CopyToProto", (PyCFunction)CopyToProto, METH_O},
1905     {nullptr},
1906 };
1907 
1908 }  // namespace method_descriptor
1909 
1910 PyTypeObject PyMethodDescriptor_Type = {
1911     PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME
1912     ".MethodDescriptor",       // tp_name
1913     sizeof(PyBaseDescriptor),  // tp_basicsize
1914     0,                         // tp_itemsize
1915     nullptr,                   // tp_dealloc
1916 #if PY_VERSION_HEX < 0x03080000
1917     nullptr,  // tp_print
1918 #else
1919     0,  // tp_vectorcall_offset
1920 #endif
1921     nullptr,                             // tp_getattr
1922     nullptr,                             // tp_setattr
1923     nullptr,                             // tp_compare
1924     nullptr,                             // tp_repr
1925     nullptr,                             // tp_as_number
1926     nullptr,                             // tp_as_sequence
1927     nullptr,                             // tp_as_mapping
1928     nullptr,                             // tp_hash
1929     nullptr,                             // tp_call
1930     nullptr,                             // tp_str
1931     nullptr,                             // tp_getattro
1932     nullptr,                             // tp_setattro
1933     nullptr,                             // tp_as_buffer
1934     Py_TPFLAGS_DEFAULT,                  // tp_flags
1935     "A Method Descriptor",               // tp_doc
1936     nullptr,                             // tp_traverse
1937     nullptr,                             // tp_clear
1938     nullptr,                             // tp_richcompare
1939     0,                                   // tp_weaklistoffset
1940     nullptr,                             // tp_iter
1941     nullptr,                             // tp_iternext
1942     method_descriptor::Methods,          // tp_methods
1943     nullptr,                             // tp_members
1944     method_descriptor::Getters,          // tp_getset
1945     &descriptor::PyBaseDescriptor_Type,  // tp_base
1946 };
1947 
PyMethodDescriptor_FromDescriptor(const MethodDescriptor * method_descriptor)1948 PyObject* PyMethodDescriptor_FromDescriptor(
1949     const MethodDescriptor* method_descriptor) {
1950   return descriptor::NewInternedDescriptor(&PyMethodDescriptor_Type,
1951                                            method_descriptor, nullptr);
1952 }
1953 
1954 // Add a enum values to a type dictionary.
AddEnumValues(PyTypeObject * type,const EnumDescriptor * enum_descriptor)1955 static bool AddEnumValues(PyTypeObject *type,
1956                           const EnumDescriptor* enum_descriptor) {
1957   for (int i = 0; i < enum_descriptor->value_count(); ++i) {
1958     const EnumValueDescriptor* value = enum_descriptor->value(i);
1959     ScopedPyObjectPtr obj(PyLong_FromLong(value->number()));
1960     if (obj == nullptr) {
1961       return false;
1962     }
1963     if (PyDict_SetItemString(type->tp_dict, value->name().c_str(), obj.get()) <
1964         0) {
1965       return false;
1966     }
1967   }
1968   return true;
1969 }
1970 
AddIntConstant(PyTypeObject * type,const char * name,int value)1971 static bool AddIntConstant(PyTypeObject *type, const char* name, int value) {
1972   ScopedPyObjectPtr obj(PyLong_FromLong(value));
1973   if (PyDict_SetItemString(type->tp_dict, name, obj.get()) < 0) {
1974     return false;
1975   }
1976   return true;
1977 }
1978 
1979 
InitDescriptor()1980 bool InitDescriptor() {
1981   if (PyType_Ready(&PyMessageDescriptor_Type) < 0)
1982     return false;
1983 
1984   if (PyType_Ready(&PyFieldDescriptor_Type) < 0)
1985     return false;
1986 
1987   if (!AddEnumValues(&PyFieldDescriptor_Type,
1988                      FieldDescriptorProto::Label_descriptor())) {
1989     return false;
1990   }
1991   if (!AddEnumValues(&PyFieldDescriptor_Type,
1992                      FieldDescriptorProto::Type_descriptor())) {
1993     return false;
1994   }
1995 #define ADD_FIELDDESC_CONSTANT(NAME) AddIntConstant( \
1996     &PyFieldDescriptor_Type, #NAME, FieldDescriptor::NAME)
1997   if (!ADD_FIELDDESC_CONSTANT(CPPTYPE_INT32) ||
1998       !ADD_FIELDDESC_CONSTANT(CPPTYPE_INT64) ||
1999       !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT32) ||
2000       !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT64) ||
2001       !ADD_FIELDDESC_CONSTANT(CPPTYPE_DOUBLE) ||
2002       !ADD_FIELDDESC_CONSTANT(CPPTYPE_FLOAT) ||
2003       !ADD_FIELDDESC_CONSTANT(CPPTYPE_BOOL) ||
2004       !ADD_FIELDDESC_CONSTANT(CPPTYPE_ENUM) ||
2005       !ADD_FIELDDESC_CONSTANT(CPPTYPE_STRING) ||
2006       !ADD_FIELDDESC_CONSTANT(CPPTYPE_MESSAGE)) {
2007     return false;
2008   }
2009 #undef ADD_FIELDDESC_CONSTANT
2010 
2011   if (PyType_Ready(&PyEnumDescriptor_Type) < 0)
2012     return false;
2013 
2014   if (PyType_Ready(&PyEnumValueDescriptor_Type) < 0)
2015     return false;
2016 
2017   if (PyType_Ready(&PyFileDescriptor_Type) < 0)
2018     return false;
2019 
2020   if (PyType_Ready(&PyOneofDescriptor_Type) < 0)
2021     return false;
2022 
2023   if (PyType_Ready(&PyServiceDescriptor_Type) < 0)
2024     return false;
2025 
2026   if (PyType_Ready(&PyMethodDescriptor_Type) < 0)
2027     return false;
2028 
2029   if (!InitDescriptorMappingTypes())
2030     return false;
2031 
2032   // Initialize globals defined in this file.
2033   interned_descriptors = new std::unordered_map<const void*, PyObject*>;
2034 
2035   return true;
2036 }
2037 
2038 }  // namespace python
2039 }  // namespace protobuf
2040 }  // namespace google
2041