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