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