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