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