blob: a875a7be86c0b1f3cba0b5f07a10670c597216ab [file] [log] [blame]
jieluo@google.combde4a322014-08-12 21:10:30 +00001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
Feng Xiaoe4288622014-10-01 16:26:23 -07003// https://developers.google.com/protocol-buffers/
jieluo@google.combde4a322014-08-12 21:10:30 +00004//
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>
Jisi Liuada65562015-02-25 16:39:11 -080034#include <frameobject.h>
jieluo@google.combde4a322014-08-12 21:10:30 +000035#include <string>
36
Jisi Liuada65562015-02-25 16:39:11 -080037#include <google/protobuf/io/coded_stream.h>
jieluo@google.combde4a322014-08-12 21:10:30 +000038#include <google/protobuf/descriptor.pb.h>
Jisi Liuada65562015-02-25 16:39:11 -080039#include <google/protobuf/dynamic_message.h>
jieluo@google.combde4a322014-08-12 21:10:30 +000040#include <google/protobuf/pyext/descriptor.h>
Jisi Liuada65562015-02-25 16:39:11 -080041#include <google/protobuf/pyext/descriptor_containers.h>
42#include <google/protobuf/pyext/descriptor_pool.h>
Feng Xiao6ef984a2014-11-10 17:34:54 -080043#include <google/protobuf/pyext/message.h>
jieluo@google.combde4a322014-08-12 21:10:30 +000044#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
45
jieluo@google.combde4a322014-08-12 21:10:30 +000046#if PY_MAJOR_VERSION >= 3
47 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
Jisi Liuada65562015-02-25 16:39:11 -080048 #define PyString_Check PyUnicode_Check
49 #define PyString_InternFromString PyUnicode_InternFromString
jieluo@google.combde4a322014-08-12 21:10:30 +000050 #define PyInt_FromLong PyLong_FromLong
Jisi Liuada65562015-02-25 16:39:11 -080051 #define PyInt_FromSize_t PyLong_FromSize_t
jieluo@google.combde4a322014-08-12 21:10:30 +000052 #if PY_VERSION_HEX < 0x03030000
53 #error "Python 3.0 - 3.2 are not supported."
jieluo@google.combde4a322014-08-12 21:10:30 +000054 #endif
Jisi Liuada65562015-02-25 16:39:11 -080055 #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)))
jieluo@google.combde4a322014-08-12 21:10:30 +000059#endif
60
61namespace google {
62namespace protobuf {
63namespace python {
64
Feng Xiaob17ec3c2015-08-23 17:50:38 -070065// 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.
71hash_map<const void*, PyObject*> interned_descriptors;
72
Jisi Liuada65562015-02-25 16:39:11 -080073PyObject* 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.
94bool _CalledFromGeneratedFile(int stacklevel) {
95 PyThreadState *state = PyThreadState_GET();
96 if (state == NULL) {
97 return false;
98 }
99 PyFrameObject* frame = state->frame;
100 if (frame == NULL) {
101 return false;
102 }
103 while (stacklevel-- > 0) {
104 frame = frame->f_back;
105 if (frame == NULL) {
106 return false;
107 }
108 }
109 if (frame->f_globals != frame->f_locals) {
110 // Not at global module scope
111 return false;
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 < 7) {
126 // filename is too short.
127 return false;
128 }
129 if (strcmp(&filename[filename_size - 7], "_pb2.py") != 0) {
130 // Filename is not ending with _pb2.
131 return false;
132 }
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.
138static 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
jieluo@google.combde4a322014-08-12 21:10:30 +0000147
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
Jisi Liuada65562015-02-25 16:39:11 -0800156// Helper functions for descriptor objects.
jieluo@google.combde4a322014-08-12 21:10:30 +0000157
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700158// A set of templates to retrieve the C++ FileDescriptor of any descriptor.
159template<class DescriptorClass>
160const FileDescriptor* GetFileDescriptor(const DescriptorClass* descriptor) {
161 return descriptor->file();
162}
163template<>
164const FileDescriptor* GetFileDescriptor(const FileDescriptor* descriptor) {
165 return descriptor;
166}
167template<>
168const FileDescriptor* GetFileDescriptor(const EnumValueDescriptor* descriptor) {
169 return descriptor->type()->file();
170}
171template<>
172const FileDescriptor* GetFileDescriptor(const OneofDescriptor* descriptor) {
173 return descriptor->containing_type()->file();
174}
175
Jisi Liuada65562015-02-25 16:39:11 -0800176// Converts options into a Python protobuf, and cache the result.
177//
178// This is a bit tricky because options can contain extension fields defined in
179// the same proto file. In this case the options parsed from the serialized_pb
180// have unkown fields, and we need to parse them again.
181//
182// Always returns a new reference.
183template<class DescriptorClass>
184static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700185 // Options (and their extensions) are completely resolved in the proto file
186 // containing the descriptor.
187 PyDescriptorPool* pool = GetDescriptorPool_FromPool(
188 GetFileDescriptor(descriptor)->pool());
189
Jisi Liuada65562015-02-25 16:39:11 -0800190 hash_map<const void*, PyObject*>* descriptor_options =
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700191 pool->descriptor_options;
Jisi Liuada65562015-02-25 16:39:11 -0800192 // First search in the cache.
193 if (descriptor_options->find(descriptor) != descriptor_options->end()) {
194 PyObject *value = (*descriptor_options)[descriptor];
195 Py_INCREF(value);
196 return value;
197 }
Feng Xiao6ef984a2014-11-10 17:34:54 -0800198
Jisi Liuada65562015-02-25 16:39:11 -0800199 // Build the Options object: get its Python class, and make a copy of the C++
200 // read-only instance.
201 const Message& options(descriptor->options());
202 const Descriptor *message_type = options.GetDescriptor();
203 PyObject* message_class(cdescriptor_pool::GetMessageClass(
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700204 pool, message_type));
Jisi Liuada65562015-02-25 16:39:11 -0800205 if (message_class == NULL) {
Feng Xiaoe841bac2015-12-11 17:09:20 -0800206 // The Options message was not found in the current DescriptorPool.
207 // In this case, there cannot be extensions to these options, and we can
208 // try to use the basic pool instead.
209 PyErr_Clear();
210 message_class = cdescriptor_pool::GetMessageClass(
211 GetDefaultDescriptorPool(), message_type);
212 }
213 if (message_class == NULL) {
Jisi Liuada65562015-02-25 16:39:11 -0800214 PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s",
215 message_type->full_name().c_str());
216 return NULL;
217 }
218 ScopedPyObjectPtr value(PyEval_CallObject(message_class, NULL));
219 if (value == NULL) {
220 return NULL;
221 }
Feng Xiaoe841bac2015-12-11 17:09:20 -0800222 if (!PyObject_TypeCheck(value.get(), &CMessage_Type)) {
223 PyErr_Format(PyExc_TypeError, "Invalid class for %s: %s",
224 message_type->full_name().c_str(),
225 Py_TYPE(value.get())->tp_name);
226 return NULL;
227 }
Jisi Liuada65562015-02-25 16:39:11 -0800228 CMessage* cmsg = reinterpret_cast<CMessage*>(value.get());
229
230 const Reflection* reflection = options.GetReflection();
231 const UnknownFieldSet& unknown_fields(reflection->GetUnknownFields(options));
232 if (unknown_fields.empty()) {
233 cmsg->message->CopyFrom(options);
234 } else {
235 // Reparse options string! XXX call cmessage::MergeFromString
236 string serialized;
237 options.SerializeToString(&serialized);
238 io::CodedInputStream input(
239 reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
Jisi Liu46e8ff62015-10-05 11:59:43 -0700240 input.SetExtensionRegistry(pool->pool, pool->message_factory);
Jisi Liuada65562015-02-25 16:39:11 -0800241 bool success = cmsg->message->MergePartialFromCodedStream(&input);
242 if (!success) {
243 PyErr_Format(PyExc_ValueError, "Error parsing Options message");
244 return NULL;
245 }
246 }
247
248 // Cache the result.
Josh Haberman00700b72015-10-06 14:13:09 -0700249 Py_INCREF(value.get());
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700250 (*pool->descriptor_options)[descriptor] = value.get();
Jisi Liuada65562015-02-25 16:39:11 -0800251
252 return value.release();
253}
254
255// Copy the C++ descriptor to a Python message.
256// The Python message is an instance of descriptor_pb2.DescriptorProto
257// or similar.
258template<class DescriptorProtoClass, class DescriptorClass>
259static PyObject* CopyToPythonProto(const DescriptorClass *descriptor,
260 PyObject *target) {
261 const Descriptor* self_descriptor =
262 DescriptorProtoClass::default_instance().GetDescriptor();
263 CMessage* message = reinterpret_cast<CMessage*>(target);
264 if (!PyObject_TypeCheck(target, &CMessage_Type) ||
265 message->message->GetDescriptor() != self_descriptor) {
266 PyErr_Format(PyExc_TypeError, "Not a %s message",
267 self_descriptor->full_name().c_str());
268 return NULL;
269 }
270 cmessage::AssureWritable(message);
271 DescriptorProtoClass* descriptor_message =
272 static_cast<DescriptorProtoClass*>(message->message);
273 descriptor->CopyTo(descriptor_message);
274 Py_RETURN_NONE;
275}
276
277// All Descriptors classes share the same memory layout.
278typedef struct PyBaseDescriptor {
279 PyObject_HEAD
280
281 // Pointer to the C++ proto2 descriptor.
282 // Like all descriptors, it is owned by the global DescriptorPool.
283 const void* descriptor;
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700284
285 // Owned reference to the DescriptorPool, to ensure it is kept alive.
286 PyDescriptorPool* pool;
Jisi Liuada65562015-02-25 16:39:11 -0800287} PyBaseDescriptor;
288
289
290// FileDescriptor structure "inherits" from the base descriptor.
291typedef struct PyFileDescriptor {
292 PyBaseDescriptor base;
293
294 // The cached version of serialized pb. Either NULL, or a Bytes string.
295 // We own the reference.
296 PyObject *serialized_pb;
297} PyFileDescriptor;
298
299
300namespace descriptor {
301
302// Creates or retrieve a Python descriptor of the specified type.
303// Objects are interned: the same descriptor will return the same object if it
304// was kept alive.
Bo Yang5db21732015-05-21 14:28:59 -0700305// 'was_created' is an optional pointer to a bool, and is set to true if a new
306// object was allocated.
Jisi Liuada65562015-02-25 16:39:11 -0800307// Always return a new reference.
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700308template<class DescriptorClass>
309PyObject* NewInternedDescriptor(PyTypeObject* type,
310 const DescriptorClass* descriptor,
Bo Yang5db21732015-05-21 14:28:59 -0700311 bool* was_created) {
312 if (was_created) {
313 *was_created = false;
314 }
Jisi Liuada65562015-02-25 16:39:11 -0800315 if (descriptor == NULL) {
316 PyErr_BadInternalCall();
317 return NULL;
318 }
319
320 // See if the object is in the map of interned descriptors
321 hash_map<const void*, PyObject*>::iterator it =
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700322 interned_descriptors.find(descriptor);
323 if (it != interned_descriptors.end()) {
Jisi Liuada65562015-02-25 16:39:11 -0800324 GOOGLE_DCHECK(Py_TYPE(it->second) == type);
325 Py_INCREF(it->second);
326 return it->second;
327 }
328 // Create a new descriptor object
329 PyBaseDescriptor* py_descriptor = PyObject_New(
330 PyBaseDescriptor, type);
331 if (py_descriptor == NULL) {
332 return NULL;
333 }
334 py_descriptor->descriptor = descriptor;
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700335
Jisi Liuada65562015-02-25 16:39:11 -0800336 // and cache it.
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700337 interned_descriptors.insert(
Jisi Liuada65562015-02-25 16:39:11 -0800338 std::make_pair(descriptor, reinterpret_cast<PyObject*>(py_descriptor)));
339
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700340 // Ensures that the DescriptorPool stays alive.
341 PyDescriptorPool* pool = GetDescriptorPool_FromPool(
342 GetFileDescriptor(descriptor)->pool());
343 if (pool == NULL) {
Feng Xiaoe841bac2015-12-11 17:09:20 -0800344 // Don't DECREF, the object is not fully initialized.
345 PyObject_Del(py_descriptor);
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700346 return NULL;
347 }
348 Py_INCREF(pool);
349 py_descriptor->pool = pool;
350
Bo Yang5db21732015-05-21 14:28:59 -0700351 if (was_created) {
352 *was_created = true;
353 }
Jisi Liuada65562015-02-25 16:39:11 -0800354 return reinterpret_cast<PyObject*>(py_descriptor);
355}
356
357static void Dealloc(PyBaseDescriptor* self) {
358 // Remove from interned dictionary
Feng Xiaob17ec3c2015-08-23 17:50:38 -0700359 interned_descriptors.erase(self->descriptor);
360 Py_CLEAR(self->pool);
Feng Xiao6ef984a2014-11-10 17:34:54 -0800361 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
362}
363
Feng Xiao6ef984a2014-11-10 17:34:54 -0800364static PyGetSetDef Getters[] = {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800365 {NULL}
366};
367
Jisi Liuada65562015-02-25 16:39:11 -0800368PyTypeObject PyBaseDescriptor_Type = {
369 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Bo Yang5db21732015-05-21 14:28:59 -0700370 FULL_MODULE_NAME ".DescriptorBase", // tp_name
Jisi Liuada65562015-02-25 16:39:11 -0800371 sizeof(PyBaseDescriptor), // tp_basicsize
372 0, // tp_itemsize
373 (destructor)Dealloc, // tp_dealloc
374 0, // tp_print
375 0, // tp_getattr
376 0, // tp_setattr
377 0, // tp_compare
378 0, // tp_repr
379 0, // tp_as_number
380 0, // tp_as_sequence
381 0, // tp_as_mapping
382 0, // tp_hash
383 0, // tp_call
384 0, // tp_str
385 0, // tp_getattro
386 0, // tp_setattro
387 0, // tp_as_buffer
388 Py_TPFLAGS_DEFAULT, // tp_flags
389 "Descriptors base class", // tp_doc
390 0, // tp_traverse
391 0, // tp_clear
392 0, // tp_richcompare
393 0, // tp_weaklistoffset
394 0, // tp_iter
395 0, // tp_iternext
396 0, // tp_methods
397 0, // tp_members
398 Getters, // tp_getset
399};
Feng Xiao6ef984a2014-11-10 17:34:54 -0800400
Jisi Liuada65562015-02-25 16:39:11 -0800401} // namespace descriptor
402
403const void* PyDescriptor_AsVoidPtr(PyObject* obj) {
404 if (!PyObject_TypeCheck(obj, &descriptor::PyBaseDescriptor_Type)) {
405 PyErr_SetString(PyExc_TypeError, "Not a BaseDescriptor");
406 return NULL;
407 }
408 return reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor;
409}
410
411namespace message_descriptor {
412
413// Unchecked accessor to the C++ pointer.
414static const Descriptor* _GetDescriptor(PyBaseDescriptor* self) {
415 return reinterpret_cast<const Descriptor*>(self->descriptor);
416}
417
418static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
419 return PyString_FromCppString(_GetDescriptor(self)->name());
420}
421
422static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
423 return PyString_FromCppString(_GetDescriptor(self)->full_name());
424}
425
426static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
Bo Yang5db21732015-05-21 14:28:59 -0700427 return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
Jisi Liuada65562015-02-25 16:39:11 -0800428}
429
430static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
Jisi Liu46e8ff62015-10-05 11:59:43 -0700431 // Retuns the canonical class for the given descriptor.
432 // This is the class that was registered with the primary descriptor pool
433 // which contains this descriptor.
434 // This might not be the one you expect! For example the returned object does
435 // not know about extensions defined in a custom pool.
Jisi Liuada65562015-02-25 16:39:11 -0800436 PyObject* concrete_class(cdescriptor_pool::GetMessageClass(
Jisi Liu46e8ff62015-10-05 11:59:43 -0700437 GetDescriptorPool_FromPool(_GetDescriptor(self)->file()->pool()),
438 _GetDescriptor(self)));
Jisi Liuada65562015-02-25 16:39:11 -0800439 Py_XINCREF(concrete_class);
440 return concrete_class;
441}
442
Jisi Liuada65562015-02-25 16:39:11 -0800443static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) {
444 return NewMessageFieldsByName(_GetDescriptor(self));
445}
446
Jisi Liu46e8ff62015-10-05 11:59:43 -0700447static PyObject* GetFieldsByCamelcaseName(PyBaseDescriptor* self,
448 void *closure) {
449 return NewMessageFieldsByCamelcaseName(_GetDescriptor(self));
450}
451
Jisi Liuada65562015-02-25 16:39:11 -0800452static PyObject* GetFieldsByNumber(PyBaseDescriptor* self, void *closure) {
453 return NewMessageFieldsByNumber(_GetDescriptor(self));
454}
455
456static PyObject* GetFieldsSeq(PyBaseDescriptor* self, void *closure) {
457 return NewMessageFieldsSeq(_GetDescriptor(self));
458}
459
460static PyObject* GetNestedTypesByName(PyBaseDescriptor* self, void *closure) {
461 return NewMessageNestedTypesByName(_GetDescriptor(self));
462}
463
464static PyObject* GetNestedTypesSeq(PyBaseDescriptor* self, void *closure) {
465 return NewMessageNestedTypesSeq(_GetDescriptor(self));
466}
467
468static PyObject* GetExtensionsByName(PyBaseDescriptor* self, void *closure) {
469 return NewMessageExtensionsByName(_GetDescriptor(self));
470}
471
472static PyObject* GetExtensions(PyBaseDescriptor* self, void *closure) {
473 return NewMessageExtensionsSeq(_GetDescriptor(self));
474}
475
476static PyObject* GetEnumsSeq(PyBaseDescriptor* self, void *closure) {
477 return NewMessageEnumsSeq(_GetDescriptor(self));
478}
479
480static PyObject* GetEnumTypesByName(PyBaseDescriptor* self, void *closure) {
481 return NewMessageEnumsByName(_GetDescriptor(self));
482}
483
484static PyObject* GetEnumValuesByName(PyBaseDescriptor* self, void *closure) {
485 return NewMessageEnumValuesByName(_GetDescriptor(self));
486}
487
488static PyObject* GetOneofsByName(PyBaseDescriptor* self, void *closure) {
489 return NewMessageOneofsByName(_GetDescriptor(self));
490}
491
492static PyObject* GetOneofsSeq(PyBaseDescriptor* self, void *closure) {
493 return NewMessageOneofsSeq(_GetDescriptor(self));
494}
495
496static PyObject* IsExtendable(PyBaseDescriptor *self, void *closure) {
497 if (_GetDescriptor(self)->extension_range_count() > 0) {
498 Py_RETURN_TRUE;
499 } else {
500 Py_RETURN_FALSE;
501 }
502}
503
Josh Haberman0b70a432015-02-25 20:17:32 -0800504static PyObject* GetExtensionRanges(PyBaseDescriptor *self, void *closure) {
505 const Descriptor* descriptor = _GetDescriptor(self);
506 PyObject* range_list = PyList_New(descriptor->extension_range_count());
507
508 for (int i = 0; i < descriptor->extension_range_count(); i++) {
509 const Descriptor::ExtensionRange* range = descriptor->extension_range(i);
510 PyObject* start = PyInt_FromLong(range->start);
511 PyObject* end = PyInt_FromLong(range->end);
512 PyList_SetItem(range_list, i, PyTuple_Pack(2, start, end));
513 }
514
515 return range_list;
516}
517
Jisi Liuada65562015-02-25 16:39:11 -0800518static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
519 const Descriptor* containing_type =
520 _GetDescriptor(self)->containing_type();
521 if (containing_type) {
Bo Yang5db21732015-05-21 14:28:59 -0700522 return PyMessageDescriptor_FromDescriptor(containing_type);
Jisi Liuada65562015-02-25 16:39:11 -0800523 } else {
524 Py_RETURN_NONE;
525 }
526}
527
528static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
529 void *closure) {
530 return CheckCalledFromGeneratedFile("containing_type");
531}
532
533static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
534 const MessageOptions& options(_GetDescriptor(self)->options());
535 if (&options != &MessageOptions::default_instance()) {
536 Py_RETURN_TRUE;
537 } else {
538 Py_RETURN_FALSE;
539 }
540}
541static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
542 void *closure) {
543 return CheckCalledFromGeneratedFile("has_options");
544}
545
546static PyObject* GetOptions(PyBaseDescriptor *self) {
547 return GetOrBuildOptions(_GetDescriptor(self));
548}
549
550static int SetOptions(PyBaseDescriptor *self, PyObject *value,
551 void *closure) {
552 return CheckCalledFromGeneratedFile("_options");
553}
554
555static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
556 return CopyToPythonProto<DescriptorProto>(_GetDescriptor(self), target);
557}
558
559static PyObject* EnumValueName(PyBaseDescriptor *self, PyObject *args) {
560 const char *enum_name;
561 int number;
562 if (!PyArg_ParseTuple(args, "si", &enum_name, &number))
563 return NULL;
564 const EnumDescriptor *enum_type =
565 _GetDescriptor(self)->FindEnumTypeByName(enum_name);
566 if (enum_type == NULL) {
567 PyErr_SetString(PyExc_KeyError, enum_name);
568 return NULL;
569 }
570 const EnumValueDescriptor *enum_value =
571 enum_type->FindValueByNumber(number);
572 if (enum_value == NULL) {
573 PyErr_Format(PyExc_KeyError, "%d", number);
574 return NULL;
575 }
576 return PyString_FromCppString(enum_value->name());
577}
578
579static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) {
580 return PyString_InternFromString(
581 FileDescriptor::SyntaxName(_GetDescriptor(self)->file()->syntax()));
582}
583
584static PyGetSetDef Getters[] = {
Bo Yang5db21732015-05-21 14:28:59 -0700585 { "name", (getter)GetName, NULL, "Last name"},
586 { "full_name", (getter)GetFullName, NULL, "Full name"},
587 { "_concrete_class", (getter)GetConcreteClass, NULL, "concrete class"},
588 { "file", (getter)GetFile, NULL, "File descriptor"},
Jisi Liuada65562015-02-25 16:39:11 -0800589
Bo Yang5db21732015-05-21 14:28:59 -0700590 { "fields", (getter)GetFieldsSeq, NULL, "Fields sequence"},
591 { "fields_by_name", (getter)GetFieldsByName, NULL, "Fields by name"},
Jisi Liu46e8ff62015-10-05 11:59:43 -0700592 { "fields_by_camelcase_name", (getter)GetFieldsByCamelcaseName, NULL,
593 "Fields by camelCase name"},
Bo Yang5db21732015-05-21 14:28:59 -0700594 { "fields_by_number", (getter)GetFieldsByNumber, NULL, "Fields by number"},
595 { "nested_types", (getter)GetNestedTypesSeq, NULL, "Nested types sequence"},
596 { "nested_types_by_name", (getter)GetNestedTypesByName, NULL,
597 "Nested types by name"},
598 { "extensions", (getter)GetExtensions, NULL, "Extensions Sequence"},
599 { "extensions_by_name", (getter)GetExtensionsByName, NULL,
600 "Extensions by name"},
601 { "extension_ranges", (getter)GetExtensionRanges, NULL, "Extension ranges"},
602 { "enum_types", (getter)GetEnumsSeq, NULL, "Enum sequence"},
603 { "enum_types_by_name", (getter)GetEnumTypesByName, NULL,
604 "Enum types by name"},
605 { "enum_values_by_name", (getter)GetEnumValuesByName, NULL,
606 "Enum values by name"},
607 { "oneofs_by_name", (getter)GetOneofsByName, NULL, "Oneofs by name"},
608 { "oneofs", (getter)GetOneofsSeq, NULL, "Oneofs by name"},
609 { "containing_type", (getter)GetContainingType, (setter)SetContainingType,
610 "Containing type"},
611 { "is_extendable", (getter)IsExtendable, (setter)NULL},
612 { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
613 { "_options", (getter)NULL, (setter)SetOptions, "Options"},
614 { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
Jisi Liuada65562015-02-25 16:39:11 -0800615 {NULL}
616};
617
618static PyMethodDef Methods[] = {
619 { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
620 { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
621 { "EnumValueName", (PyCFunction)EnumValueName, METH_VARARGS, },
622 {NULL}
623};
624
625} // namespace message_descriptor
626
627PyTypeObject PyMessageDescriptor_Type = {
Feng Xiao6ef984a2014-11-10 17:34:54 -0800628 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Bo Yang5db21732015-05-21 14:28:59 -0700629 FULL_MODULE_NAME ".MessageDescriptor", // tp_name
Jisi Liuada65562015-02-25 16:39:11 -0800630 sizeof(PyBaseDescriptor), // tp_basicsize
Feng Xiao6ef984a2014-11-10 17:34:54 -0800631 0, // tp_itemsize
Jisi Liuada65562015-02-25 16:39:11 -0800632 0, // tp_dealloc
Feng Xiao6ef984a2014-11-10 17:34:54 -0800633 0, // tp_print
634 0, // tp_getattr
635 0, // tp_setattr
636 0, // tp_compare
637 0, // tp_repr
638 0, // tp_as_number
639 0, // tp_as_sequence
640 0, // tp_as_mapping
641 0, // tp_hash
642 0, // tp_call
643 0, // tp_str
644 0, // tp_getattro
645 0, // tp_setattro
646 0, // tp_as_buffer
647 Py_TPFLAGS_DEFAULT, // tp_flags
Bo Yang5db21732015-05-21 14:28:59 -0700648 "A Message Descriptor", // tp_doc
Feng Xiao6ef984a2014-11-10 17:34:54 -0800649 0, // tp_traverse
650 0, // tp_clear
651 0, // tp_richcompare
652 0, // tp_weaklistoffset
653 0, // tp_iter
654 0, // tp_iternext
Jisi Liuada65562015-02-25 16:39:11 -0800655 message_descriptor::Methods, // tp_methods
Feng Xiao6ef984a2014-11-10 17:34:54 -0800656 0, // tp_members
Jisi Liuada65562015-02-25 16:39:11 -0800657 message_descriptor::Getters, // tp_getset
658 &descriptor::PyBaseDescriptor_Type, // tp_base
Feng Xiao6ef984a2014-11-10 17:34:54 -0800659};
660
Bo Yang5db21732015-05-21 14:28:59 -0700661PyObject* PyMessageDescriptor_FromDescriptor(
Jisi Liuada65562015-02-25 16:39:11 -0800662 const Descriptor* message_descriptor) {
663 return descriptor::NewInternedDescriptor(
Bo Yang5db21732015-05-21 14:28:59 -0700664 &PyMessageDescriptor_Type, message_descriptor, NULL);
jieluo@google.combde4a322014-08-12 21:10:30 +0000665}
666
Jisi Liuada65562015-02-25 16:39:11 -0800667const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj) {
668 if (!PyObject_TypeCheck(obj, &PyMessageDescriptor_Type)) {
669 PyErr_SetString(PyExc_TypeError, "Not a MessageDescriptor");
670 return NULL;
671 }
672 return reinterpret_cast<const Descriptor*>(
673 reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
jieluo@google.combde4a322014-08-12 21:10:30 +0000674}
675
Jisi Liuada65562015-02-25 16:39:11 -0800676namespace field_descriptor {
677
678// Unchecked accessor to the C++ pointer.
679static const FieldDescriptor* _GetDescriptor(
680 PyBaseDescriptor *self) {
681 return reinterpret_cast<const FieldDescriptor*>(self->descriptor);
jieluo@google.combde4a322014-08-12 21:10:30 +0000682}
683
Jisi Liuada65562015-02-25 16:39:11 -0800684static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
685 return PyString_FromCppString(_GetDescriptor(self)->full_name());
jieluo@google.combde4a322014-08-12 21:10:30 +0000686}
687
Jisi Liuada65562015-02-25 16:39:11 -0800688static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
689 return PyString_FromCppString(_GetDescriptor(self)->name());
jieluo@google.combde4a322014-08-12 21:10:30 +0000690}
691
Jisi Liu46e8ff62015-10-05 11:59:43 -0700692static PyObject* GetCamelcaseName(PyBaseDescriptor* self, void *closure) {
693 return PyString_FromCppString(_GetDescriptor(self)->camelcase_name());
694}
695
Jisi Liuada65562015-02-25 16:39:11 -0800696static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
697 return PyInt_FromLong(_GetDescriptor(self)->type());
698}
699
700static PyObject* GetCppType(PyBaseDescriptor *self, void *closure) {
701 return PyInt_FromLong(_GetDescriptor(self)->cpp_type());
702}
703
704static PyObject* GetLabel(PyBaseDescriptor *self, void *closure) {
705 return PyInt_FromLong(_GetDescriptor(self)->label());
706}
707
708static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
709 return PyInt_FromLong(_GetDescriptor(self)->number());
710}
711
712static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
713 return PyInt_FromLong(_GetDescriptor(self)->index());
714}
715
716static PyObject* GetID(PyBaseDescriptor *self, void *closure) {
jieluo@google.combde4a322014-08-12 21:10:30 +0000717 return PyLong_FromVoidPtr(self);
718}
719
Jisi Liuada65562015-02-25 16:39:11 -0800720static PyObject* IsExtension(PyBaseDescriptor *self, void *closure) {
721 return PyBool_FromLong(_GetDescriptor(self)->is_extension());
722}
723
724static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) {
725 return PyBool_FromLong(_GetDescriptor(self)->has_default_value());
726}
727
728static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
729 PyObject *result;
730
731 switch (_GetDescriptor(self)->cpp_type()) {
732 case FieldDescriptor::CPPTYPE_INT32: {
733 int32 value = _GetDescriptor(self)->default_value_int32();
734 result = PyInt_FromLong(value);
735 break;
736 }
737 case FieldDescriptor::CPPTYPE_INT64: {
738 int64 value = _GetDescriptor(self)->default_value_int64();
739 result = PyLong_FromLongLong(value);
740 break;
741 }
742 case FieldDescriptor::CPPTYPE_UINT32: {
743 uint32 value = _GetDescriptor(self)->default_value_uint32();
744 result = PyInt_FromSize_t(value);
745 break;
746 }
747 case FieldDescriptor::CPPTYPE_UINT64: {
748 uint64 value = _GetDescriptor(self)->default_value_uint64();
749 result = PyLong_FromUnsignedLongLong(value);
750 break;
751 }
752 case FieldDescriptor::CPPTYPE_FLOAT: {
753 float value = _GetDescriptor(self)->default_value_float();
754 result = PyFloat_FromDouble(value);
755 break;
756 }
757 case FieldDescriptor::CPPTYPE_DOUBLE: {
758 double value = _GetDescriptor(self)->default_value_double();
759 result = PyFloat_FromDouble(value);
760 break;
761 }
762 case FieldDescriptor::CPPTYPE_BOOL: {
763 bool value = _GetDescriptor(self)->default_value_bool();
764 result = PyBool_FromLong(value);
765 break;
766 }
767 case FieldDescriptor::CPPTYPE_STRING: {
768 string value = _GetDescriptor(self)->default_value_string();
769 result = ToStringObject(_GetDescriptor(self), value);
770 break;
771 }
772 case FieldDescriptor::CPPTYPE_ENUM: {
773 const EnumValueDescriptor* value =
774 _GetDescriptor(self)->default_value_enum();
775 result = PyInt_FromLong(value->number());
776 break;
777 }
778 default:
779 PyErr_Format(PyExc_NotImplementedError, "default value for %s",
780 _GetDescriptor(self)->full_name().c_str());
781 return NULL;
782 }
783 return result;
784}
785
786static PyObject* GetCDescriptor(PyObject *self, void *closure) {
787 Py_INCREF(self);
788 return self;
789}
790
791static PyObject *GetEnumType(PyBaseDescriptor *self, void *closure) {
792 const EnumDescriptor* enum_type = _GetDescriptor(self)->enum_type();
793 if (enum_type) {
Bo Yang5db21732015-05-21 14:28:59 -0700794 return PyEnumDescriptor_FromDescriptor(enum_type);
Jisi Liuada65562015-02-25 16:39:11 -0800795 } else {
796 Py_RETURN_NONE;
797 }
798}
799
800static int SetEnumType(PyBaseDescriptor *self, PyObject *value, void *closure) {
801 return CheckCalledFromGeneratedFile("enum_type");
802}
803
804static PyObject *GetMessageType(PyBaseDescriptor *self, void *closure) {
805 const Descriptor* message_type = _GetDescriptor(self)->message_type();
806 if (message_type) {
Bo Yang5db21732015-05-21 14:28:59 -0700807 return PyMessageDescriptor_FromDescriptor(message_type);
Jisi Liuada65562015-02-25 16:39:11 -0800808 } else {
809 Py_RETURN_NONE;
810 }
811}
812
813static int SetMessageType(PyBaseDescriptor *self, PyObject *value,
814 void *closure) {
815 return CheckCalledFromGeneratedFile("message_type");
816}
817
818static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
819 const Descriptor* containing_type =
820 _GetDescriptor(self)->containing_type();
821 if (containing_type) {
Bo Yang5db21732015-05-21 14:28:59 -0700822 return PyMessageDescriptor_FromDescriptor(containing_type);
Jisi Liuada65562015-02-25 16:39:11 -0800823 } else {
824 Py_RETURN_NONE;
825 }
826}
827
828static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
829 void *closure) {
830 return CheckCalledFromGeneratedFile("containing_type");
831}
832
833static PyObject* GetExtensionScope(PyBaseDescriptor *self, void *closure) {
834 const Descriptor* extension_scope =
835 _GetDescriptor(self)->extension_scope();
836 if (extension_scope) {
Bo Yang5db21732015-05-21 14:28:59 -0700837 return PyMessageDescriptor_FromDescriptor(extension_scope);
Jisi Liuada65562015-02-25 16:39:11 -0800838 } else {
839 Py_RETURN_NONE;
840 }
841}
842
843static PyObject* GetContainingOneof(PyBaseDescriptor *self, void *closure) {
844 const OneofDescriptor* containing_oneof =
845 _GetDescriptor(self)->containing_oneof();
846 if (containing_oneof) {
Bo Yang5db21732015-05-21 14:28:59 -0700847 return PyOneofDescriptor_FromDescriptor(containing_oneof);
Jisi Liuada65562015-02-25 16:39:11 -0800848 } else {
849 Py_RETURN_NONE;
850 }
851}
852
853static int SetContainingOneof(PyBaseDescriptor *self, PyObject *value,
854 void *closure) {
855 return CheckCalledFromGeneratedFile("containing_oneof");
856}
857
858static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
859 const FieldOptions& options(_GetDescriptor(self)->options());
860 if (&options != &FieldOptions::default_instance()) {
861 Py_RETURN_TRUE;
862 } else {
863 Py_RETURN_FALSE;
864 }
865}
866static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
867 void *closure) {
868 return CheckCalledFromGeneratedFile("has_options");
869}
870
871static PyObject* GetOptions(PyBaseDescriptor *self) {
872 return GetOrBuildOptions(_GetDescriptor(self));
873}
874
875static int SetOptions(PyBaseDescriptor *self, PyObject *value,
876 void *closure) {
877 return CheckCalledFromGeneratedFile("_options");
878}
879
880
jieluo@google.combde4a322014-08-12 21:10:30 +0000881static PyGetSetDef Getters[] = {
Bo Yang5db21732015-05-21 14:28:59 -0700882 { "full_name", (getter)GetFullName, NULL, "Full name"},
883 { "name", (getter)GetName, NULL, "Unqualified name"},
Jisi Liu46e8ff62015-10-05 11:59:43 -0700884 { "camelcase_name", (getter)GetCamelcaseName, NULL, "Camelcase name"},
Bo Yang5db21732015-05-21 14:28:59 -0700885 { "type", (getter)GetType, NULL, "C++ Type"},
886 { "cpp_type", (getter)GetCppType, NULL, "C++ Type"},
887 { "label", (getter)GetLabel, NULL, "Label"},
888 { "number", (getter)GetNumber, NULL, "Number"},
889 { "index", (getter)GetIndex, NULL, "Index"},
890 { "default_value", (getter)GetDefaultValue, NULL, "Default Value"},
891 { "has_default_value", (getter)HasDefaultValue},
892 { "is_extension", (getter)IsExtension, NULL, "ID"},
893 { "id", (getter)GetID, NULL, "ID"},
894 { "_cdescriptor", (getter)GetCDescriptor, NULL, "HAACK REMOVE ME"},
Jisi Liuada65562015-02-25 16:39:11 -0800895
Bo Yang5db21732015-05-21 14:28:59 -0700896 { "message_type", (getter)GetMessageType, (setter)SetMessageType,
897 "Message type"},
898 { "enum_type", (getter)GetEnumType, (setter)SetEnumType, "Enum type"},
899 { "containing_type", (getter)GetContainingType, (setter)SetContainingType,
900 "Containing type"},
901 { "extension_scope", (getter)GetExtensionScope, (setter)NULL,
902 "Extension scope"},
903 { "containing_oneof", (getter)GetContainingOneof, (setter)SetContainingOneof,
904 "Containing oneof"},
905 { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
906 { "_options", (getter)NULL, (setter)SetOptions, "Options"},
jieluo@google.combde4a322014-08-12 21:10:30 +0000907 {NULL}
908};
909
Jisi Liuada65562015-02-25 16:39:11 -0800910static PyMethodDef Methods[] = {
911 { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
912 {NULL}
913};
jieluo@google.combde4a322014-08-12 21:10:30 +0000914
Jisi Liuada65562015-02-25 16:39:11 -0800915} // namespace field_descriptor
916
917PyTypeObject PyFieldDescriptor_Type = {
jieluo@google.combde4a322014-08-12 21:10:30 +0000918 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Bo Yang5db21732015-05-21 14:28:59 -0700919 FULL_MODULE_NAME ".FieldDescriptor", // tp_name
Jisi Liuada65562015-02-25 16:39:11 -0800920 sizeof(PyBaseDescriptor), // tp_basicsize
jieluo@google.combde4a322014-08-12 21:10:30 +0000921 0, // tp_itemsize
Jisi Liuada65562015-02-25 16:39:11 -0800922 0, // tp_dealloc
jieluo@google.combde4a322014-08-12 21:10:30 +0000923 0, // tp_print
924 0, // tp_getattr
925 0, // tp_setattr
926 0, // tp_compare
927 0, // tp_repr
928 0, // tp_as_number
929 0, // tp_as_sequence
930 0, // tp_as_mapping
931 0, // tp_hash
932 0, // tp_call
933 0, // tp_str
934 0, // tp_getattro
935 0, // tp_setattro
936 0, // tp_as_buffer
937 Py_TPFLAGS_DEFAULT, // tp_flags
Bo Yang5db21732015-05-21 14:28:59 -0700938 "A Field Descriptor", // tp_doc
jieluo@google.combde4a322014-08-12 21:10:30 +0000939 0, // tp_traverse
940 0, // tp_clear
941 0, // tp_richcompare
942 0, // tp_weaklistoffset
943 0, // tp_iter
944 0, // tp_iternext
Jisi Liuada65562015-02-25 16:39:11 -0800945 field_descriptor::Methods, // tp_methods
jieluo@google.combde4a322014-08-12 21:10:30 +0000946 0, // tp_members
Jisi Liuada65562015-02-25 16:39:11 -0800947 field_descriptor::Getters, // tp_getset
948 &descriptor::PyBaseDescriptor_Type, // tp_base
949};
950
Bo Yang5db21732015-05-21 14:28:59 -0700951PyObject* PyFieldDescriptor_FromDescriptor(
Jisi Liuada65562015-02-25 16:39:11 -0800952 const FieldDescriptor* field_descriptor) {
953 return descriptor::NewInternedDescriptor(
Bo Yang5db21732015-05-21 14:28:59 -0700954 &PyFieldDescriptor_Type, field_descriptor, NULL);
Jisi Liuada65562015-02-25 16:39:11 -0800955}
956
957const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj) {
958 if (!PyObject_TypeCheck(obj, &PyFieldDescriptor_Type)) {
959 PyErr_SetString(PyExc_TypeError, "Not a FieldDescriptor");
960 return NULL;
961 }
962 return reinterpret_cast<const FieldDescriptor*>(
963 reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
964}
965
966namespace enum_descriptor {
967
968// Unchecked accessor to the C++ pointer.
969static const EnumDescriptor* _GetDescriptor(
970 PyBaseDescriptor *self) {
971 return reinterpret_cast<const EnumDescriptor*>(self->descriptor);
972}
973
974static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
975 return PyString_FromCppString(_GetDescriptor(self)->full_name());
976}
977
978static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
979 return PyString_FromCppString(_GetDescriptor(self)->name());
980}
981
982static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
Bo Yang5db21732015-05-21 14:28:59 -0700983 return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
Jisi Liuada65562015-02-25 16:39:11 -0800984}
985
986static PyObject* GetEnumvaluesByName(PyBaseDescriptor* self, void *closure) {
987 return NewEnumValuesByName(_GetDescriptor(self));
988}
989
990static PyObject* GetEnumvaluesByNumber(PyBaseDescriptor* self, void *closure) {
991 return NewEnumValuesByNumber(_GetDescriptor(self));
992}
993
994static PyObject* GetEnumvaluesSeq(PyBaseDescriptor* self, void *closure) {
995 return NewEnumValuesSeq(_GetDescriptor(self));
996}
997
998static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
999 const Descriptor* containing_type =
1000 _GetDescriptor(self)->containing_type();
1001 if (containing_type) {
Bo Yang5db21732015-05-21 14:28:59 -07001002 return PyMessageDescriptor_FromDescriptor(containing_type);
Jisi Liuada65562015-02-25 16:39:11 -08001003 } else {
1004 Py_RETURN_NONE;
1005 }
1006}
1007
1008static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
1009 void *closure) {
1010 return CheckCalledFromGeneratedFile("containing_type");
1011}
1012
1013
1014static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
1015 const EnumOptions& options(_GetDescriptor(self)->options());
1016 if (&options != &EnumOptions::default_instance()) {
1017 Py_RETURN_TRUE;
1018 } else {
1019 Py_RETURN_FALSE;
1020 }
1021}
1022static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
1023 void *closure) {
1024 return CheckCalledFromGeneratedFile("has_options");
1025}
1026
1027static PyObject* GetOptions(PyBaseDescriptor *self) {
1028 return GetOrBuildOptions(_GetDescriptor(self));
1029}
1030
1031static int SetOptions(PyBaseDescriptor *self, PyObject *value,
1032 void *closure) {
1033 return CheckCalledFromGeneratedFile("_options");
1034}
1035
1036static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
1037 return CopyToPythonProto<EnumDescriptorProto>(_GetDescriptor(self), target);
1038}
1039
1040static PyMethodDef Methods[] = {
1041 { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
1042 { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
1043 {NULL}
1044};
1045
1046static PyGetSetDef Getters[] = {
Bo Yang5db21732015-05-21 14:28:59 -07001047 { "full_name", (getter)GetFullName, NULL, "Full name"},
1048 { "name", (getter)GetName, NULL, "last name"},
1049 { "file", (getter)GetFile, NULL, "File descriptor"},
1050 { "values", (getter)GetEnumvaluesSeq, NULL, "values"},
1051 { "values_by_name", (getter)GetEnumvaluesByName, NULL,
1052 "Enum values by name"},
1053 { "values_by_number", (getter)GetEnumvaluesByNumber, NULL,
1054 "Enum values by number"},
Jisi Liuada65562015-02-25 16:39:11 -08001055
Bo Yang5db21732015-05-21 14:28:59 -07001056 { "containing_type", (getter)GetContainingType, (setter)SetContainingType,
1057 "Containing type"},
1058 { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
1059 { "_options", (getter)NULL, (setter)SetOptions, "Options"},
Jisi Liuada65562015-02-25 16:39:11 -08001060 {NULL}
1061};
1062
1063} // namespace enum_descriptor
1064
1065PyTypeObject PyEnumDescriptor_Type = {
1066 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Bo Yang5db21732015-05-21 14:28:59 -07001067 FULL_MODULE_NAME ".EnumDescriptor", // tp_name
Jisi Liuada65562015-02-25 16:39:11 -08001068 sizeof(PyBaseDescriptor), // tp_basicsize
1069 0, // tp_itemsize
1070 0, // tp_dealloc
1071 0, // tp_print
1072 0, // tp_getattr
1073 0, // tp_setattr
1074 0, // tp_compare
1075 0, // tp_repr
1076 0, // tp_as_number
1077 0, // tp_as_sequence
1078 0, // tp_as_mapping
1079 0, // tp_hash
1080 0, // tp_call
1081 0, // tp_str
1082 0, // tp_getattro
1083 0, // tp_setattro
1084 0, // tp_as_buffer
1085 Py_TPFLAGS_DEFAULT, // tp_flags
Bo Yang5db21732015-05-21 14:28:59 -07001086 "A Enum Descriptor", // tp_doc
Jisi Liuada65562015-02-25 16:39:11 -08001087 0, // tp_traverse
1088 0, // tp_clear
1089 0, // tp_richcompare
1090 0, // tp_weaklistoffset
1091 0, // tp_iter
1092 0, // tp_iternext
1093 enum_descriptor::Methods, // tp_getset
1094 0, // tp_members
1095 enum_descriptor::Getters, // tp_getset
1096 &descriptor::PyBaseDescriptor_Type, // tp_base
1097};
1098
Bo Yang5db21732015-05-21 14:28:59 -07001099PyObject* PyEnumDescriptor_FromDescriptor(
Jisi Liuada65562015-02-25 16:39:11 -08001100 const EnumDescriptor* enum_descriptor) {
1101 return descriptor::NewInternedDescriptor(
Bo Yang5db21732015-05-21 14:28:59 -07001102 &PyEnumDescriptor_Type, enum_descriptor, NULL);
Jisi Liuada65562015-02-25 16:39:11 -08001103}
1104
Jisi Liu46e8ff62015-10-05 11:59:43 -07001105const EnumDescriptor* PyEnumDescriptor_AsDescriptor(PyObject* obj) {
1106 if (!PyObject_TypeCheck(obj, &PyEnumDescriptor_Type)) {
1107 PyErr_SetString(PyExc_TypeError, "Not an EnumDescriptor");
1108 return NULL;
1109 }
1110 return reinterpret_cast<const EnumDescriptor*>(
1111 reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
1112}
1113
Jisi Liuada65562015-02-25 16:39:11 -08001114namespace enumvalue_descriptor {
1115
1116// Unchecked accessor to the C++ pointer.
1117static const EnumValueDescriptor* _GetDescriptor(
1118 PyBaseDescriptor *self) {
1119 return reinterpret_cast<const EnumValueDescriptor*>(self->descriptor);
1120}
1121
1122static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
1123 return PyString_FromCppString(_GetDescriptor(self)->name());
1124}
1125
1126static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
1127 return PyInt_FromLong(_GetDescriptor(self)->number());
1128}
1129
1130static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
1131 return PyInt_FromLong(_GetDescriptor(self)->index());
1132}
1133
1134static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
Bo Yang5db21732015-05-21 14:28:59 -07001135 return PyEnumDescriptor_FromDescriptor(_GetDescriptor(self)->type());
Jisi Liuada65562015-02-25 16:39:11 -08001136}
1137
1138static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
1139 const EnumValueOptions& options(_GetDescriptor(self)->options());
1140 if (&options != &EnumValueOptions::default_instance()) {
1141 Py_RETURN_TRUE;
1142 } else {
1143 Py_RETURN_FALSE;
1144 }
1145}
1146static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
1147 void *closure) {
1148 return CheckCalledFromGeneratedFile("has_options");
1149}
1150
1151static PyObject* GetOptions(PyBaseDescriptor *self) {
1152 return GetOrBuildOptions(_GetDescriptor(self));
1153}
1154
1155static int SetOptions(PyBaseDescriptor *self, PyObject *value,
1156 void *closure) {
1157 return CheckCalledFromGeneratedFile("_options");
1158}
1159
1160
1161static PyGetSetDef Getters[] = {
Bo Yang5db21732015-05-21 14:28:59 -07001162 { "name", (getter)GetName, NULL, "name"},
1163 { "number", (getter)GetNumber, NULL, "number"},
1164 { "index", (getter)GetIndex, NULL, "index"},
1165 { "type", (getter)GetType, NULL, "index"},
Jisi Liuada65562015-02-25 16:39:11 -08001166
Bo Yang5db21732015-05-21 14:28:59 -07001167 { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
1168 { "_options", (getter)NULL, (setter)SetOptions, "Options"},
Jisi Liuada65562015-02-25 16:39:11 -08001169 {NULL}
1170};
1171
1172static PyMethodDef Methods[] = {
1173 { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
1174 {NULL}
1175};
1176
1177} // namespace enumvalue_descriptor
1178
1179PyTypeObject PyEnumValueDescriptor_Type = {
1180 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Bo Yang5db21732015-05-21 14:28:59 -07001181 FULL_MODULE_NAME ".EnumValueDescriptor", // tp_name
Jisi Liuada65562015-02-25 16:39:11 -08001182 sizeof(PyBaseDescriptor), // tp_basicsize
1183 0, // tp_itemsize
1184 0, // tp_dealloc
1185 0, // tp_print
1186 0, // tp_getattr
1187 0, // tp_setattr
1188 0, // tp_compare
1189 0, // tp_repr
1190 0, // tp_as_number
1191 0, // tp_as_sequence
1192 0, // tp_as_mapping
1193 0, // tp_hash
1194 0, // tp_call
1195 0, // tp_str
1196 0, // tp_getattro
1197 0, // tp_setattro
1198 0, // tp_as_buffer
1199 Py_TPFLAGS_DEFAULT, // tp_flags
Bo Yang5db21732015-05-21 14:28:59 -07001200 "A EnumValue Descriptor", // tp_doc
Jisi Liuada65562015-02-25 16:39:11 -08001201 0, // tp_traverse
1202 0, // tp_clear
1203 0, // tp_richcompare
1204 0, // tp_weaklistoffset
1205 0, // tp_iter
1206 0, // tp_iternext
1207 enumvalue_descriptor::Methods, // tp_methods
1208 0, // tp_members
1209 enumvalue_descriptor::Getters, // tp_getset
1210 &descriptor::PyBaseDescriptor_Type, // tp_base
1211};
1212
Bo Yang5db21732015-05-21 14:28:59 -07001213PyObject* PyEnumValueDescriptor_FromDescriptor(
Jisi Liuada65562015-02-25 16:39:11 -08001214 const EnumValueDescriptor* enumvalue_descriptor) {
1215 return descriptor::NewInternedDescriptor(
Bo Yang5db21732015-05-21 14:28:59 -07001216 &PyEnumValueDescriptor_Type, enumvalue_descriptor, NULL);
Jisi Liuada65562015-02-25 16:39:11 -08001217}
1218
1219namespace file_descriptor {
1220
1221// Unchecked accessor to the C++ pointer.
1222static const FileDescriptor* _GetDescriptor(PyFileDescriptor *self) {
1223 return reinterpret_cast<const FileDescriptor*>(self->base.descriptor);
1224}
1225
1226static void Dealloc(PyFileDescriptor* self) {
1227 Py_XDECREF(self->serialized_pb);
1228 descriptor::Dealloc(&self->base);
1229}
1230
Feng Xiaoe841bac2015-12-11 17:09:20 -08001231static PyObject* GetPool(PyFileDescriptor *self, void *closure) {
1232 PyObject* pool = reinterpret_cast<PyObject*>(
1233 GetDescriptorPool_FromPool(_GetDescriptor(self)->pool()));
1234 Py_XINCREF(pool);
1235 return pool;
1236}
1237
Jisi Liuada65562015-02-25 16:39:11 -08001238static PyObject* GetName(PyFileDescriptor *self, void *closure) {
1239 return PyString_FromCppString(_GetDescriptor(self)->name());
1240}
1241
1242static PyObject* GetPackage(PyFileDescriptor *self, void *closure) {
1243 return PyString_FromCppString(_GetDescriptor(self)->package());
1244}
1245
1246static PyObject* GetSerializedPb(PyFileDescriptor *self, void *closure) {
1247 PyObject *serialized_pb = self->serialized_pb;
1248 if (serialized_pb != NULL) {
1249 Py_INCREF(serialized_pb);
1250 return serialized_pb;
1251 }
1252 FileDescriptorProto file_proto;
1253 _GetDescriptor(self)->CopyTo(&file_proto);
1254 string contents;
1255 file_proto.SerializePartialToString(&contents);
1256 self->serialized_pb = PyBytes_FromStringAndSize(
1257 contents.c_str(), contents.size());
1258 if (self->serialized_pb == NULL) {
1259 return NULL;
1260 }
1261 Py_INCREF(self->serialized_pb);
1262 return self->serialized_pb;
1263}
1264
1265static PyObject* GetMessageTypesByName(PyFileDescriptor* self, void *closure) {
1266 return NewFileMessageTypesByName(_GetDescriptor(self));
1267}
1268
1269static PyObject* GetEnumTypesByName(PyFileDescriptor* self, void *closure) {
1270 return NewFileEnumTypesByName(_GetDescriptor(self));
1271}
1272
1273static PyObject* GetExtensionsByName(PyFileDescriptor* self, void *closure) {
1274 return NewFileExtensionsByName(_GetDescriptor(self));
1275}
1276
1277static PyObject* GetDependencies(PyFileDescriptor* self, void *closure) {
1278 return NewFileDependencies(_GetDescriptor(self));
1279}
1280
1281static PyObject* GetPublicDependencies(PyFileDescriptor* self, void *closure) {
1282 return NewFilePublicDependencies(_GetDescriptor(self));
1283}
1284
1285static PyObject* GetHasOptions(PyFileDescriptor *self, void *closure) {
1286 const FileOptions& options(_GetDescriptor(self)->options());
1287 if (&options != &FileOptions::default_instance()) {
1288 Py_RETURN_TRUE;
1289 } else {
1290 Py_RETURN_FALSE;
1291 }
1292}
1293static int SetHasOptions(PyFileDescriptor *self, PyObject *value,
1294 void *closure) {
1295 return CheckCalledFromGeneratedFile("has_options");
1296}
1297
1298static PyObject* GetOptions(PyFileDescriptor *self) {
1299 return GetOrBuildOptions(_GetDescriptor(self));
1300}
1301
1302static int SetOptions(PyFileDescriptor *self, PyObject *value,
1303 void *closure) {
1304 return CheckCalledFromGeneratedFile("_options");
1305}
1306
1307static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) {
1308 return PyString_InternFromString(
1309 FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax()));
1310}
1311
1312static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) {
1313 return CopyToPythonProto<FileDescriptorProto>(_GetDescriptor(self), target);
1314}
1315
1316static PyGetSetDef Getters[] = {
Feng Xiaoe841bac2015-12-11 17:09:20 -08001317 { "pool", (getter)GetPool, NULL, "pool"},
Bo Yang5db21732015-05-21 14:28:59 -07001318 { "name", (getter)GetName, NULL, "name"},
1319 { "package", (getter)GetPackage, NULL, "package"},
1320 { "serialized_pb", (getter)GetSerializedPb},
1321 { "message_types_by_name", (getter)GetMessageTypesByName, NULL,
1322 "Messages by name"},
1323 { "enum_types_by_name", (getter)GetEnumTypesByName, NULL, "Enums by name"},
1324 { "extensions_by_name", (getter)GetExtensionsByName, NULL,
1325 "Extensions by name"},
1326 { "dependencies", (getter)GetDependencies, NULL, "Dependencies"},
1327 { "public_dependencies", (getter)GetPublicDependencies, NULL, "Dependencies"},
Jisi Liuada65562015-02-25 16:39:11 -08001328
Bo Yang5db21732015-05-21 14:28:59 -07001329 { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
1330 { "_options", (getter)NULL, (setter)SetOptions, "Options"},
1331 { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
Jisi Liuada65562015-02-25 16:39:11 -08001332 {NULL}
1333};
1334
1335static PyMethodDef Methods[] = {
1336 { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
1337 { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
1338 {NULL}
1339};
1340
1341} // namespace file_descriptor
1342
1343PyTypeObject PyFileDescriptor_Type = {
1344 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Bo Yang5db21732015-05-21 14:28:59 -07001345 FULL_MODULE_NAME ".FileDescriptor", // tp_name
Jisi Liuada65562015-02-25 16:39:11 -08001346 sizeof(PyFileDescriptor), // tp_basicsize
1347 0, // tp_itemsize
Bo Yang5db21732015-05-21 14:28:59 -07001348 (destructor)file_descriptor::Dealloc, // tp_dealloc
Jisi Liuada65562015-02-25 16:39:11 -08001349 0, // tp_print
1350 0, // tp_getattr
1351 0, // tp_setattr
1352 0, // tp_compare
1353 0, // tp_repr
1354 0, // tp_as_number
1355 0, // tp_as_sequence
1356 0, // tp_as_mapping
1357 0, // tp_hash
1358 0, // tp_call
1359 0, // tp_str
1360 0, // tp_getattro
1361 0, // tp_setattro
1362 0, // tp_as_buffer
1363 Py_TPFLAGS_DEFAULT, // tp_flags
Bo Yang5db21732015-05-21 14:28:59 -07001364 "A File Descriptor", // tp_doc
Jisi Liuada65562015-02-25 16:39:11 -08001365 0, // tp_traverse
1366 0, // tp_clear
1367 0, // tp_richcompare
1368 0, // tp_weaklistoffset
1369 0, // tp_iter
1370 0, // tp_iternext
1371 file_descriptor::Methods, // tp_methods
1372 0, // tp_members
1373 file_descriptor::Getters, // tp_getset
1374 &descriptor::PyBaseDescriptor_Type, // tp_base
jieluo@google.combde4a322014-08-12 21:10:30 +00001375 0, // tp_dict
1376 0, // tp_descr_get
1377 0, // tp_descr_set
1378 0, // tp_dictoffset
1379 0, // tp_init
Feng Xiaoe841bac2015-12-11 17:09:20 -08001380 0, // tp_alloc
1381 0, // tp_new
jieluo@google.combde4a322014-08-12 21:10:30 +00001382 PyObject_Del, // tp_free
1383};
1384
Bo Yang5db21732015-05-21 14:28:59 -07001385PyObject* PyFileDescriptor_FromDescriptor(
1386 const FileDescriptor* file_descriptor) {
1387 return PyFileDescriptor_FromDescriptorWithSerializedPb(file_descriptor,
1388 NULL);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001389}
1390
Bo Yang5db21732015-05-21 14:28:59 -07001391PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb(
Jisi Liuada65562015-02-25 16:39:11 -08001392 const FileDescriptor* file_descriptor, PyObject *serialized_pb) {
Bo Yang5db21732015-05-21 14:28:59 -07001393 bool was_created;
1394 PyObject* py_descriptor = descriptor::NewInternedDescriptor(
1395 &PyFileDescriptor_Type, file_descriptor, &was_created);
Jisi Liuada65562015-02-25 16:39:11 -08001396 if (py_descriptor == NULL) {
1397 return NULL;
Feng Xiao6ef984a2014-11-10 17:34:54 -08001398 }
Bo Yang5db21732015-05-21 14:28:59 -07001399 if (was_created) {
Jisi Liuada65562015-02-25 16:39:11 -08001400 PyFileDescriptor* cfile_descriptor =
1401 reinterpret_cast<PyFileDescriptor*>(py_descriptor);
1402 Py_XINCREF(serialized_pb);
1403 cfile_descriptor->serialized_pb = serialized_pb;
1404 }
Bo Yang5db21732015-05-21 14:28:59 -07001405 // TODO(amauryfa): In the case of a cached object, check that serialized_pb
1406 // is the same as before.
Jisi Liuada65562015-02-25 16:39:11 -08001407
1408 return py_descriptor;
jieluo@google.combde4a322014-08-12 21:10:30 +00001409}
1410
Jisi Liu46e8ff62015-10-05 11:59:43 -07001411const FileDescriptor* PyFileDescriptor_AsDescriptor(PyObject* obj) {
1412 if (!PyObject_TypeCheck(obj, &PyFileDescriptor_Type)) {
1413 PyErr_SetString(PyExc_TypeError, "Not a FileDescriptor");
1414 return NULL;
1415 }
1416 return reinterpret_cast<const FileDescriptor*>(
1417 reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
1418}
1419
Jisi Liuada65562015-02-25 16:39:11 -08001420namespace oneof_descriptor {
1421
1422// Unchecked accessor to the C++ pointer.
1423static const OneofDescriptor* _GetDescriptor(
1424 PyBaseDescriptor *self) {
1425 return reinterpret_cast<const OneofDescriptor*>(self->descriptor);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001426}
1427
Jisi Liuada65562015-02-25 16:39:11 -08001428static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
1429 return PyString_FromCppString(_GetDescriptor(self)->name());
Feng Xiao6ef984a2014-11-10 17:34:54 -08001430}
1431
Jisi Liuada65562015-02-25 16:39:11 -08001432static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
1433 return PyString_FromCppString(_GetDescriptor(self)->full_name());
jieluo@google.combde4a322014-08-12 21:10:30 +00001434}
1435
Jisi Liuada65562015-02-25 16:39:11 -08001436static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
1437 return PyInt_FromLong(_GetDescriptor(self)->index());
Feng Xiao6ef984a2014-11-10 17:34:54 -08001438}
1439
Jisi Liuada65562015-02-25 16:39:11 -08001440static PyObject* GetFields(PyBaseDescriptor* self, void *closure) {
1441 return NewOneofFieldsSeq(_GetDescriptor(self));
1442}
1443
1444static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
1445 const Descriptor* containing_type =
1446 _GetDescriptor(self)->containing_type();
1447 if (containing_type) {
Bo Yang5db21732015-05-21 14:28:59 -07001448 return PyMessageDescriptor_FromDescriptor(containing_type);
Feng Xiao6ef984a2014-11-10 17:34:54 -08001449 } else {
Jisi Liuada65562015-02-25 16:39:11 -08001450 Py_RETURN_NONE;
Feng Xiao6ef984a2014-11-10 17:34:54 -08001451 }
1452}
1453
Jisi Liuada65562015-02-25 16:39:11 -08001454static PyGetSetDef Getters[] = {
Bo Yang5db21732015-05-21 14:28:59 -07001455 { "name", (getter)GetName, NULL, "Name"},
1456 { "full_name", (getter)GetFullName, NULL, "Full name"},
1457 { "index", (getter)GetIndex, NULL, "Index"},
jieluo@google.combde4a322014-08-12 21:10:30 +00001458
Bo Yang5db21732015-05-21 14:28:59 -07001459 { "containing_type", (getter)GetContainingType, NULL, "Containing type"},
1460 { "fields", (getter)GetFields, NULL, "Fields"},
jieluo@google.combde4a322014-08-12 21:10:30 +00001461 {NULL}
1462};
1463
Jisi Liuada65562015-02-25 16:39:11 -08001464} // namespace oneof_descriptor
jieluo@google.combde4a322014-08-12 21:10:30 +00001465
Jisi Liuada65562015-02-25 16:39:11 -08001466PyTypeObject PyOneofDescriptor_Type = {
jieluo@google.combde4a322014-08-12 21:10:30 +00001467 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Bo Yang5db21732015-05-21 14:28:59 -07001468 FULL_MODULE_NAME ".OneofDescriptor", // tp_name
Jisi Liuada65562015-02-25 16:39:11 -08001469 sizeof(PyBaseDescriptor), // tp_basicsize
1470 0, // tp_itemsize
1471 0, // tp_dealloc
1472 0, // tp_print
1473 0, // tp_getattr
1474 0, // tp_setattr
1475 0, // tp_compare
1476 0, // tp_repr
1477 0, // tp_as_number
1478 0, // tp_as_sequence
1479 0, // tp_as_mapping
1480 0, // tp_hash
1481 0, // tp_call
1482 0, // tp_str
1483 0, // tp_getattro
1484 0, // tp_setattro
1485 0, // tp_as_buffer
1486 Py_TPFLAGS_DEFAULT, // tp_flags
Bo Yang5db21732015-05-21 14:28:59 -07001487 "A Oneof Descriptor", // tp_doc
Jisi Liuada65562015-02-25 16:39:11 -08001488 0, // tp_traverse
1489 0, // tp_clear
1490 0, // tp_richcompare
1491 0, // tp_weaklistoffset
1492 0, // tp_iter
1493 0, // tp_iternext
1494 0, // tp_methods
1495 0, // tp_members
1496 oneof_descriptor::Getters, // tp_getset
1497 &descriptor::PyBaseDescriptor_Type, // tp_base
jieluo@google.combde4a322014-08-12 21:10:30 +00001498};
1499
Bo Yang5db21732015-05-21 14:28:59 -07001500PyObject* PyOneofDescriptor_FromDescriptor(
Jisi Liuada65562015-02-25 16:39:11 -08001501 const OneofDescriptor* oneof_descriptor) {
1502 return descriptor::NewInternedDescriptor(
Bo Yang5db21732015-05-21 14:28:59 -07001503 &PyOneofDescriptor_Type, oneof_descriptor, NULL);
jieluo@google.combde4a322014-08-12 21:10:30 +00001504}
1505
Jisi Liuada65562015-02-25 16:39:11 -08001506// Add a enum values to a type dictionary.
1507static bool AddEnumValues(PyTypeObject *type,
1508 const EnumDescriptor* enum_descriptor) {
1509 for (int i = 0; i < enum_descriptor->value_count(); ++i) {
1510 const EnumValueDescriptor* value = enum_descriptor->value(i);
1511 ScopedPyObjectPtr obj(PyInt_FromLong(value->number()));
1512 if (obj == NULL) {
1513 return false;
1514 }
Josh Haberman00700b72015-10-06 14:13:09 -07001515 if (PyDict_SetItemString(type->tp_dict, value->name().c_str(), obj.get()) <
1516 0) {
Jisi Liuada65562015-02-25 16:39:11 -08001517 return false;
1518 }
1519 }
1520 return true;
1521}
1522
1523static bool AddIntConstant(PyTypeObject *type, const char* name, int value) {
1524 ScopedPyObjectPtr obj(PyInt_FromLong(value));
Josh Haberman00700b72015-10-06 14:13:09 -07001525 if (PyDict_SetItemString(type->tp_dict, name, obj.get()) < 0) {
Feng Xiao6ef984a2014-11-10 17:34:54 -08001526 return false;
Jisi Liuada65562015-02-25 16:39:11 -08001527 }
1528 return true;
1529}
1530
1531
1532bool InitDescriptor() {
1533 if (PyType_Ready(&PyMessageDescriptor_Type) < 0)
jieluo@google.combde4a322014-08-12 21:10:30 +00001534 return false;
1535
Jisi Liuada65562015-02-25 16:39:11 -08001536 if (PyType_Ready(&PyFieldDescriptor_Type) < 0)
1537 return false;
1538
1539 if (!AddEnumValues(&PyFieldDescriptor_Type,
1540 FieldDescriptorProto::Label_descriptor())) {
1541 return false;
1542 }
1543 if (!AddEnumValues(&PyFieldDescriptor_Type,
1544 FieldDescriptorProto::Type_descriptor())) {
1545 return false;
1546 }
1547#define ADD_FIELDDESC_CONSTANT(NAME) AddIntConstant( \
1548 &PyFieldDescriptor_Type, #NAME, FieldDescriptor::NAME)
1549 if (!ADD_FIELDDESC_CONSTANT(CPPTYPE_INT32) ||
1550 !ADD_FIELDDESC_CONSTANT(CPPTYPE_INT64) ||
1551 !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT32) ||
1552 !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT64) ||
1553 !ADD_FIELDDESC_CONSTANT(CPPTYPE_DOUBLE) ||
1554 !ADD_FIELDDESC_CONSTANT(CPPTYPE_FLOAT) ||
1555 !ADD_FIELDDESC_CONSTANT(CPPTYPE_BOOL) ||
1556 !ADD_FIELDDESC_CONSTANT(CPPTYPE_ENUM) ||
1557 !ADD_FIELDDESC_CONSTANT(CPPTYPE_STRING) ||
1558 !ADD_FIELDDESC_CONSTANT(CPPTYPE_MESSAGE)) {
1559 return false;
1560 }
1561#undef ADD_FIELDDESC_CONSTANT
1562
1563 if (PyType_Ready(&PyEnumDescriptor_Type) < 0)
1564 return false;
1565
1566 if (PyType_Ready(&PyEnumValueDescriptor_Type) < 0)
1567 return false;
1568
1569 if (PyType_Ready(&PyFileDescriptor_Type) < 0)
1570 return false;
1571
1572 if (PyType_Ready(&PyOneofDescriptor_Type) < 0)
1573 return false;
1574
1575 if (!InitDescriptorMappingTypes())
jieluo@google.combde4a322014-08-12 21:10:30 +00001576 return false;
1577
1578 return true;
1579}
1580
1581} // namespace python
1582} // namespace protobuf
1583} // namespace google