| // Protocol Buffers - Google's data interchange format |
| // Copyright 2008 Google Inc. All rights reserved. |
| // |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file or at |
| // https://developers.google.com/open-source/licenses/bsd |
| |
| // Author: petar@google.com (Petar Petrov) |
| |
| #include "google/protobuf/pyext/descriptor.h" |
| |
| #define PY_SSIZE_T_CLEAN |
| #include <Python.h> |
| #include <frameobject.h> |
| |
| #include <cstdint> |
| #include <string> |
| #include <unordered_map> |
| |
| #include "google/protobuf/descriptor.pb.h" |
| #include "absl/container/flat_hash_map.h" |
| #include "absl/log/absl_check.h" |
| #include "absl/strings/string_view.h" |
| #include "google/protobuf/descriptor.h" |
| #include "google/protobuf/dynamic_message.h" |
| #include "google/protobuf/io/coded_stream.h" |
| #include "google/protobuf/pyext/descriptor_containers.h" |
| #include "google/protobuf/pyext/descriptor_pool.h" |
| #include "google/protobuf/pyext/message.h" |
| #include "google/protobuf/pyext/message_factory.h" |
| #include "google/protobuf/pyext/scoped_pyobject_ptr.h" |
| |
| #define PyString_AsStringAndSize(ob, charpp, sizep) \ |
| (PyUnicode_Check(ob) \ |
| ? ((*(charpp) = const_cast<char*>( \ |
| PyUnicode_AsUTF8AndSize(ob, (sizep)))) == nullptr \ |
| ? -1 \ |
| : 0) \ |
| : PyBytes_AsStringAndSize(ob, (charpp), (sizep))) |
| |
| #if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) |
| static PyCodeObject* PyFrame_GetCode(PyFrameObject *frame) |
| { |
| Py_INCREF(frame->f_code); |
| return frame->f_code; |
| } |
| |
| static PyFrameObject* PyFrame_GetBack(PyFrameObject *frame) |
| { |
| Py_XINCREF(frame->f_back); |
| return frame->f_back; |
| } |
| #endif |
| |
| #if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION) |
| static PyObject* PyFrame_GetLocals(PyFrameObject *frame) |
| { |
| if (PyFrame_FastToLocalsWithError(frame) < 0) { |
| return NULL; |
| } |
| Py_INCREF(frame->f_locals); |
| return frame->f_locals; |
| } |
| |
| static PyObject* PyFrame_GetGlobals(PyFrameObject *frame) |
| { |
| Py_INCREF(frame->f_globals); |
| return frame->f_globals; |
| } |
| #endif |
| |
| namespace google { |
| namespace protobuf { |
| namespace python { |
| |
| // Store interned descriptors, so that the same C++ descriptor yields the same |
| // Python object. Objects are not immortal: this map does not own the |
| // references, and items are deleted when the last reference to the object is |
| // released. |
| // This is enough to support the "is" operator on live objects. |
| // All descriptors are stored here. |
| std::unordered_map<const void*, PyObject*>* interned_descriptors; |
| |
| PyObject* PyString_FromCppString(const std::string& str) { |
| return PyUnicode_FromStringAndSize(str.c_str(), str.size()); |
| } |
| |
| // Check that the calling Python code is the global scope of a _pb2.py module. |
| // This function is used to support the current code generated by the proto |
| // compiler, which creates descriptors, then update some properties. |
| // For example: |
| // message_descriptor = Descriptor( |
| // name='Message', |
| // fields = [FieldDescriptor(name='field')] |
| // message_descriptor.fields[0].containing_type = message_descriptor |
| // |
| // This code is still executed, but the descriptors now have no other storage |
| // than the (const) C++ pointer, and are immutable. |
| // So we let this code pass, by simply ignoring the new value. |
| // |
| // From user code, descriptors still look immutable. |
| // |
| // TODO: Change the proto2 compiler to remove the assignments, and |
| // remove this hack. |
| bool _CalledFromGeneratedFile(int stacklevel) { |
| #ifdef PYPY_VERSION |
| return true; |
| #else |
| // This check is not critical and is somewhat difficult to implement correctly |
| // in PyPy. |
| PyFrameObject* frame = PyEval_GetFrame(); |
| PyCodeObject* frame_code = nullptr; |
| PyObject* frame_globals = nullptr; |
| PyObject* frame_locals = nullptr; |
| bool result = false; |
| |
| if (frame == nullptr) { |
| goto exit; |
| } |
| Py_INCREF(frame); |
| while (stacklevel-- > 0) { |
| PyFrameObject* next_frame = PyFrame_GetBack(frame); |
| Py_DECREF(frame); |
| frame = next_frame; |
| if (frame == nullptr) { |
| goto exit; |
| } |
| } |
| |
| frame_code = PyFrame_GetCode(frame); |
| if (frame_code->co_filename == nullptr) { |
| goto exit; |
| } |
| char* filename; |
| Py_ssize_t filename_size; |
| if (PyString_AsStringAndSize(frame_code->co_filename, |
| &filename, &filename_size) < 0) { |
| // filename is not a string. |
| PyErr_Clear(); |
| goto exit; |
| } |
| if ((filename_size < 3) || |
| (strcmp(&filename[filename_size - 3], ".py") != 0)) { |
| // Cython's stack does not have .py file name and is not at global module |
| // scope. |
| result = true; |
| goto exit; |
| } |
| if (filename_size < 7) { |
| // filename is too short. |
| goto exit; |
| } |
| if (strcmp(&filename[filename_size - 7], "_pb2.py") != 0) { |
| // Filename is not ending with _pb2. |
| goto exit; |
| } |
| |
| frame_globals = PyFrame_GetGlobals(frame); |
| frame_locals = PyFrame_GetLocals(frame); |
| if (frame_globals != frame_locals) { |
| // Not at global module scope |
| goto exit; |
| } |
| result = true; |
| exit: |
| Py_XDECREF(frame_globals); |
| Py_XDECREF(frame_locals); |
| Py_XDECREF(frame_code); |
| Py_XDECREF(frame); |
| return result; |
| #endif |
| } |
| |
| // If the calling code is not a _pb2.py file, raise AttributeError. |
| // To be used in attribute setters. |
| static int CheckCalledFromGeneratedFile(const char* attr_name) { |
| if (_CalledFromGeneratedFile(0)) { |
| return 0; |
| } |
| PyErr_Format(PyExc_AttributeError, |
| "attribute is not writable: %s", attr_name); |
| return -1; |
| } |
| |
| |
| #ifndef PyVarObject_HEAD_INIT |
| #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, |
| #endif |
| #ifndef Py_TYPE |
| #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) |
| #endif |
| |
| |
| // Helper functions for descriptor objects. |
| |
| // A set of templates to retrieve the C++ FileDescriptor of any descriptor. |
| template<class DescriptorClass> |
| const FileDescriptor* GetFileDescriptor(const DescriptorClass* descriptor) { |
| return descriptor->file(); |
| } |
| template<> |
| const FileDescriptor* GetFileDescriptor(const FileDescriptor* descriptor) { |
| return descriptor; |
| } |
| template<> |
| const FileDescriptor* GetFileDescriptor(const EnumValueDescriptor* descriptor) { |
| return descriptor->type()->file(); |
| } |
| template<> |
| const FileDescriptor* GetFileDescriptor(const OneofDescriptor* descriptor) { |
| return descriptor->containing_type()->file(); |
| } |
| template<> |
| const FileDescriptor* GetFileDescriptor(const MethodDescriptor* descriptor) { |
| return descriptor->service()->file(); |
| } |
| |
| bool Reparse( |
| PyMessageFactory* message_factory, const Message& from, Message* to) { |
| // Reparse message. |
| std::string serialized; |
| from.SerializeToString(&serialized); |
| io::CodedInputStream input( |
| reinterpret_cast<const uint8_t*>(serialized.c_str()), serialized.size()); |
| input.SetExtensionRegistry(message_factory->pool->pool, |
| message_factory->message_factory); |
| bool success = to->ParseFromCodedStream(&input); |
| if (!success) { |
| return false; |
| } |
| return true; |
| } |
| |
| // Converts descriptor messages into a Python protobuf, and cache the result. |
| // |
| // This is a bit tricky because options can contain extension fields defined in |
| // the same proto file. In this case the options parsed from the serialized_pb |
| // have unknown fields, and we need to parse them again. |
| // |
| // Always returns a new reference. |
| static PyObject* GetOrBuildMessageInDefaultPool( |
| absl::flat_hash_map<const void*, PyObject*>& cache, const void* key, |
| const Message& message) { |
| // First search in the cache. |
| if (cache.find(key) != cache.end()) { |
| PyObject* value = cache[key]; |
| Py_INCREF(value); |
| return value; |
| } |
| |
| // Similar to the C++ implementation, we return a message object from the |
| // default (generated) factory, so that client code know that they can use |
| // extensions from generated files: |
| // d.GetOptions().Extensions[some_pb2.extension] |
| // |
| // The consequence is that extensions not defined in the default pool won't |
| // be available. If needed, we could add an optional 'message_factory' |
| // parameter to the GetOptions() function. |
| PyMessageFactory* message_factory = |
| GetDefaultDescriptorPool()->py_message_factory; |
| |
| // Build the message object: get its Python class, and make a copy of the C++ |
| // read-only instance. |
| const Descriptor* message_type = message.GetDescriptor(); |
| CMessageClass* message_class = |
| message_factory::GetOrCreateMessageClass(message_factory, message_type); |
| if (message_class == nullptr) { |
| PyErr_Format(PyExc_TypeError, "Could not retrieve class for: %s", |
| message_type->full_name().c_str()); |
| return nullptr; |
| } |
| ScopedPyObjectPtr args(PyTuple_New(0)); |
| ScopedPyObjectPtr value( |
| PyObject_Call(message_class->AsPyObject(), args.get(), nullptr)); |
| Py_DECREF(message_class); |
| if (value == nullptr) { |
| return nullptr; |
| } |
| if (!PyObject_TypeCheck(value.get(), CMessage_Type)) { |
| PyErr_Format(PyExc_TypeError, "Invalid class for %s: %s", |
| message_type->full_name().c_str(), |
| Py_TYPE(value.get())->tp_name); |
| return nullptr; |
| } |
| CMessage* cmsg = reinterpret_cast<CMessage*>(value.get()); |
| |
| const Reflection* reflection = message.GetReflection(); |
| const UnknownFieldSet& unknown_fields(reflection->GetUnknownFields(message)); |
| if (unknown_fields.empty()) { |
| cmsg->message->CopyFrom(message); |
| } else { |
| // Reparse options string! XXX call cmessage::MergeFromString |
| if (!Reparse(message_factory, message, cmsg->message)) { |
| PyErr_Format(PyExc_ValueError, "Error reparsing Options message"); |
| return nullptr; |
| } |
| } |
| |
| // Cache the result. |
| Py_INCREF(value.get()); |
| cache[key] = value.get(); |
| |
| return value.release(); |
| } |
| |
| template <class DescriptorClass> |
| static PyObject* GetOrBuildOptions(const DescriptorClass* descriptor) { |
| // Options are cached in the pool that owns the descriptor. |
| PyDescriptorPool* caching_pool = |
| GetDescriptorPool_FromPool(GetFileDescriptor(descriptor)->pool()); |
| return GetOrBuildMessageInDefaultPool(*caching_pool->descriptor_options, |
| descriptor, descriptor->options()); |
| } |
| |
| template <class DescriptorClass> |
| static PyObject* GetFeaturesImpl(const DescriptorClass* descriptor) { |
| if (descriptor == nullptr) { |
| return nullptr; |
| } |
| const FeatureSet& features = |
| internal::InternalFeatureHelper::GetFeatures(*descriptor); |
| |
| // Features are cached in the pool that owns the descriptor. |
| PyDescriptorPool* caching_pool = |
| GetDescriptorPool_FromPool(GetFileDescriptor(descriptor)->pool()); |
| return GetOrBuildMessageInDefaultPool(*caching_pool->descriptor_features, |
| descriptor, features); |
| } |
| |
| // Copy the C++ descriptor to a Python message. |
| // The Python message is an instance of descriptor_pb2.DescriptorProto |
| // or similar. |
| template<class DescriptorProtoClass, class DescriptorClass> |
| static PyObject* CopyToPythonProto(const DescriptorClass *descriptor, |
| PyObject *target) { |
| const Descriptor* self_descriptor = |
| DescriptorProtoClass::default_instance().GetDescriptor(); |
| CMessage* message = reinterpret_cast<CMessage*>(target); |
| if (!PyObject_TypeCheck(target, CMessage_Type) || |
| message->message->GetDescriptor() != self_descriptor) { |
| PyErr_Format(PyExc_TypeError, "Not a %s message", |
| self_descriptor->full_name().c_str()); |
| return nullptr; |
| } |
| cmessage::AssureWritable(message); |
| DescriptorProtoClass* descriptor_message = |
| static_cast<DescriptorProtoClass*>(message->message); |
| descriptor->CopyTo(descriptor_message); |
| // Custom options might in unknown extensions. Reparse |
| // the descriptor_message. Can't skip reparse when options unknown |
| // fields is empty, because they might in sub descriptors' options. |
| PyMessageFactory* message_factory = |
| GetDefaultDescriptorPool()->py_message_factory; |
| if (!Reparse(message_factory, *descriptor_message, descriptor_message)) { |
| PyErr_Format(PyExc_ValueError, "Error reparsing descriptor message"); |
| return nullptr; |
| } |
| |
| Py_RETURN_NONE; |
| } |
| |
| // All Descriptors classes share the same memory layout. |
| typedef struct PyBaseDescriptor { |
| PyObject_HEAD |
| |
| // Pointer to the C++ proto2 descriptor. |
| // Like all descriptors, it is owned by the global DescriptorPool. |
| const void* descriptor; |
| |
| // Owned reference to the DescriptorPool, to ensure it is kept alive. |
| PyDescriptorPool* pool; |
| } PyBaseDescriptor; |
| |
| |
| // FileDescriptor structure "inherits" from the base descriptor. |
| typedef struct PyFileDescriptor { |
| PyBaseDescriptor base; |
| |
| // The cached version of serialized pb. Either null, or a Bytes string. |
| // We own the reference. |
| PyObject *serialized_pb; |
| } PyFileDescriptor; |
| |
| |
| namespace descriptor { |
| |
| // Creates or retrieve a Python descriptor of the specified type. |
| // Objects are interned: the same descriptor will return the same object if it |
| // was kept alive. |
| // 'was_created' is an optional pointer to a bool, and is set to true if a new |
| // object was allocated. |
| // Always return a new reference. |
| template<class DescriptorClass> |
| PyObject* NewInternedDescriptor(PyTypeObject* type, |
| const DescriptorClass* descriptor, |
| bool* was_created) { |
| if (was_created) { |
| *was_created = false; |
| } |
| if (descriptor == nullptr) { |
| PyErr_BadInternalCall(); |
| return nullptr; |
| } |
| |
| // See if the object is in the map of interned descriptors |
| std::unordered_map<const void*, PyObject*>::iterator it = |
| interned_descriptors->find(descriptor); |
| if (it != interned_descriptors->end()) { |
| ABSL_DCHECK(Py_TYPE(it->second) == type); |
| Py_INCREF(it->second); |
| return it->second; |
| } |
| // Create a new descriptor object |
| PyBaseDescriptor* py_descriptor = PyObject_GC_New( |
| PyBaseDescriptor, type); |
| if (py_descriptor == nullptr) { |
| return nullptr; |
| } |
| py_descriptor->descriptor = descriptor; |
| |
| // and cache it. |
| interned_descriptors->insert( |
| std::make_pair(descriptor, reinterpret_cast<PyObject*>(py_descriptor))); |
| |
| // Ensures that the DescriptorPool stays alive. |
| PyDescriptorPool* pool = GetDescriptorPool_FromPool( |
| GetFileDescriptor(descriptor)->pool()); |
| if (pool == nullptr) { |
| // Don't DECREF, the object is not fully initialized. |
| PyObject_Del(py_descriptor); |
| return nullptr; |
| } |
| Py_INCREF(pool); |
| py_descriptor->pool = pool; |
| |
| PyObject_GC_Track(py_descriptor); |
| |
| if (was_created) { |
| *was_created = true; |
| } |
| return reinterpret_cast<PyObject*>(py_descriptor); |
| } |
| |
| static void Dealloc(PyObject* pself) { |
| PyBaseDescriptor* self = reinterpret_cast<PyBaseDescriptor*>(pself); |
| // Remove from interned dictionary |
| interned_descriptors->erase(self->descriptor); |
| Py_CLEAR(self->pool); |
| Py_TYPE(self)->tp_free(pself); |
| } |
| |
| static int GcTraverse(PyObject* pself, visitproc visit, void* arg) { |
| PyBaseDescriptor* self = reinterpret_cast<PyBaseDescriptor*>(pself); |
| Py_VISIT(self->pool); |
| return 0; |
| } |
| |
| static int GcClear(PyObject* pself) { |
| PyBaseDescriptor* self = reinterpret_cast<PyBaseDescriptor*>(pself); |
| Py_CLEAR(self->pool); |
| return 0; |
| } |
| |
| static PyGetSetDef Getters[] = { |
| {nullptr}, |
| }; |
| |
| PyTypeObject PyBaseDescriptor_Type = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME |
| ".DescriptorBase", // tp_name |
| sizeof(PyBaseDescriptor), // tp_basicsize |
| 0, // tp_itemsize |
| (destructor)Dealloc, // tp_dealloc |
| #if PY_VERSION_HEX < 0x03080000 |
| nullptr, // tp_print |
| #else |
| 0, // tp_vectorcall_offset |
| #endif |
| nullptr, // tp_getattr |
| nullptr, // tp_setattr |
| nullptr, // tp_compare |
| nullptr, // tp_repr |
| nullptr, // tp_as_number |
| nullptr, // tp_as_sequence |
| nullptr, // tp_as_mapping |
| nullptr, // tp_hash |
| nullptr, // tp_call |
| nullptr, // tp_str |
| nullptr, // tp_getattro |
| nullptr, // tp_setattro |
| nullptr, // tp_as_buffer |
| Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags |
| "Descriptors base class", // tp_doc |
| GcTraverse, // tp_traverse |
| GcClear, // tp_clear |
| nullptr, // tp_richcompare |
| 0, // tp_weaklistoffset |
| nullptr, // tp_iter |
| nullptr, // tp_iternext |
| nullptr, // tp_methods |
| nullptr, // tp_members |
| Getters, // tp_getset |
| }; |
| |
| } // namespace descriptor |
| |
| const void* PyDescriptor_AsVoidPtr(PyObject* obj) { |
| if (!PyObject_TypeCheck(obj, &descriptor::PyBaseDescriptor_Type)) { |
| PyErr_SetString(PyExc_TypeError, "Not a BaseDescriptor"); |
| return nullptr; |
| } |
| return reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor; |
| } |
| |
| namespace message_descriptor { |
| |
| // Unchecked accessor to the C++ pointer. |
| static const Descriptor* _GetDescriptor(PyBaseDescriptor* self) { |
| return reinterpret_cast<const Descriptor*>(self->descriptor); |
| } |
| |
| static PyObject* GetName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->name()); |
| } |
| |
| static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->full_name()); |
| } |
| |
| static PyObject* GetFile(PyBaseDescriptor *self, void *closure) { |
| return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file()); |
| } |
| |
| static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) { |
| // Returns the canonical class for the given descriptor. |
| // This is the class that was registered with the primary descriptor pool |
| // which contains this descriptor. |
| // This might not be the one you expect! For example the returned object does |
| // not know about extensions defined in a custom pool. |
| CMessageClass* concrete_class(message_factory::GetMessageClass( |
| GetDescriptorPool_FromPool( |
| _GetDescriptor(self)->file()->pool())->py_message_factory, |
| _GetDescriptor(self))); |
| |
| if (concrete_class == nullptr) { |
| PyErr_Clear(); |
| return nullptr; |
| } |
| |
| Py_XINCREF(concrete_class); |
| return concrete_class->AsPyObject(); |
| } |
| |
| static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) { |
| return NewMessageFieldsByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFieldsByCamelcaseName(PyBaseDescriptor* self, |
| void *closure) { |
| return NewMessageFieldsByCamelcaseName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFieldsByNumber(PyBaseDescriptor* self, void *closure) { |
| return NewMessageFieldsByNumber(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFieldsSeq(PyBaseDescriptor* self, void *closure) { |
| return NewMessageFieldsSeq(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetNestedTypesByName(PyBaseDescriptor* self, void *closure) { |
| return NewMessageNestedTypesByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetNestedTypesSeq(PyBaseDescriptor* self, void *closure) { |
| return NewMessageNestedTypesSeq(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetExtensionsByName(PyBaseDescriptor* self, void *closure) { |
| return NewMessageExtensionsByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetExtensions(PyBaseDescriptor* self, void *closure) { |
| return NewMessageExtensionsSeq(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetEnumsSeq(PyBaseDescriptor* self, void *closure) { |
| return NewMessageEnumsSeq(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetEnumTypesByName(PyBaseDescriptor* self, void *closure) { |
| return NewMessageEnumsByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetEnumValuesByName(PyBaseDescriptor* self, void *closure) { |
| return NewMessageEnumValuesByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetOneofsByName(PyBaseDescriptor* self, void *closure) { |
| return NewMessageOneofsByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetOneofsSeq(PyBaseDescriptor* self, void *closure) { |
| return NewMessageOneofsSeq(_GetDescriptor(self)); |
| } |
| |
| static PyObject* IsExtendable(PyBaseDescriptor *self, void *closure) { |
| if (_GetDescriptor(self)->extension_range_count() > 0) { |
| Py_RETURN_TRUE; |
| } else { |
| Py_RETURN_FALSE; |
| } |
| } |
| |
| static PyObject* GetExtensionRanges(PyBaseDescriptor *self, void *closure) { |
| const Descriptor* descriptor = _GetDescriptor(self); |
| PyObject* range_list = PyList_New(descriptor->extension_range_count()); |
| |
| for (int i = 0; i < descriptor->extension_range_count(); i++) { |
| const Descriptor::ExtensionRange* range = descriptor->extension_range(i); |
| PyObject* start = PyLong_FromLong(range->start_number()); |
| PyObject* end = PyLong_FromLong(range->end_number()); |
| PyList_SetItem(range_list, i, PyTuple_Pack(2, start, end)); |
| } |
| |
| return range_list; |
| } |
| |
| static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { |
| const Descriptor* containing_type = |
| _GetDescriptor(self)->containing_type(); |
| if (containing_type) { |
| return PyMessageDescriptor_FromDescriptor(containing_type); |
| } else { |
| Py_RETURN_NONE; |
| } |
| } |
| |
| static int SetContainingType(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("containing_type"); |
| } |
| |
| static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { |
| const MessageOptions& options(_GetDescriptor(self)->options()); |
| if (&options != &MessageOptions::default_instance()) { |
| Py_RETURN_TRUE; |
| } else { |
| Py_RETURN_FALSE; |
| } |
| } |
| static int SetHasOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("has_options"); |
| } |
| |
| static PyObject* GetOptions(PyBaseDescriptor *self) { |
| return GetOrBuildOptions(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFeatures(PyBaseDescriptor* self) { |
| return GetFeaturesImpl(_GetDescriptor(self)); |
| } |
| |
| static int SetOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_options"); |
| } |
| |
| static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_serialized_options"); |
| } |
| |
| static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { |
| return CopyToPythonProto<DescriptorProto>(_GetDescriptor(self), target); |
| } |
| |
| static PyObject* EnumValueName(PyBaseDescriptor *self, PyObject *args) { |
| const char *enum_name; |
| int number; |
| if (!PyArg_ParseTuple(args, "si", &enum_name, &number)) return nullptr; |
| const EnumDescriptor *enum_type = |
| _GetDescriptor(self)->FindEnumTypeByName(enum_name); |
| if (enum_type == nullptr) { |
| PyErr_SetString(PyExc_KeyError, enum_name); |
| return nullptr; |
| } |
| const EnumValueDescriptor *enum_value = |
| enum_type->FindValueByNumber(number); |
| if (enum_value == nullptr) { |
| PyErr_Format(PyExc_KeyError, "%d", number); |
| return nullptr; |
| } |
| return PyString_FromCppString(enum_value->name()); |
| } |
| |
| static PyGetSetDef Getters[] = { |
| {"name", (getter)GetName, nullptr, "Last name"}, |
| {"full_name", (getter)GetFullName, nullptr, "Full name"}, |
| {"_concrete_class", (getter)GetConcreteClass, nullptr, "concrete class"}, |
| {"file", (getter)GetFile, nullptr, "File descriptor"}, |
| |
| {"fields", (getter)GetFieldsSeq, nullptr, "Fields sequence"}, |
| {"fields_by_name", (getter)GetFieldsByName, nullptr, "Fields by name"}, |
| {"fields_by_camelcase_name", (getter)GetFieldsByCamelcaseName, nullptr, |
| "Fields by camelCase name"}, |
| {"fields_by_number", (getter)GetFieldsByNumber, nullptr, |
| "Fields by number"}, |
| {"nested_types", (getter)GetNestedTypesSeq, nullptr, |
| "Nested types sequence"}, |
| {"nested_types_by_name", (getter)GetNestedTypesByName, nullptr, |
| "Nested types by name"}, |
| {"extensions", (getter)GetExtensions, nullptr, "Extensions Sequence"}, |
| {"extensions_by_name", (getter)GetExtensionsByName, nullptr, |
| "Extensions by name"}, |
| {"extension_ranges", (getter)GetExtensionRanges, nullptr, |
| "Extension ranges"}, |
| {"enum_types", (getter)GetEnumsSeq, nullptr, "Enum sequence"}, |
| {"enum_types_by_name", (getter)GetEnumTypesByName, nullptr, |
| "Enum types by name"}, |
| {"enum_values_by_name", (getter)GetEnumValuesByName, nullptr, |
| "Enum values by name"}, |
| {"oneofs_by_name", (getter)GetOneofsByName, nullptr, "Oneofs by name"}, |
| {"oneofs", (getter)GetOneofsSeq, nullptr, "Oneofs by name"}, |
| {"containing_type", (getter)GetContainingType, (setter)SetContainingType, |
| "Containing type"}, |
| {"is_extendable", (getter)IsExtendable, (setter) nullptr}, |
| {"has_options", (getter)GetHasOptions, (setter)SetHasOptions, |
| "Has Options"}, |
| {"_options", (getter) nullptr, (setter)SetOptions, "Options"}, |
| {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions, |
| "Serialized Options"}, |
| {nullptr}, |
| }; |
| |
| static PyMethodDef Methods[] = { |
| {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS}, |
| {"_GetFeatures", (PyCFunction)GetFeatures, METH_NOARGS}, |
| {"CopyToProto", (PyCFunction)CopyToProto, METH_O}, |
| {"EnumValueName", (PyCFunction)EnumValueName, METH_VARARGS}, |
| {nullptr}, |
| }; |
| |
| } // namespace message_descriptor |
| |
| PyTypeObject PyMessageDescriptor_Type = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME |
| ".MessageDescriptor", // tp_name |
| sizeof(PyBaseDescriptor), // tp_basicsize |
| 0, // tp_itemsize |
| nullptr, // tp_dealloc |
| #if PY_VERSION_HEX < 0x03080000 |
| nullptr, // tp_print |
| #else |
| 0, // tp_vectorcall_offset |
| #endif |
| nullptr, // tp_getattr |
| nullptr, // tp_setattr |
| nullptr, // tp_compare |
| nullptr, // tp_repr |
| nullptr, // tp_as_number |
| nullptr, // tp_as_sequence |
| nullptr, // tp_as_mapping |
| nullptr, // tp_hash |
| nullptr, // tp_call |
| nullptr, // tp_str |
| nullptr, // tp_getattro |
| nullptr, // tp_setattro |
| nullptr, // tp_as_buffer |
| Py_TPFLAGS_DEFAULT, // tp_flags |
| "A Message Descriptor", // tp_doc |
| nullptr, // tp_traverse |
| nullptr, // tp_clear |
| nullptr, // tp_richcompare |
| 0, // tp_weaklistoffset |
| nullptr, // tp_iter |
| nullptr, // tp_iternext |
| message_descriptor::Methods, // tp_methods |
| nullptr, // tp_members |
| message_descriptor::Getters, // tp_getset |
| &descriptor::PyBaseDescriptor_Type, // tp_base |
| }; |
| |
| PyObject* PyMessageDescriptor_FromDescriptor( |
| const Descriptor* message_descriptor) { |
| return descriptor::NewInternedDescriptor(&PyMessageDescriptor_Type, |
| message_descriptor, nullptr); |
| } |
| |
| const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj) { |
| if (!PyObject_TypeCheck(obj, &PyMessageDescriptor_Type)) { |
| PyErr_SetString(PyExc_TypeError, "Not a MessageDescriptor"); |
| return nullptr; |
| } |
| return reinterpret_cast<const Descriptor*>( |
| reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor); |
| } |
| |
| namespace field_descriptor { |
| |
| // Unchecked accessor to the C++ pointer. |
| static const FieldDescriptor* _GetDescriptor( |
| PyBaseDescriptor *self) { |
| return reinterpret_cast<const FieldDescriptor*>(self->descriptor); |
| } |
| |
| static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->full_name()); |
| } |
| |
| static PyObject* GetName(PyBaseDescriptor *self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->name()); |
| } |
| |
| static PyObject* GetCamelcaseName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->camelcase_name()); |
| } |
| |
| static PyObject* GetJsonName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->json_name()); |
| } |
| |
| static PyObject* GetFile(PyBaseDescriptor *self, void *closure) { |
| return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file()); |
| } |
| |
| static PyObject* GetType(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->type()); |
| } |
| |
| static PyObject* GetCppType(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->cpp_type()); |
| } |
| |
| static PyObject* GetLabel(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->label()); |
| } |
| |
| static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->number()); |
| } |
| |
| static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->index()); |
| } |
| |
| static PyObject* GetID(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromVoidPtr(self); |
| } |
| |
| static PyObject* IsExtension(PyBaseDescriptor *self, void *closure) { |
| return PyBool_FromLong(_GetDescriptor(self)->is_extension()); |
| } |
| |
| static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) { |
| return PyBool_FromLong(_GetDescriptor(self)->has_default_value()); |
| } |
| |
| static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) { |
| PyObject *result; |
| |
| if (_GetDescriptor(self)->is_repeated()) { |
| return PyList_New(0); |
| } |
| |
| |
| switch (_GetDescriptor(self)->cpp_type()) { |
| case FieldDescriptor::CPPTYPE_INT32: { |
| int32_t value = _GetDescriptor(self)->default_value_int32(); |
| result = PyLong_FromLong(value); |
| break; |
| } |
| case FieldDescriptor::CPPTYPE_INT64: { |
| int64_t value = _GetDescriptor(self)->default_value_int64(); |
| result = PyLong_FromLongLong(value); |
| break; |
| } |
| case FieldDescriptor::CPPTYPE_UINT32: { |
| uint32_t value = _GetDescriptor(self)->default_value_uint32(); |
| result = PyLong_FromSsize_t(value); |
| break; |
| } |
| case FieldDescriptor::CPPTYPE_UINT64: { |
| uint64_t value = _GetDescriptor(self)->default_value_uint64(); |
| result = PyLong_FromUnsignedLongLong(value); |
| break; |
| } |
| case FieldDescriptor::CPPTYPE_FLOAT: { |
| float value = _GetDescriptor(self)->default_value_float(); |
| result = PyFloat_FromDouble(value); |
| break; |
| } |
| case FieldDescriptor::CPPTYPE_DOUBLE: { |
| double value = _GetDescriptor(self)->default_value_double(); |
| result = PyFloat_FromDouble(value); |
| break; |
| } |
| case FieldDescriptor::CPPTYPE_BOOL: { |
| bool value = _GetDescriptor(self)->default_value_bool(); |
| result = PyBool_FromLong(value); |
| break; |
| } |
| case FieldDescriptor::CPPTYPE_STRING: { |
| const std::string& value = _GetDescriptor(self)->default_value_string(); |
| result = ToStringObject(_GetDescriptor(self), value); |
| break; |
| } |
| case FieldDescriptor::CPPTYPE_ENUM: { |
| const EnumValueDescriptor* value = |
| _GetDescriptor(self)->default_value_enum(); |
| result = PyLong_FromLong(value->number()); |
| break; |
| } |
| case FieldDescriptor::CPPTYPE_MESSAGE: { |
| Py_RETURN_NONE; |
| break; |
| } |
| default: |
| PyErr_Format(PyExc_NotImplementedError, "default value for %s", |
| _GetDescriptor(self)->full_name().c_str()); |
| return nullptr; |
| } |
| return result; |
| } |
| |
| static PyObject* GetCDescriptor(PyObject *self, void *closure) { |
| Py_INCREF(self); |
| return self; |
| } |
| |
| static PyObject *GetEnumType(PyBaseDescriptor *self, void *closure) { |
| const EnumDescriptor* enum_type = _GetDescriptor(self)->enum_type(); |
| if (enum_type) { |
| return PyEnumDescriptor_FromDescriptor(enum_type); |
| } else { |
| Py_RETURN_NONE; |
| } |
| } |
| |
| static int SetEnumType(PyBaseDescriptor *self, PyObject *value, void *closure) { |
| return CheckCalledFromGeneratedFile("enum_type"); |
| } |
| |
| static PyObject *GetMessageType(PyBaseDescriptor *self, void *closure) { |
| const Descriptor* message_type = _GetDescriptor(self)->message_type(); |
| if (message_type) { |
| return PyMessageDescriptor_FromDescriptor(message_type); |
| } else { |
| Py_RETURN_NONE; |
| } |
| } |
| |
| static int SetMessageType(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("message_type"); |
| } |
| |
| static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { |
| const Descriptor* containing_type = |
| _GetDescriptor(self)->containing_type(); |
| if (containing_type) { |
| return PyMessageDescriptor_FromDescriptor(containing_type); |
| } else { |
| Py_RETURN_NONE; |
| } |
| } |
| |
| static int SetContainingType(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("containing_type"); |
| } |
| |
| static PyObject* GetExtensionScope(PyBaseDescriptor *self, void *closure) { |
| const auto* desc = _GetDescriptor(self); |
| const Descriptor* extension_scope = |
| desc->is_extension() ? desc->extension_scope() : nullptr; |
| if (extension_scope) { |
| return PyMessageDescriptor_FromDescriptor(extension_scope); |
| } else { |
| Py_RETURN_NONE; |
| } |
| } |
| |
| static PyObject* GetContainingOneof(PyBaseDescriptor *self, void *closure) { |
| const OneofDescriptor* containing_oneof = |
| _GetDescriptor(self)->containing_oneof(); |
| if (containing_oneof) { |
| return PyOneofDescriptor_FromDescriptor(containing_oneof); |
| } else { |
| Py_RETURN_NONE; |
| } |
| } |
| |
| static int SetContainingOneof(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("containing_oneof"); |
| } |
| |
| static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { |
| const FieldOptions& options(_GetDescriptor(self)->options()); |
| if (&options != &FieldOptions::default_instance()) { |
| Py_RETURN_TRUE; |
| } else { |
| Py_RETURN_FALSE; |
| } |
| } |
| static int SetHasOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("has_options"); |
| } |
| |
| static PyObject* GetHasPresence(PyBaseDescriptor* self, void* closure) { |
| if (_GetDescriptor(self)->has_presence()) { |
| Py_RETURN_TRUE; |
| } else { |
| Py_RETURN_FALSE; |
| } |
| } |
| |
| static PyObject* GetOptions(PyBaseDescriptor *self) { |
| return GetOrBuildOptions(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFeatures(PyBaseDescriptor* self) { |
| return GetFeaturesImpl(_GetDescriptor(self)); |
| } |
| |
| static int SetOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_options"); |
| } |
| |
| static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_serialized_options"); |
| } |
| |
| static PyGetSetDef Getters[] = { |
| {"full_name", (getter)GetFullName, nullptr, "Full name"}, |
| {"name", (getter)GetName, nullptr, "Unqualified name"}, |
| {"camelcase_name", (getter)GetCamelcaseName, nullptr, "Camelcase name"}, |
| {"json_name", (getter)GetJsonName, nullptr, "Json name"}, |
| {"file", (getter)GetFile, nullptr, "File Descriptor"}, |
| {"type", (getter)GetType, nullptr, "C++ Type"}, |
| {"cpp_type", (getter)GetCppType, nullptr, "C++ Type"}, |
| {"label", (getter)GetLabel, nullptr, "Label"}, |
| {"number", (getter)GetNumber, nullptr, "Number"}, |
| {"index", (getter)GetIndex, nullptr, "Index"}, |
| {"default_value", (getter)GetDefaultValue, nullptr, "Default Value"}, |
| {"has_default_value", (getter)HasDefaultValue}, |
| {"is_extension", (getter)IsExtension, nullptr, "ID"}, |
| {"id", (getter)GetID, nullptr, "ID"}, |
| {"_cdescriptor", (getter)GetCDescriptor, nullptr, "HAACK REMOVE ME"}, |
| |
| {"message_type", (getter)GetMessageType, (setter)SetMessageType, |
| "Message type"}, |
| {"enum_type", (getter)GetEnumType, (setter)SetEnumType, "Enum type"}, |
| {"containing_type", (getter)GetContainingType, (setter)SetContainingType, |
| "Containing type"}, |
| {"extension_scope", (getter)GetExtensionScope, (setter) nullptr, |
| "Extension scope"}, |
| {"containing_oneof", (getter)GetContainingOneof, (setter)SetContainingOneof, |
| "Containing oneof"}, |
| {"has_options", (getter)GetHasOptions, (setter)SetHasOptions, |
| "Has Options"}, |
| {"has_presence", (getter)GetHasPresence, (setter) nullptr, "Has Presence"}, |
| {"_options", (getter) nullptr, (setter)SetOptions, "Options"}, |
| {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions, |
| "Serialized Options"}, |
| {nullptr}, |
| }; |
| |
| static PyMethodDef Methods[] = { |
| {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS}, |
| {"_GetFeatures", (PyCFunction)GetFeatures, METH_NOARGS}, |
| {nullptr}, |
| }; |
| |
| } // namespace field_descriptor |
| |
| PyTypeObject PyFieldDescriptor_Type = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME |
| ".FieldDescriptor", // tp_name |
| sizeof(PyBaseDescriptor), // tp_basicsize |
| 0, // tp_itemsize |
| nullptr, // tp_dealloc |
| #if PY_VERSION_HEX < 0x03080000 |
| nullptr, // tp_print |
| #else |
| 0, // tp_vectorcall_offset |
| #endif |
| nullptr, // tp_getattr |
| nullptr, // tp_setattr |
| nullptr, // tp_compare |
| nullptr, // tp_repr |
| nullptr, // tp_as_number |
| nullptr, // tp_as_sequence |
| nullptr, // tp_as_mapping |
| nullptr, // tp_hash |
| nullptr, // tp_call |
| nullptr, // tp_str |
| nullptr, // tp_getattro |
| nullptr, // tp_setattro |
| nullptr, // tp_as_buffer |
| Py_TPFLAGS_DEFAULT, // tp_flags |
| "A Field Descriptor", // tp_doc |
| nullptr, // tp_traverse |
| nullptr, // tp_clear |
| nullptr, // tp_richcompare |
| 0, // tp_weaklistoffset |
| nullptr, // tp_iter |
| nullptr, // tp_iternext |
| field_descriptor::Methods, // tp_methods |
| nullptr, // tp_members |
| field_descriptor::Getters, // tp_getset |
| &descriptor::PyBaseDescriptor_Type, // tp_base |
| }; |
| |
| PyObject* PyFieldDescriptor_FromDescriptor( |
| const FieldDescriptor* field_descriptor) { |
| return descriptor::NewInternedDescriptor(&PyFieldDescriptor_Type, |
| field_descriptor, nullptr); |
| } |
| |
| const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj) { |
| if (!PyObject_TypeCheck(obj, &PyFieldDescriptor_Type)) { |
| PyErr_SetString(PyExc_TypeError, "Not a FieldDescriptor"); |
| return nullptr; |
| } |
| return reinterpret_cast<const FieldDescriptor*>( |
| reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor); |
| } |
| |
| namespace enum_descriptor { |
| |
| // Unchecked accessor to the C++ pointer. |
| static const EnumDescriptor* _GetDescriptor( |
| PyBaseDescriptor *self) { |
| return reinterpret_cast<const EnumDescriptor*>(self->descriptor); |
| } |
| |
| static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->full_name()); |
| } |
| |
| static PyObject* GetName(PyBaseDescriptor *self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->name()); |
| } |
| |
| static PyObject* GetFile(PyBaseDescriptor *self, void *closure) { |
| return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file()); |
| } |
| |
| static PyObject* GetEnumvaluesByName(PyBaseDescriptor* self, void *closure) { |
| return NewEnumValuesByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetEnumvaluesByNumber(PyBaseDescriptor* self, void *closure) { |
| return NewEnumValuesByNumber(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetEnumvaluesSeq(PyBaseDescriptor* self, void *closure) { |
| return NewEnumValuesSeq(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { |
| const Descriptor* containing_type = |
| _GetDescriptor(self)->containing_type(); |
| if (containing_type) { |
| return PyMessageDescriptor_FromDescriptor(containing_type); |
| } else { |
| Py_RETURN_NONE; |
| } |
| } |
| |
| static int SetContainingType(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("containing_type"); |
| } |
| |
| |
| static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { |
| const EnumOptions& options(_GetDescriptor(self)->options()); |
| if (&options != &EnumOptions::default_instance()) { |
| Py_RETURN_TRUE; |
| } else { |
| Py_RETURN_FALSE; |
| } |
| } |
| |
| static PyObject* GetIsClosed(PyBaseDescriptor* self, void* closure) { |
| return PyBool_FromLong(_GetDescriptor(self)->is_closed()); |
| } |
| |
| static int SetHasOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("has_options"); |
| } |
| |
| static PyObject* GetOptions(PyBaseDescriptor *self) { |
| return GetOrBuildOptions(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFeatures(PyBaseDescriptor* self) { |
| return GetFeaturesImpl(_GetDescriptor(self)); |
| } |
| |
| static int SetOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_options"); |
| } |
| |
| static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_serialized_options"); |
| } |
| |
| static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { |
| return CopyToPythonProto<EnumDescriptorProto>(_GetDescriptor(self), target); |
| } |
| |
| static PyMethodDef Methods[] = { |
| {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS}, |
| {"_GetFeatures", (PyCFunction)GetFeatures, METH_NOARGS}, |
| {"CopyToProto", (PyCFunction)CopyToProto, METH_O}, |
| {nullptr}, |
| }; |
| |
| static PyGetSetDef Getters[] = { |
| {"full_name", (getter)GetFullName, nullptr, "Full name"}, |
| {"name", (getter)GetName, nullptr, "last name"}, |
| {"file", (getter)GetFile, nullptr, "File descriptor"}, |
| {"values", (getter)GetEnumvaluesSeq, nullptr, "values"}, |
| {"values_by_name", (getter)GetEnumvaluesByName, nullptr, |
| "Enum values by name"}, |
| {"values_by_number", (getter)GetEnumvaluesByNumber, nullptr, |
| "Enum values by number"}, |
| |
| {"containing_type", (getter)GetContainingType, (setter)SetContainingType, |
| "Containing type"}, |
| {"has_options", (getter)GetHasOptions, (setter)SetHasOptions, |
| "Has Options"}, |
| {"is_closed", (getter)GetIsClosed, nullptr, "If the enum is closed"}, |
| {"_options", (getter) nullptr, (setter)SetOptions, "Options"}, |
| {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions, |
| "Serialized Options"}, |
| {nullptr}, |
| }; |
| |
| } // namespace enum_descriptor |
| |
| PyTypeObject PyEnumDescriptor_Type = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME |
| ".EnumDescriptor", // tp_name |
| sizeof(PyBaseDescriptor), // tp_basicsize |
| 0, // tp_itemsize |
| nullptr, // tp_dealloc |
| #if PY_VERSION_HEX < 0x03080000 |
| nullptr, // tp_print |
| #else |
| 0, // tp_vectorcall_offset |
| #endif |
| nullptr, // tp_getattr |
| nullptr, // tp_setattr |
| nullptr, // tp_compare |
| nullptr, // tp_repr |
| nullptr, // tp_as_number |
| nullptr, // tp_as_sequence |
| nullptr, // tp_as_mapping |
| nullptr, // tp_hash |
| nullptr, // tp_call |
| nullptr, // tp_str |
| nullptr, // tp_getattro |
| nullptr, // tp_setattro |
| nullptr, // tp_as_buffer |
| Py_TPFLAGS_DEFAULT, // tp_flags |
| "A Enum Descriptor", // tp_doc |
| nullptr, // tp_traverse |
| nullptr, // tp_clear |
| nullptr, // tp_richcompare |
| 0, // tp_weaklistoffset |
| nullptr, // tp_iter |
| nullptr, // tp_iternext |
| enum_descriptor::Methods, // tp_methods |
| nullptr, // tp_members |
| enum_descriptor::Getters, // tp_getset |
| &descriptor::PyBaseDescriptor_Type, // tp_base |
| }; |
| |
| PyObject* PyEnumDescriptor_FromDescriptor( |
| const EnumDescriptor* enum_descriptor) { |
| return descriptor::NewInternedDescriptor(&PyEnumDescriptor_Type, |
| enum_descriptor, nullptr); |
| } |
| |
| const EnumDescriptor* PyEnumDescriptor_AsDescriptor(PyObject* obj) { |
| if (!PyObject_TypeCheck(obj, &PyEnumDescriptor_Type)) { |
| PyErr_SetString(PyExc_TypeError, "Not an EnumDescriptor"); |
| return nullptr; |
| } |
| return reinterpret_cast<const EnumDescriptor*>( |
| reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor); |
| } |
| |
| namespace enumvalue_descriptor { |
| |
| // Unchecked accessor to the C++ pointer. |
| static const EnumValueDescriptor* _GetDescriptor( |
| PyBaseDescriptor *self) { |
| return reinterpret_cast<const EnumValueDescriptor*>(self->descriptor); |
| } |
| |
| static PyObject* GetName(PyBaseDescriptor *self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->name()); |
| } |
| |
| static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->number()); |
| } |
| |
| static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->index()); |
| } |
| |
| static PyObject* GetType(PyBaseDescriptor *self, void *closure) { |
| return PyEnumDescriptor_FromDescriptor(_GetDescriptor(self)->type()); |
| } |
| |
| static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { |
| const EnumValueOptions& options(_GetDescriptor(self)->options()); |
| if (&options != &EnumValueOptions::default_instance()) { |
| Py_RETURN_TRUE; |
| } else { |
| Py_RETURN_FALSE; |
| } |
| } |
| static int SetHasOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("has_options"); |
| } |
| |
| static PyObject* GetOptions(PyBaseDescriptor *self) { |
| return GetOrBuildOptions(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFeatures(PyBaseDescriptor* self) { |
| return GetFeaturesImpl(_GetDescriptor(self)); |
| } |
| |
| static int SetOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_options"); |
| } |
| |
| static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_serialized_options"); |
| } |
| |
| static PyGetSetDef Getters[] = { |
| {"name", (getter)GetName, nullptr, "name"}, |
| {"number", (getter)GetNumber, nullptr, "number"}, |
| {"index", (getter)GetIndex, nullptr, "index"}, |
| {"type", (getter)GetType, nullptr, "index"}, |
| |
| {"has_options", (getter)GetHasOptions, (setter)SetHasOptions, |
| "Has Options"}, |
| {"_options", (getter) nullptr, (setter)SetOptions, "Options"}, |
| {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions, |
| "Serialized Options"}, |
| {nullptr}, |
| }; |
| |
| static PyMethodDef Methods[] = { |
| {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS}, |
| {"_GetFeatures", (PyCFunction)GetFeatures, METH_NOARGS}, |
| {nullptr}, |
| }; |
| |
| } // namespace enumvalue_descriptor |
| |
| PyTypeObject PyEnumValueDescriptor_Type = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME |
| ".EnumValueDescriptor", // tp_name |
| sizeof(PyBaseDescriptor), // tp_basicsize |
| 0, // tp_itemsize |
| nullptr, // tp_dealloc |
| #if PY_VERSION_HEX < 0x03080000 |
| nullptr, // tp_print |
| #else |
| 0, // tp_vectorcall_offset |
| #endif |
| nullptr, // tp_getattr |
| nullptr, // tp_setattr |
| nullptr, // tp_compare |
| nullptr, // tp_repr |
| nullptr, // tp_as_number |
| nullptr, // tp_as_sequence |
| nullptr, // tp_as_mapping |
| nullptr, // tp_hash |
| nullptr, // tp_call |
| nullptr, // tp_str |
| nullptr, // tp_getattro |
| nullptr, // tp_setattro |
| nullptr, // tp_as_buffer |
| Py_TPFLAGS_DEFAULT, // tp_flags |
| "A EnumValue Descriptor", // tp_doc |
| nullptr, // tp_traverse |
| nullptr, // tp_clear |
| nullptr, // tp_richcompare |
| 0, // tp_weaklistoffset |
| nullptr, // tp_iter |
| nullptr, // tp_iternext |
| enumvalue_descriptor::Methods, // tp_methods |
| nullptr, // tp_members |
| enumvalue_descriptor::Getters, // tp_getset |
| &descriptor::PyBaseDescriptor_Type, // tp_base |
| }; |
| |
| PyObject* PyEnumValueDescriptor_FromDescriptor( |
| const EnumValueDescriptor* enumvalue_descriptor) { |
| return descriptor::NewInternedDescriptor(&PyEnumValueDescriptor_Type, |
| enumvalue_descriptor, nullptr); |
| } |
| |
| namespace file_descriptor { |
| |
| // Unchecked accessor to the C++ pointer. |
| static const FileDescriptor* _GetDescriptor(PyFileDescriptor *self) { |
| return reinterpret_cast<const FileDescriptor*>(self->base.descriptor); |
| } |
| |
| static void Dealloc(PyFileDescriptor* self) { |
| Py_XDECREF(self->serialized_pb); |
| descriptor::Dealloc(reinterpret_cast<PyObject*>(self)); |
| } |
| |
| static PyObject* GetPool(PyFileDescriptor *self, void *closure) { |
| PyObject* pool = reinterpret_cast<PyObject*>( |
| GetDescriptorPool_FromPool(_GetDescriptor(self)->pool())); |
| Py_XINCREF(pool); |
| return pool; |
| } |
| |
| static PyObject* GetName(PyFileDescriptor *self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->name()); |
| } |
| |
| static PyObject* GetPackage(PyFileDescriptor *self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->package()); |
| } |
| |
| static PyObject* GetSerializedPb(PyFileDescriptor *self, void *closure) { |
| PyObject *serialized_pb = self->serialized_pb; |
| if (serialized_pb != nullptr) { |
| Py_INCREF(serialized_pb); |
| return serialized_pb; |
| } |
| FileDescriptorProto file_proto; |
| _GetDescriptor(self)->CopyTo(&file_proto); |
| std::string contents; |
| file_proto.SerializePartialToString(&contents); |
| self->serialized_pb = PyBytes_FromStringAndSize( |
| contents.c_str(), contents.size()); |
| if (self->serialized_pb == nullptr) { |
| return nullptr; |
| } |
| Py_INCREF(self->serialized_pb); |
| return self->serialized_pb; |
| } |
| |
| static PyObject* GetMessageTypesByName(PyFileDescriptor* self, void *closure) { |
| return NewFileMessageTypesByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetEnumTypesByName(PyFileDescriptor* self, void *closure) { |
| return NewFileEnumTypesByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetExtensionsByName(PyFileDescriptor* self, void *closure) { |
| return NewFileExtensionsByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetServicesByName(PyFileDescriptor* self, void *closure) { |
| return NewFileServicesByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetDependencies(PyFileDescriptor* self, void *closure) { |
| return NewFileDependencies(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetPublicDependencies(PyFileDescriptor* self, void *closure) { |
| return NewFilePublicDependencies(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetHasOptions(PyFileDescriptor *self, void *closure) { |
| const FileOptions& options(_GetDescriptor(self)->options()); |
| if (&options != &FileOptions::default_instance()) { |
| Py_RETURN_TRUE; |
| } else { |
| Py_RETURN_FALSE; |
| } |
| } |
| static int SetHasOptions(PyFileDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("has_options"); |
| } |
| |
| static PyObject* GetDebugString(PyFileDescriptor* self) { |
| return PyString_FromCppString(_GetDescriptor(self)->DebugString()); |
| } |
| |
| static PyObject* GetOptions(PyFileDescriptor *self) { |
| return GetOrBuildOptions(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFeatures(PyFileDescriptor* self) { |
| return GetFeaturesImpl(_GetDescriptor(self)); |
| } |
| |
| static int SetOptions(PyFileDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_options"); |
| } |
| |
| static int SetSerializedOptions(PyFileDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_serialized_options"); |
| } |
| |
| static PyObject* GetEdition(PyFileDescriptor* self, void* closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->edition()); |
| } |
| |
| static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) { |
| return CopyToPythonProto<FileDescriptorProto>(_GetDescriptor(self), target); |
| } |
| |
| static PyGetSetDef Getters[] = { |
| {"pool", (getter)GetPool, nullptr, "pool"}, |
| {"name", (getter)GetName, nullptr, "name"}, |
| {"package", (getter)GetPackage, nullptr, "package"}, |
| {"serialized_pb", (getter)GetSerializedPb}, |
| {"message_types_by_name", (getter)GetMessageTypesByName, nullptr, |
| "Messages by name"}, |
| {"enum_types_by_name", (getter)GetEnumTypesByName, nullptr, |
| "Enums by name"}, |
| {"extensions_by_name", (getter)GetExtensionsByName, nullptr, |
| "Extensions by name"}, |
| {"services_by_name", (getter)GetServicesByName, nullptr, |
| "Services by name"}, |
| {"dependencies", (getter)GetDependencies, nullptr, "Dependencies"}, |
| {"public_dependencies", (getter)GetPublicDependencies, nullptr, |
| "Dependencies"}, |
| |
| {"has_options", (getter)GetHasOptions, (setter)SetHasOptions, |
| "Has Options"}, |
| {"_options", (getter) nullptr, (setter)SetOptions, "Options"}, |
| {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions, |
| "Serialized Options"}, |
| {"edition", (getter)GetEdition, (setter) nullptr, "Edition"}, |
| {nullptr}, |
| }; |
| |
| static PyMethodDef Methods[] = { |
| {"GetDebugString", (PyCFunction)GetDebugString, METH_NOARGS}, |
| {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS}, |
| {"_GetFeatures", (PyCFunction)GetFeatures, METH_NOARGS}, |
| {"CopyToProto", (PyCFunction)CopyToProto, METH_O}, |
| {nullptr}, |
| }; |
| |
| } // namespace file_descriptor |
| |
| PyTypeObject PyFileDescriptor_Type = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME |
| ".FileDescriptor", // tp_name |
| sizeof(PyFileDescriptor), // tp_basicsize |
| 0, // tp_itemsize |
| (destructor)file_descriptor::Dealloc, // tp_dealloc |
| #if PY_VERSION_HEX < 0x03080000 |
| nullptr, // tp_print |
| #else |
| 0, // tp_vectorcall_offset |
| #endif |
| nullptr, // tp_getattr |
| nullptr, // tp_setattr |
| nullptr, // tp_compare |
| nullptr, // tp_repr |
| nullptr, // tp_as_number |
| nullptr, // tp_as_sequence |
| nullptr, // tp_as_mapping |
| nullptr, // tp_hash |
| nullptr, // tp_call |
| nullptr, // tp_str |
| nullptr, // tp_getattro |
| nullptr, // tp_setattro |
| nullptr, // tp_as_buffer |
| Py_TPFLAGS_DEFAULT, // tp_flags |
| "A File Descriptor", // tp_doc |
| nullptr, // tp_traverse |
| nullptr, // tp_clear |
| nullptr, // tp_richcompare |
| 0, // tp_weaklistoffset |
| nullptr, // tp_iter |
| nullptr, // tp_iternext |
| file_descriptor::Methods, // tp_methods |
| nullptr, // tp_members |
| file_descriptor::Getters, // tp_getset |
| &descriptor::PyBaseDescriptor_Type, // tp_base |
| nullptr, // tp_dict |
| nullptr, // tp_descr_get |
| nullptr, // tp_descr_set |
| 0, // tp_dictoffset |
| nullptr, // tp_init |
| nullptr, // tp_alloc |
| nullptr, // tp_new |
| PyObject_GC_Del, // tp_free |
| }; |
| |
| PyObject* PyFileDescriptor_FromDescriptor( |
| const FileDescriptor* file_descriptor) { |
| return PyFileDescriptor_FromDescriptorWithSerializedPb(file_descriptor, |
| nullptr); |
| } |
| |
| PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb( |
| const FileDescriptor* file_descriptor, PyObject *serialized_pb) { |
| bool was_created; |
| PyObject* py_descriptor = descriptor::NewInternedDescriptor( |
| &PyFileDescriptor_Type, file_descriptor, &was_created); |
| if (py_descriptor == nullptr) { |
| return nullptr; |
| } |
| if (was_created) { |
| PyFileDescriptor* cfile_descriptor = |
| reinterpret_cast<PyFileDescriptor*>(py_descriptor); |
| Py_XINCREF(serialized_pb); |
| cfile_descriptor->serialized_pb = serialized_pb; |
| } |
| // TODO: In the case of a cached object, check that serialized_pb |
| // is the same as before. |
| |
| return py_descriptor; |
| } |
| |
| const FileDescriptor* PyFileDescriptor_AsDescriptor(PyObject* obj) { |
| if (!PyObject_TypeCheck(obj, &PyFileDescriptor_Type)) { |
| PyErr_SetString(PyExc_TypeError, "Not a FileDescriptor"); |
| return nullptr; |
| } |
| return reinterpret_cast<const FileDescriptor*>( |
| reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor); |
| } |
| |
| namespace oneof_descriptor { |
| |
| // Unchecked accessor to the C++ pointer. |
| static const OneofDescriptor* _GetDescriptor( |
| PyBaseDescriptor *self) { |
| return reinterpret_cast<const OneofDescriptor*>(self->descriptor); |
| } |
| |
| static PyObject* GetName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->name()); |
| } |
| |
| static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->full_name()); |
| } |
| |
| static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->index()); |
| } |
| |
| static PyObject* GetFields(PyBaseDescriptor* self, void *closure) { |
| return NewOneofFieldsSeq(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { |
| const Descriptor* containing_type = |
| _GetDescriptor(self)->containing_type(); |
| if (containing_type) { |
| return PyMessageDescriptor_FromDescriptor(containing_type); |
| } else { |
| Py_RETURN_NONE; |
| } |
| } |
| |
| static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { |
| const OneofOptions& options(_GetDescriptor(self)->options()); |
| if (&options != &OneofOptions::default_instance()) { |
| Py_RETURN_TRUE; |
| } else { |
| Py_RETURN_FALSE; |
| } |
| } |
| |
| static int SetHasOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("has_options"); |
| } |
| |
| static PyObject* GetOptions(PyBaseDescriptor *self) { |
| return GetOrBuildOptions(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFeatures(PyBaseDescriptor* self) { |
| return GetFeaturesImpl(_GetDescriptor(self)); |
| } |
| |
| static int SetOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_options"); |
| } |
| |
| static int SetSerializedOptions(PyBaseDescriptor *self, PyObject *value, |
| void *closure) { |
| return CheckCalledFromGeneratedFile("_serialized_options"); |
| } |
| |
| static PyGetSetDef Getters[] = { |
| {"name", (getter)GetName, nullptr, "Name"}, |
| {"full_name", (getter)GetFullName, nullptr, "Full name"}, |
| {"index", (getter)GetIndex, nullptr, "Index"}, |
| |
| {"containing_type", (getter)GetContainingType, nullptr, "Containing type"}, |
| {"has_options", (getter)GetHasOptions, (setter)SetHasOptions, |
| "Has Options"}, |
| {"_options", (getter) nullptr, (setter)SetOptions, "Options"}, |
| {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions, |
| "Serialized Options"}, |
| {"fields", (getter)GetFields, nullptr, "Fields"}, |
| {nullptr}, |
| }; |
| |
| static PyMethodDef Methods[] = { |
| {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS}, |
| {"_GetFeatures", (PyCFunction)GetFeatures, METH_NOARGS}, |
| {nullptr}, |
| }; |
| |
| } // namespace oneof_descriptor |
| |
| PyTypeObject PyOneofDescriptor_Type = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME |
| ".OneofDescriptor", // tp_name |
| sizeof(PyBaseDescriptor), // tp_basicsize |
| 0, // tp_itemsize |
| nullptr, // tp_dealloc |
| #if PY_VERSION_HEX < 0x03080000 |
| nullptr, // tp_print |
| #else |
| 0, // tp_vectorcall_offset |
| #endif |
| nullptr, // tp_getattr |
| nullptr, // tp_setattr |
| nullptr, // tp_compare |
| nullptr, // tp_repr |
| nullptr, // tp_as_number |
| nullptr, // tp_as_sequence |
| nullptr, // tp_as_mapping |
| nullptr, // tp_hash |
| nullptr, // tp_call |
| nullptr, // tp_str |
| nullptr, // tp_getattro |
| nullptr, // tp_setattro |
| nullptr, // tp_as_buffer |
| Py_TPFLAGS_DEFAULT, // tp_flags |
| "A Oneof Descriptor", // tp_doc |
| nullptr, // tp_traverse |
| nullptr, // tp_clear |
| nullptr, // tp_richcompare |
| 0, // tp_weaklistoffset |
| nullptr, // tp_iter |
| nullptr, // tp_iternext |
| oneof_descriptor::Methods, // tp_methods |
| nullptr, // tp_members |
| oneof_descriptor::Getters, // tp_getset |
| &descriptor::PyBaseDescriptor_Type, // tp_base |
| }; |
| |
| PyObject* PyOneofDescriptor_FromDescriptor( |
| const OneofDescriptor* oneof_descriptor) { |
| return descriptor::NewInternedDescriptor(&PyOneofDescriptor_Type, |
| oneof_descriptor, nullptr); |
| } |
| |
| namespace service_descriptor { |
| |
| // Unchecked accessor to the C++ pointer. |
| static const ServiceDescriptor* _GetDescriptor( |
| PyBaseDescriptor *self) { |
| return reinterpret_cast<const ServiceDescriptor*>(self->descriptor); |
| } |
| |
| static PyObject* GetName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->name()); |
| } |
| |
| static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->full_name()); |
| } |
| |
| static PyObject* GetFile(PyBaseDescriptor *self, void *closure) { |
| return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file()); |
| } |
| |
| static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->index()); |
| } |
| |
| static PyObject* GetMethods(PyBaseDescriptor* self, void *closure) { |
| return NewServiceMethodsSeq(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetMethodsByName(PyBaseDescriptor* self, void *closure) { |
| return NewServiceMethodsByName(_GetDescriptor(self)); |
| } |
| |
| static PyObject* FindMethodByName(PyBaseDescriptor *self, PyObject* arg) { |
| Py_ssize_t name_size; |
| char* name; |
| if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { |
| return nullptr; |
| } |
| |
| const MethodDescriptor* method_descriptor = |
| _GetDescriptor(self)->FindMethodByName( |
| absl::string_view(name, name_size)); |
| if (method_descriptor == nullptr) { |
| PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name); |
| return nullptr; |
| } |
| |
| return PyMethodDescriptor_FromDescriptor(method_descriptor); |
| } |
| |
| static PyObject* GetOptions(PyBaseDescriptor *self) { |
| return GetOrBuildOptions(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFeatures(PyBaseDescriptor* self) { |
| return GetFeaturesImpl(_GetDescriptor(self)); |
| } |
| |
| static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { |
| return CopyToPythonProto<ServiceDescriptorProto>(_GetDescriptor(self), |
| target); |
| } |
| |
| static PyGetSetDef Getters[] = { |
| {"name", (getter)GetName, nullptr, "Name", nullptr}, |
| {"full_name", (getter)GetFullName, nullptr, "Full name", nullptr}, |
| {"file", (getter)GetFile, nullptr, "File descriptor"}, |
| {"index", (getter)GetIndex, nullptr, "Index", nullptr}, |
| {"methods", (getter)GetMethods, nullptr, "Methods", nullptr}, |
| {"methods_by_name", (getter)GetMethodsByName, nullptr, "Methods by name", |
| nullptr}, |
| {nullptr}, |
| }; |
| |
| static PyMethodDef Methods[] = { |
| {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS}, |
| {"_GetFeatures", (PyCFunction)GetFeatures, METH_NOARGS}, |
| {"CopyToProto", (PyCFunction)CopyToProto, METH_O}, |
| {"FindMethodByName", (PyCFunction)FindMethodByName, METH_O}, |
| {nullptr}, |
| }; |
| |
| } // namespace service_descriptor |
| |
| PyTypeObject PyServiceDescriptor_Type = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME |
| ".ServiceDescriptor", // tp_name |
| sizeof(PyBaseDescriptor), // tp_basicsize |
| 0, // tp_itemsize |
| nullptr, // tp_dealloc |
| #if PY_VERSION_HEX < 0x03080000 |
| nullptr, // tp_print |
| #else |
| 0, // tp_vectorcall_offset |
| #endif |
| nullptr, // tp_getattr |
| nullptr, // tp_setattr |
| nullptr, // tp_compare |
| nullptr, // tp_repr |
| nullptr, // tp_as_number |
| nullptr, // tp_as_sequence |
| nullptr, // tp_as_mapping |
| nullptr, // tp_hash |
| nullptr, // tp_call |
| nullptr, // tp_str |
| nullptr, // tp_getattro |
| nullptr, // tp_setattro |
| nullptr, // tp_as_buffer |
| Py_TPFLAGS_DEFAULT, // tp_flags |
| "A Service Descriptor", // tp_doc |
| nullptr, // tp_traverse |
| nullptr, // tp_clear |
| nullptr, // tp_richcompare |
| 0, // tp_weaklistoffset |
| nullptr, // tp_iter |
| nullptr, // tp_iternext |
| service_descriptor::Methods, // tp_methods |
| nullptr, // tp_members |
| service_descriptor::Getters, // tp_getset |
| &descriptor::PyBaseDescriptor_Type, // tp_base |
| }; |
| |
| PyObject* PyServiceDescriptor_FromDescriptor( |
| const ServiceDescriptor* service_descriptor) { |
| return descriptor::NewInternedDescriptor(&PyServiceDescriptor_Type, |
| service_descriptor, nullptr); |
| } |
| |
| const ServiceDescriptor* PyServiceDescriptor_AsDescriptor(PyObject* obj) { |
| if (!PyObject_TypeCheck(obj, &PyServiceDescriptor_Type)) { |
| PyErr_SetString(PyExc_TypeError, "Not a ServiceDescriptor"); |
| return nullptr; |
| } |
| return reinterpret_cast<const ServiceDescriptor*>( |
| reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor); |
| } |
| |
| namespace method_descriptor { |
| |
| // Unchecked accessor to the C++ pointer. |
| static const MethodDescriptor* _GetDescriptor( |
| PyBaseDescriptor *self) { |
| return reinterpret_cast<const MethodDescriptor*>(self->descriptor); |
| } |
| |
| static PyObject* GetName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->name()); |
| } |
| |
| static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { |
| return PyString_FromCppString(_GetDescriptor(self)->full_name()); |
| } |
| |
| static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) { |
| return PyLong_FromLong(_GetDescriptor(self)->index()); |
| } |
| |
| static PyObject* GetContainingService(PyBaseDescriptor *self, void *closure) { |
| const ServiceDescriptor* containing_service = |
| _GetDescriptor(self)->service(); |
| return PyServiceDescriptor_FromDescriptor(containing_service); |
| } |
| |
| static PyObject* GetInputType(PyBaseDescriptor *self, void *closure) { |
| const Descriptor* input_type = _GetDescriptor(self)->input_type(); |
| return PyMessageDescriptor_FromDescriptor(input_type); |
| } |
| |
| static PyObject* GetOutputType(PyBaseDescriptor *self, void *closure) { |
| const Descriptor* output_type = _GetDescriptor(self)->output_type(); |
| return PyMessageDescriptor_FromDescriptor(output_type); |
| } |
| |
| static PyObject* GetClientStreaming(PyBaseDescriptor* self, void* closure) { |
| return PyBool_FromLong(_GetDescriptor(self)->client_streaming() ? 1 : 0); |
| } |
| |
| static PyObject* GetServerStreaming(PyBaseDescriptor* self, void* closure) { |
| return PyBool_FromLong(_GetDescriptor(self)->server_streaming() ? 1 : 0); |
| } |
| |
| static PyObject* GetOptions(PyBaseDescriptor *self) { |
| return GetOrBuildOptions(_GetDescriptor(self)); |
| } |
| |
| static PyObject* GetFeatures(PyBaseDescriptor* self) { |
| return GetFeaturesImpl(_GetDescriptor(self)); |
| } |
| |
| static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { |
| return CopyToPythonProto<MethodDescriptorProto>(_GetDescriptor(self), target); |
| } |
| |
| static PyGetSetDef Getters[] = { |
| {"name", (getter)GetName, nullptr, "Name", nullptr}, |
| {"full_name", (getter)GetFullName, nullptr, "Full name", nullptr}, |
| {"index", (getter)GetIndex, nullptr, "Index", nullptr}, |
| {"containing_service", (getter)GetContainingService, nullptr, |
| "Containing service", nullptr}, |
| {"input_type", (getter)GetInputType, nullptr, "Input type", nullptr}, |
| {"output_type", (getter)GetOutputType, nullptr, "Output type", nullptr}, |
| {"client_streaming", (getter)GetClientStreaming, nullptr, |
| "Client streaming", nullptr}, |
| {"server_streaming", (getter)GetServerStreaming, nullptr, |
| "Server streaming", nullptr}, |
| {nullptr}, |
| }; |
| |
| static PyMethodDef Methods[] = { |
| {"GetOptions", (PyCFunction)GetOptions, METH_NOARGS}, |
| {"_GetFeatures", (PyCFunction)GetFeatures, METH_NOARGS}, |
| {"CopyToProto", (PyCFunction)CopyToProto, METH_O}, |
| {nullptr}, |
| }; |
| |
| } // namespace method_descriptor |
| |
| PyTypeObject PyMethodDescriptor_Type = { |
| PyVarObject_HEAD_INIT(&PyType_Type, 0) FULL_MODULE_NAME |
| ".MethodDescriptor", // tp_name |
| sizeof(PyBaseDescriptor), // tp_basicsize |
| 0, // tp_itemsize |
| nullptr, // tp_dealloc |
| #if PY_VERSION_HEX < 0x03080000 |
| nullptr, // tp_print |
| #else |
| 0, // tp_vectorcall_offset |
| #endif |
| nullptr, // tp_getattr |
| nullptr, // tp_setattr |
| nullptr, // tp_compare |
| nullptr, // tp_repr |
| nullptr, // tp_as_number |
| nullptr, // tp_as_sequence |
| nullptr, // tp_as_mapping |
| nullptr, // tp_hash |
| nullptr, // tp_call |
| nullptr, // tp_str |
| nullptr, // tp_getattro |
| nullptr, // tp_setattro |
| nullptr, // tp_as_buffer |
| Py_TPFLAGS_DEFAULT, // tp_flags |
| "A Method Descriptor", // tp_doc |
| nullptr, // tp_traverse |
| nullptr, // tp_clear |
| nullptr, // tp_richcompare |
| 0, // tp_weaklistoffset |
| nullptr, // tp_iter |
| nullptr, // tp_iternext |
| method_descriptor::Methods, // tp_methods |
| nullptr, // tp_members |
| method_descriptor::Getters, // tp_getset |
| &descriptor::PyBaseDescriptor_Type, // tp_base |
| }; |
| |
| PyObject* PyMethodDescriptor_FromDescriptor( |
| const MethodDescriptor* method_descriptor) { |
| return descriptor::NewInternedDescriptor(&PyMethodDescriptor_Type, |
| method_descriptor, nullptr); |
| } |
| |
| // Add a enum values to a type dictionary. |
| static bool AddEnumValues(PyTypeObject *type, |
| const EnumDescriptor* enum_descriptor) { |
| for (int i = 0; i < enum_descriptor->value_count(); ++i) { |
| const EnumValueDescriptor* value = enum_descriptor->value(i); |
| ScopedPyObjectPtr obj(PyLong_FromLong(value->number())); |
| if (obj == nullptr) { |
| return false; |
| } |
| if (PyDict_SetItemString(type->tp_dict, value->name().c_str(), obj.get()) < |
| 0) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| static bool AddIntConstant(PyTypeObject *type, const char* name, int value) { |
| ScopedPyObjectPtr obj(PyLong_FromLong(value)); |
| if (PyDict_SetItemString(type->tp_dict, name, obj.get()) < 0) { |
| return false; |
| } |
| return true; |
| } |
| |
| |
| bool InitDescriptor() { |
| if (PyType_Ready(&PyMessageDescriptor_Type) < 0) |
| return false; |
| |
| if (PyType_Ready(&PyFieldDescriptor_Type) < 0) |
| return false; |
| |
| if (!AddEnumValues(&PyFieldDescriptor_Type, |
| FieldDescriptorProto::Label_descriptor())) { |
| return false; |
| } |
| if (!AddEnumValues(&PyFieldDescriptor_Type, |
| FieldDescriptorProto::Type_descriptor())) { |
| return false; |
| } |
| #define ADD_FIELDDESC_CONSTANT(NAME) AddIntConstant( \ |
| &PyFieldDescriptor_Type, #NAME, FieldDescriptor::NAME) |
| if (!ADD_FIELDDESC_CONSTANT(CPPTYPE_INT32) || |
| !ADD_FIELDDESC_CONSTANT(CPPTYPE_INT64) || |
| !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT32) || |
| !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT64) || |
| !ADD_FIELDDESC_CONSTANT(CPPTYPE_DOUBLE) || |
| !ADD_FIELDDESC_CONSTANT(CPPTYPE_FLOAT) || |
| !ADD_FIELDDESC_CONSTANT(CPPTYPE_BOOL) || |
| !ADD_FIELDDESC_CONSTANT(CPPTYPE_ENUM) || |
| !ADD_FIELDDESC_CONSTANT(CPPTYPE_STRING) || |
| !ADD_FIELDDESC_CONSTANT(CPPTYPE_MESSAGE)) { |
| return false; |
| } |
| #undef ADD_FIELDDESC_CONSTANT |
| |
| if (PyType_Ready(&PyEnumDescriptor_Type) < 0) |
| return false; |
| |
| if (PyType_Ready(&PyEnumValueDescriptor_Type) < 0) |
| return false; |
| |
| if (PyType_Ready(&PyFileDescriptor_Type) < 0) |
| return false; |
| |
| if (PyType_Ready(&PyOneofDescriptor_Type) < 0) |
| return false; |
| |
| if (PyType_Ready(&PyServiceDescriptor_Type) < 0) |
| return false; |
| |
| if (PyType_Ready(&PyMethodDescriptor_Type) < 0) |
| return false; |
| |
| if (!InitDescriptorMappingTypes()) |
| return false; |
| |
| // Initialize globals defined in this file. |
| interned_descriptors = new std::unordered_map<const void*, PyObject*>; |
| |
| return true; |
| } |
| |
| } // namespace python |
| } // namespace protobuf |
| } // namespace google |