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