blob: 7e121c40433ec34dcf3d1bddafca31396906869a [file] [log] [blame]
Adam Cozzette501ecec2023-09-26 14:36:20 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2023 Google LLC. All rights reserved.
Adam Cozzette501ecec2023-09-26 14:36:20 -07003//
Protobuf Team Bot0fab7732023-11-20 13:38:15 -08004// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
Adam Cozzette501ecec2023-09-26 14:36:20 -07007
8#include "python/descriptor.h"
9
10#include "python/convert.h"
11#include "python/descriptor_containers.h"
12#include "python/descriptor_pool.h"
13#include "python/message.h"
14#include "python/protobuf.h"
Eric Salob997cb62023-12-21 08:09:54 -080015#include "upb/base/upcast.h"
Adam Cozzette501ecec2023-09-26 14:36:20 -070016#include "upb/reflection/def.h"
17#include "upb/util/def_to_proto.h"
18
19// -----------------------------------------------------------------------------
20// DescriptorBase
21// -----------------------------------------------------------------------------
22
23// This representation is used by all concrete descriptors.
24
25typedef struct {
26 PyObject_HEAD;
27 PyObject* pool; // We own a ref.
28 const void* def; // Type depends on the class. Kept alive by "pool".
29 PyObject* options; // NULL if not present or not cached.
Mike Kruskalc23d5332023-11-10 15:18:00 -080030 PyObject* features; // NULL if not present or not cached.
Adam Cozzette501ecec2023-09-26 14:36:20 -070031 PyObject* message_meta; // We own a ref.
32} PyUpb_DescriptorBase;
33
34PyObject* PyUpb_AnyDescriptor_GetPool(PyObject* desc) {
35 PyUpb_DescriptorBase* base = (void*)desc;
36 return base->pool;
37}
38
39const void* PyUpb_AnyDescriptor_GetDef(PyObject* desc) {
40 PyUpb_DescriptorBase* base = (void*)desc;
41 return base->def;
42}
43
44static PyUpb_DescriptorBase* PyUpb_DescriptorBase_DoCreate(
45 PyUpb_DescriptorType type, const void* def, const upb_FileDef* file) {
46 PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
47 PyTypeObject* type_obj = state->descriptor_types[type];
48 assert(def);
49
50 PyUpb_DescriptorBase* base = (void*)PyType_GenericAlloc(type_obj, 0);
51 base->pool = PyUpb_DescriptorPool_Get(upb_FileDef_Pool(file));
52 base->def = def;
53 base->options = NULL;
Mike Kruskalc23d5332023-11-10 15:18:00 -080054 base->features = NULL;
Adam Cozzette501ecec2023-09-26 14:36:20 -070055 base->message_meta = NULL;
56
57 PyUpb_ObjCache_Add(def, &base->ob_base);
58 return base;
59}
60
61// Returns a Python object wrapping |def|, of descriptor type |type|. If a
62// wrapper was previously created for this def, returns it, otherwise creates a
63// new wrapper.
64static PyObject* PyUpb_DescriptorBase_Get(PyUpb_DescriptorType type,
65 const void* def,
66 const upb_FileDef* file) {
67 PyUpb_DescriptorBase* base = (PyUpb_DescriptorBase*)PyUpb_ObjCache_Get(def);
68
69 if (!base) {
70 base = PyUpb_DescriptorBase_DoCreate(type, def, file);
71 }
72
73 return &base->ob_base;
74}
75
76static PyUpb_DescriptorBase* PyUpb_DescriptorBase_Check(
77 PyObject* obj, PyUpb_DescriptorType type) {
78 PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
79 PyTypeObject* type_obj = state->descriptor_types[type];
80 if (!PyObject_TypeCheck(obj, type_obj)) {
81 PyErr_Format(PyExc_TypeError, "Expected object of type %S, but got %R",
82 type_obj, obj);
83 return NULL;
84 }
85 return (PyUpb_DescriptorBase*)obj;
86}
87
Mike Kruskalc23d5332023-11-10 15:18:00 -080088static PyObject* PyUpb_DescriptorBase_GetCached(PyObject** cached,
89 const upb_Message* opts,
90 const upb_MiniTable* layout,
91 const char* msg_name,
92 const char* strip_field) {
93 if (!*cached) {
Adam Cozzette501ecec2023-09-26 14:36:20 -070094 // Load descriptors protos if they are not loaded already. We have to do
95 // this lazily, otherwise, it would lead to circular imports.
96 PyObject* mod = PyImport_ImportModuleLevel(PYUPB_DESCRIPTOR_MODULE, NULL,
97 NULL, NULL, 0);
98 if (mod == NULL) return NULL;
99 Py_DECREF(mod);
100
101 // Find the correct options message.
102 PyObject* default_pool = PyUpb_DescriptorPool_GetDefaultPool();
103 const upb_DefPool* symtab = PyUpb_DescriptorPool_GetSymtab(default_pool);
104 const upb_MessageDef* m = upb_DefPool_FindMessageByName(symtab, msg_name);
105 assert(m);
106
107 // Copy the options message from C to Python using serialize+parse.
108 // We don't wrap the C object directly because there is no guarantee that
109 // the descriptor_pb2 that was loaded at runtime has the same members or
110 // layout as the C types that were compiled in.
111 size_t size;
112 PyObject* py_arena = PyUpb_Arena_New();
113 upb_Arena* arena = PyUpb_Arena_Get(py_arena);
114 char* pb;
115 // TODO: Need to correctly handle failed return codes.
116 (void)upb_Encode(opts, layout, 0, arena, &pb, &size);
117 const upb_MiniTable* opts2_layout = upb_MessageDef_MiniTable(m);
118 upb_Message* opts2 = upb_Message_New(opts2_layout, arena);
119 assert(opts2);
120 upb_DecodeStatus ds =
121 upb_Decode(pb, size, opts2, opts2_layout,
122 upb_DefPool_ExtensionRegistry(symtab), 0, arena);
123 (void)ds;
124 assert(ds == kUpb_DecodeStatus_Ok);
125
Mike Kruskalc23d5332023-11-10 15:18:00 -0800126 if (strip_field) {
127 const upb_FieldDef* field =
128 upb_MessageDef_FindFieldByName(m, strip_field);
129 assert(field);
130 upb_Message_ClearFieldByDef(opts2, field);
131 }
132
133 *cached = PyUpb_Message_Get(opts2, m, py_arena);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700134 Py_DECREF(py_arena);
135 }
136
Mike Kruskalc23d5332023-11-10 15:18:00 -0800137 Py_INCREF(*cached);
138 return *cached;
139}
140
141static PyObject* PyUpb_DescriptorBase_GetOptions(PyObject** cached,
142 const upb_Message* opts,
143 const upb_MiniTable* layout,
144 const char* msg_name) {
145 return PyUpb_DescriptorBase_GetCached(cached, opts, layout, msg_name,
146 "features");
147}
148
149static PyObject* PyUpb_DescriptorBase_GetFeatures(PyObject** cached,
150 const upb_Message* opts) {
151 return PyUpb_DescriptorBase_GetCached(
152 cached, opts, &google__protobuf__FeatureSet_msg_init,
153 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".FeatureSet", NULL);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700154}
155
156typedef void* PyUpb_ToProto_Func(const void* def, upb_Arena* arena);
157
158static PyObject* PyUpb_DescriptorBase_GetSerializedProto(
159 PyObject* _self, PyUpb_ToProto_Func* func, const upb_MiniTable* layout) {
160 PyUpb_DescriptorBase* self = (void*)_self;
161 upb_Arena* arena = upb_Arena_New();
162 if (!arena) PYUPB_RETURN_OOM;
163 upb_Message* proto = func(self->def, arena);
164 if (!proto) goto oom;
165 size_t size;
166 char* pb;
167 upb_EncodeStatus status = upb_Encode(proto, layout, 0, arena, &pb, &size);
168 if (status) goto oom; // TODO non-oom errors are possible here
169 PyObject* str = PyBytes_FromStringAndSize(pb, size);
170 upb_Arena_Free(arena);
171 return str;
172
173oom:
174 upb_Arena_Free(arena);
175 PyErr_SetNone(PyExc_MemoryError);
176 return NULL;
177}
178
179static PyObject* PyUpb_DescriptorBase_CopyToProto(PyObject* _self,
180 PyUpb_ToProto_Func* func,
181 const upb_MiniTable* layout,
182 const char* expected_type,
183 PyObject* py_proto) {
184 if (!PyUpb_Message_Verify(py_proto)) return NULL;
185 const upb_MessageDef* m = PyUpb_Message_GetMsgdef(py_proto);
186 const char* type = upb_MessageDef_FullName(m);
187 if (strcmp(type, expected_type) != 0) {
188 PyErr_Format(
189 PyExc_TypeError,
190 "CopyToProto: message is of incorrect type '%s' (expected '%s'", type,
191 expected_type);
192 return NULL;
193 }
194 PyObject* serialized =
195 PyUpb_DescriptorBase_GetSerializedProto(_self, func, layout);
196 if (!serialized) return NULL;
197 PyObject* ret = PyUpb_Message_MergeFromString(py_proto, serialized);
198 Py_DECREF(serialized);
199 return ret;
200}
201
202static void PyUpb_DescriptorBase_Dealloc(PyUpb_DescriptorBase* base) {
Protobuf Team Bote32d0942023-11-06 06:43:06 -0800203 // This deallocator can be called on different types (which, despite
204 // 'Base' in the name of one of them, do not inherit from each other).
205 // Some of these types are GC types (they have Py_TPFLAGS_HAVE_GC set),
206 // which means Python's GC can visit them (via tp_visit and/or tp_clear
207 // methods) at any time. This also means we *must* stop GC from tracking
208 // instances of them before we start destructing the object. In Python
209 // 3.11, failing to do so would raise a runtime warning.
210 if (PyType_HasFeature(Py_TYPE(base), Py_TPFLAGS_HAVE_GC)) {
211 PyObject_GC_UnTrack(base);
212 }
Adam Cozzette501ecec2023-09-26 14:36:20 -0700213 PyUpb_ObjCache_Delete(base->def);
Protobuf Team Bote32d0942023-11-06 06:43:06 -0800214 // In addition to being visited by GC, instances can also (potentially) be
215 // accessed whenever arbitrary code is executed. Destructors can execute
216 // arbitrary code, so any struct members we DECREF should be set to NULL
217 // or a new value *before* calling Py_DECREF on them. The Py_CLEAR macro
218 // (and Py_SETREF in Python 3.8+) takes care to do this safely.
219 Py_CLEAR(base->message_meta);
220 Py_CLEAR(base->pool);
221 Py_CLEAR(base->options);
Mike Kruskalc23d5332023-11-10 15:18:00 -0800222 Py_CLEAR(base->features);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700223 PyUpb_Dealloc(base);
224}
225
226static int PyUpb_Descriptor_Traverse(PyUpb_DescriptorBase* base,
227 visitproc visit, void* arg) {
228 Py_VISIT(base->message_meta);
229 return 0;
230}
231
232static int PyUpb_Descriptor_Clear(PyUpb_DescriptorBase* base) {
233 Py_CLEAR(base->message_meta);
234 return 0;
235}
236
237#define DESCRIPTOR_BASE_SLOTS \
238 {Py_tp_new, (void*)&PyUpb_Forbidden_New}, { \
239 Py_tp_dealloc, (void*)&PyUpb_DescriptorBase_Dealloc \
240 }
241
242// -----------------------------------------------------------------------------
243// Descriptor
244// -----------------------------------------------------------------------------
245
246PyObject* PyUpb_Descriptor_Get(const upb_MessageDef* m) {
247 assert(m);
248 const upb_FileDef* file = upb_MessageDef_File(m);
249 return PyUpb_DescriptorBase_Get(kPyUpb_Descriptor, m, file);
250}
251
252PyObject* PyUpb_Descriptor_GetClass(const upb_MessageDef* m) {
253 PyObject* ret = PyUpb_ObjCache_Get(upb_MessageDef_MiniTable(m));
254 if (ret) return ret;
255
256 // On demand create the clss if not exist. However, if users repeatedly
257 // create and destroy a class, it could trigger a loop. This is not an
258 // issue now, but if we see CPU waste for repeatedly create and destroy
259 // in the future, we could make PyUpb_Descriptor_Get() append the descriptor
260 // to an internal list in DescriptorPool, let the pool keep descriptors alive.
261 PyObject* py_descriptor = PyUpb_Descriptor_Get(m);
262 if (py_descriptor == NULL) return NULL;
263 const char* name = upb_MessageDef_Name(m);
264 PyObject* dict = PyDict_New();
265 if (dict == NULL) goto err;
266 int status = PyDict_SetItemString(dict, "DESCRIPTOR", py_descriptor);
267 if (status < 0) goto err;
268 ret = PyUpb_MessageMeta_DoCreateClass(py_descriptor, name, dict);
269
270err:
271 Py_XDECREF(py_descriptor);
272 Py_XDECREF(dict);
273 return ret;
274}
275
276void PyUpb_Descriptor_SetClass(PyObject* py_descriptor, PyObject* meta) {
277 PyUpb_DescriptorBase* base = (PyUpb_DescriptorBase*)py_descriptor;
Adam Cozzette501ecec2023-09-26 14:36:20 -0700278 Py_INCREF(meta);
Protobuf Team Bote32d0942023-11-06 06:43:06 -0800279 // Py_SETREF replaces strong references without an intermediate invalid
280 // object state, which code executed by base->message_meta's destructor
281 // might see, but it's Python 3.8+.
282 PyObject* tmp = base->message_meta;
283 base->message_meta = meta;
284 Py_XDECREF(tmp);
Adam Cozzette501ecec2023-09-26 14:36:20 -0700285}
286
287// The LookupNested*() functions provide name lookup for entities nested inside
288// a message. This uses the symtab's table, which requires that the symtab is
289// not being mutated concurrently. We can guarantee this for Python-owned
290// symtabs, but upb cannot guarantee it in general for an arbitrary
291// `const upb_MessageDef*`.
292
293static const void* PyUpb_Descriptor_LookupNestedMessage(const upb_MessageDef* m,
294 const char* name) {
295 const upb_FileDef* filedef = upb_MessageDef_File(m);
296 const upb_DefPool* symtab = upb_FileDef_Pool(filedef);
297 PyObject* qname =
298 PyUnicode_FromFormat("%s.%s", upb_MessageDef_FullName(m), name);
299 const upb_MessageDef* ret = upb_DefPool_FindMessageByName(
300 symtab, PyUnicode_AsUTF8AndSize(qname, NULL));
301 Py_DECREF(qname);
302 return ret;
303}
304
305static const void* PyUpb_Descriptor_LookupNestedEnum(const upb_MessageDef* m,
306 const char* name) {
307 const upb_FileDef* filedef = upb_MessageDef_File(m);
308 const upb_DefPool* symtab = upb_FileDef_Pool(filedef);
309 PyObject* qname =
310 PyUnicode_FromFormat("%s.%s", upb_MessageDef_FullName(m), name);
311 const upb_EnumDef* ret =
312 upb_DefPool_FindEnumByName(symtab, PyUnicode_AsUTF8AndSize(qname, NULL));
313 Py_DECREF(qname);
314 return ret;
315}
316
317static const void* PyUpb_Descriptor_LookupNestedExtension(
318 const upb_MessageDef* m, const char* name) {
319 const upb_FileDef* filedef = upb_MessageDef_File(m);
320 const upb_DefPool* symtab = upb_FileDef_Pool(filedef);
321 PyObject* qname =
322 PyUnicode_FromFormat("%s.%s", upb_MessageDef_FullName(m), name);
323 const upb_FieldDef* ret = upb_DefPool_FindExtensionByName(
324 symtab, PyUnicode_AsUTF8AndSize(qname, NULL));
325 Py_DECREF(qname);
326 return ret;
327}
328
329static PyObject* PyUpb_Descriptor_GetExtensionRanges(PyObject* _self,
330 void* closure) {
331 PyUpb_DescriptorBase* self = (PyUpb_DescriptorBase*)_self;
332 int n = upb_MessageDef_ExtensionRangeCount(self->def);
333 PyObject* range_list = PyList_New(n);
334
335 for (int i = 0; i < n; i++) {
336 const upb_ExtensionRange* range =
337 upb_MessageDef_ExtensionRange(self->def, i);
338 PyObject* start = PyLong_FromLong(upb_ExtensionRange_Start(range));
339 PyObject* end = PyLong_FromLong(upb_ExtensionRange_End(range));
340 PyList_SetItem(range_list, i, PyTuple_Pack(2, start, end));
341 }
342
343 return range_list;
344}
345
346static PyObject* PyUpb_Descriptor_GetExtensions(PyObject* _self,
347 void* closure) {
348 PyUpb_DescriptorBase* self = (void*)_self;
349 static PyUpb_GenericSequence_Funcs funcs = {
350 (void*)&upb_MessageDef_NestedExtensionCount,
351 (void*)&upb_MessageDef_NestedExtension,
352 (void*)&PyUpb_FieldDescriptor_Get,
353 };
354 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
355}
356
357static PyObject* PyUpb_Descriptor_GetExtensionsByName(PyObject* _self,
358 void* closure) {
359 PyUpb_DescriptorBase* self = (void*)_self;
360 static PyUpb_ByNameMap_Funcs funcs = {
361 {
362 (void*)&upb_MessageDef_NestedExtensionCount,
363 (void*)&upb_MessageDef_NestedExtension,
364 (void*)&PyUpb_FieldDescriptor_Get,
365 },
366 (void*)&PyUpb_Descriptor_LookupNestedExtension,
367 (void*)&upb_FieldDef_Name,
368 };
369 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
370}
371
372static PyObject* PyUpb_Descriptor_GetEnumTypes(PyObject* _self, void* closure) {
373 PyUpb_DescriptorBase* self = (void*)_self;
374 static PyUpb_GenericSequence_Funcs funcs = {
375 (void*)&upb_MessageDef_NestedEnumCount,
376 (void*)&upb_MessageDef_NestedEnum,
377 (void*)&PyUpb_EnumDescriptor_Get,
378 };
379 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
380}
381
382static PyObject* PyUpb_Descriptor_GetOneofs(PyObject* _self, void* closure) {
383 PyUpb_DescriptorBase* self = (void*)_self;
384 static PyUpb_GenericSequence_Funcs funcs = {
385 (void*)&upb_MessageDef_OneofCount,
386 (void*)&upb_MessageDef_Oneof,
387 (void*)&PyUpb_OneofDescriptor_Get,
388 };
389 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
390}
391
392static PyObject* PyUpb_Descriptor_GetOptions(PyObject* _self, PyObject* args) {
393 PyUpb_DescriptorBase* self = (void*)_self;
394 return PyUpb_DescriptorBase_GetOptions(
Eric Salob997cb62023-12-21 08:09:54 -0800395 &self->options, UPB_UPCAST(upb_MessageDef_Options(self->def)),
Mike Kruskalc23d5332023-11-10 15:18:00 -0800396 &google__protobuf__MessageOptions_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700397 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".MessageOptions");
398}
399
Mike Kruskalc23d5332023-11-10 15:18:00 -0800400static PyObject* PyUpb_Descriptor_GetFeatures(PyObject* _self, PyObject* args) {
401 PyUpb_DescriptorBase* self = (void*)_self;
402 return PyUpb_DescriptorBase_GetFeatures(
Eric Salob997cb62023-12-21 08:09:54 -0800403 &self->features, UPB_UPCAST(upb_MessageDef_ResolvedFeatures(self->def)));
Mike Kruskalc23d5332023-11-10 15:18:00 -0800404}
405
Adam Cozzette501ecec2023-09-26 14:36:20 -0700406static PyObject* PyUpb_Descriptor_CopyToProto(PyObject* _self,
407 PyObject* py_proto) {
408 return PyUpb_DescriptorBase_CopyToProto(
409 _self, (PyUpb_ToProto_Func*)&upb_MessageDef_ToProto,
Eric Salo5b6543e2023-10-07 16:26:40 -0700410 &google__protobuf__DescriptorProto_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700411 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".DescriptorProto", py_proto);
412}
413
414static PyObject* PyUpb_Descriptor_EnumValueName(PyObject* _self,
415 PyObject* args) {
416 PyUpb_DescriptorBase* self = (void*)_self;
417 const char* enum_name;
418 int number;
419 if (!PyArg_ParseTuple(args, "si", &enum_name, &number)) return NULL;
420 const upb_EnumDef* e =
421 PyUpb_Descriptor_LookupNestedEnum(self->def, enum_name);
422 if (!e) {
423 PyErr_SetString(PyExc_KeyError, enum_name);
424 return NULL;
425 }
426 const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(e, number);
427 if (!ev) {
428 PyErr_Format(PyExc_KeyError, "%d", number);
429 return NULL;
430 }
431 return PyUnicode_FromString(upb_EnumValueDef_Name(ev));
432}
433
434static PyObject* PyUpb_Descriptor_GetFieldsByName(PyObject* _self,
435 void* closure) {
436 PyUpb_DescriptorBase* self = (void*)_self;
437 static PyUpb_ByNameMap_Funcs funcs = {
438 {
439 (void*)&upb_MessageDef_FieldCount,
440 (void*)&upb_MessageDef_Field,
441 (void*)&PyUpb_FieldDescriptor_Get,
442 },
443 (void*)&upb_MessageDef_FindFieldByName,
444 (void*)&upb_FieldDef_Name,
445 };
446 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
447}
448
449static PyObject* PyUpb_Descriptor_GetFieldsByCamelCaseName(PyObject* _self,
450 void* closure) {
451 PyUpb_DescriptorBase* self = (void*)_self;
452 static PyUpb_ByNameMap_Funcs funcs = {
453 {
454 (void*)&upb_MessageDef_FieldCount,
455 (void*)&upb_MessageDef_Field,
456 (void*)&PyUpb_FieldDescriptor_Get,
457 },
458 (void*)&upb_MessageDef_FindByJsonName,
459 (void*)&upb_FieldDef_JsonName,
460 };
461 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
462}
463
464static PyObject* PyUpb_Descriptor_GetFieldsByNumber(PyObject* _self,
465 void* closure) {
466 static PyUpb_ByNumberMap_Funcs funcs = {
467 {
468 (void*)&upb_MessageDef_FieldCount,
469 (void*)&upb_MessageDef_Field,
470 (void*)&PyUpb_FieldDescriptor_Get,
471 },
472 (void*)&upb_MessageDef_FindFieldByNumber,
473 (void*)&upb_FieldDef_Number,
474 };
475 PyUpb_DescriptorBase* self = (void*)_self;
476 return PyUpb_ByNumberMap_New(&funcs, self->def, self->pool);
477}
478
479static PyObject* PyUpb_Descriptor_GetNestedTypes(PyObject* _self,
480 void* closure) {
481 PyUpb_DescriptorBase* self = (void*)_self;
482 static PyUpb_GenericSequence_Funcs funcs = {
483 (void*)&upb_MessageDef_NestedMessageCount,
484 (void*)&upb_MessageDef_NestedMessage,
485 (void*)&PyUpb_Descriptor_Get,
486 };
487 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
488}
489
490static PyObject* PyUpb_Descriptor_GetNestedTypesByName(PyObject* _self,
491 void* closure) {
492 PyUpb_DescriptorBase* self = (void*)_self;
493 static PyUpb_ByNameMap_Funcs funcs = {
494 {
495 (void*)&upb_MessageDef_NestedMessageCount,
496 (void*)&upb_MessageDef_NestedMessage,
497 (void*)&PyUpb_Descriptor_Get,
498 },
499 (void*)&PyUpb_Descriptor_LookupNestedMessage,
500 (void*)&upb_MessageDef_Name,
501 };
502 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
503}
504
505static PyObject* PyUpb_Descriptor_GetContainingType(PyObject* _self,
506 void* closure) {
507 // upb does not natively store the lexical parent of a message type, but we
508 // can derive it with some string manipulation and a lookup.
509 PyUpb_DescriptorBase* self = (void*)_self;
510 const upb_MessageDef* m = self->def;
511 const upb_FileDef* file = upb_MessageDef_File(m);
512 const upb_DefPool* symtab = upb_FileDef_Pool(file);
513 const char* full_name = upb_MessageDef_FullName(m);
514 const char* last_dot = strrchr(full_name, '.');
515 if (!last_dot) Py_RETURN_NONE;
516 const upb_MessageDef* parent = upb_DefPool_FindMessageByNameWithSize(
517 symtab, full_name, last_dot - full_name);
518 if (!parent) Py_RETURN_NONE;
519 return PyUpb_Descriptor_Get(parent);
520}
521
522static PyObject* PyUpb_Descriptor_GetEnumTypesByName(PyObject* _self,
523 void* closure) {
524 PyUpb_DescriptorBase* self = (void*)_self;
525 static PyUpb_ByNameMap_Funcs funcs = {
526 {
527 (void*)&upb_MessageDef_NestedEnumCount,
528 (void*)&upb_MessageDef_NestedEnum,
529 (void*)&PyUpb_EnumDescriptor_Get,
530 },
531 (void*)&PyUpb_Descriptor_LookupNestedEnum,
532 (void*)&upb_EnumDef_Name,
533 };
534 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
535}
536
537static PyObject* PyUpb_Descriptor_GetIsExtendable(PyObject* _self,
538 void* closure) {
539 PyUpb_DescriptorBase* self = (void*)_self;
540 if (upb_MessageDef_ExtensionRangeCount(self->def) > 0) {
541 Py_RETURN_TRUE;
542 } else {
543 Py_RETURN_FALSE;
544 }
545}
546
547static PyObject* PyUpb_Descriptor_GetFullName(PyObject* self, void* closure) {
548 const upb_MessageDef* msgdef = PyUpb_Descriptor_GetDef(self);
549 return PyUnicode_FromString(upb_MessageDef_FullName(msgdef));
550}
551
552static PyObject* PyUpb_Descriptor_GetConcreteClass(PyObject* self,
553 void* closure) {
554 const upb_MessageDef* msgdef = PyUpb_Descriptor_GetDef(self);
555 return PyUpb_ObjCache_Get(upb_MessageDef_MiniTable(msgdef));
556}
557
558static PyObject* PyUpb_Descriptor_GetFile(PyObject* self, void* closure) {
559 const upb_MessageDef* msgdef = PyUpb_Descriptor_GetDef(self);
560 return PyUpb_FileDescriptor_Get(upb_MessageDef_File(msgdef));
561}
562
563static PyObject* PyUpb_Descriptor_GetFields(PyObject* _self, void* closure) {
564 PyUpb_DescriptorBase* self = (void*)_self;
565 static PyUpb_GenericSequence_Funcs funcs = {
566 (void*)&upb_MessageDef_FieldCount,
567 (void*)&upb_MessageDef_Field,
568 (void*)&PyUpb_FieldDescriptor_Get,
569 };
570 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
571}
572
573static PyObject* PyUpb_Descriptor_GetHasOptions(PyObject* _self,
574 void* closure) {
575 PyUpb_DescriptorBase* self = (void*)_self;
576 return PyBool_FromLong(upb_MessageDef_HasOptions(self->def));
577}
578
579static PyObject* PyUpb_Descriptor_GetName(PyObject* self, void* closure) {
580 const upb_MessageDef* msgdef = PyUpb_Descriptor_GetDef(self);
581 return PyUnicode_FromString(upb_MessageDef_Name(msgdef));
582}
583
584static PyObject* PyUpb_Descriptor_GetEnumValuesByName(PyObject* _self,
585 void* closure) {
586 // upb does not natively store any table containing all nested values.
587 // Consider:
588 // message M {
589 // enum E1 {
590 // A = 0;
591 // B = 1;
592 // }
593 // enum E2 {
594 // C = 0;
595 // D = 1;
596 // }
597 // }
598 //
599 // In this case, upb stores tables for E1 and E2, but it does not store a
600 // table for M that combines them (it is rarely needed and costs precious
601 // space and time to build).
602 //
603 // To work around this, we build an actual Python dict whenever a user
604 // actually asks for this.
605 PyUpb_DescriptorBase* self = (void*)_self;
606 PyObject* ret = PyDict_New();
607 if (!ret) return NULL;
608 int enum_count = upb_MessageDef_NestedEnumCount(self->def);
609 for (int i = 0; i < enum_count; i++) {
610 const upb_EnumDef* e = upb_MessageDef_NestedEnum(self->def, i);
611 int value_count = upb_EnumDef_ValueCount(e);
612 for (int j = 0; j < value_count; j++) {
613 // Collisions should be impossible here, as uniqueness is checked by
614 // protoc (this is an invariant of the protobuf language). However this
615 // uniqueness constraint is not currently checked by upb/def.c at load
616 // time, so if the user supplies a manually-constructed descriptor that
617 // does not respect this constraint, a collision could be possible and the
618 // last-defined enumerator would win. This could be seen as an argument
619 // for having upb actually build the table at load time, thus checking the
620 // constraint proactively, but upb is always checking a subset of the full
621 // validation performed by C++, and we have to pick and choose the biggest
622 // bang for the buck.
623 const upb_EnumValueDef* ev = upb_EnumDef_Value(e, j);
624 const char* name = upb_EnumValueDef_Name(ev);
625 PyObject* val = PyUpb_EnumValueDescriptor_Get(ev);
626 if (!val || PyDict_SetItemString(ret, name, val) < 0) {
627 Py_XDECREF(val);
628 Py_DECREF(ret);
629 return NULL;
630 }
631 Py_DECREF(val);
632 }
633 }
634 return ret;
635}
636
637static PyObject* PyUpb_Descriptor_GetOneofsByName(PyObject* _self,
638 void* closure) {
639 PyUpb_DescriptorBase* self = (void*)_self;
640 static PyUpb_ByNameMap_Funcs funcs = {
641 {
642 (void*)&upb_MessageDef_OneofCount,
643 (void*)&upb_MessageDef_Oneof,
644 (void*)&PyUpb_OneofDescriptor_Get,
645 },
646 (void*)&upb_MessageDef_FindOneofByName,
647 (void*)&upb_OneofDef_Name,
648 };
649 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
650}
651
Adam Cozzette501ecec2023-09-26 14:36:20 -0700652static PyGetSetDef PyUpb_Descriptor_Getters[] = {
653 {"name", PyUpb_Descriptor_GetName, NULL, "Last name"},
654 {"full_name", PyUpb_Descriptor_GetFullName, NULL, "Full name"},
655 {"_concrete_class", PyUpb_Descriptor_GetConcreteClass, NULL,
656 "concrete class"},
657 {"file", PyUpb_Descriptor_GetFile, NULL, "File descriptor"},
658 {"fields", PyUpb_Descriptor_GetFields, NULL, "Fields sequence"},
659 {"fields_by_name", PyUpb_Descriptor_GetFieldsByName, NULL,
660 "Fields by name"},
661 {"fields_by_camelcase_name", PyUpb_Descriptor_GetFieldsByCamelCaseName,
662 NULL, "Fields by camelCase name"},
663 {"fields_by_number", PyUpb_Descriptor_GetFieldsByNumber, NULL,
664 "Fields by number"},
665 {"nested_types", PyUpb_Descriptor_GetNestedTypes, NULL,
666 "Nested types sequence"},
667 {"nested_types_by_name", PyUpb_Descriptor_GetNestedTypesByName, NULL,
668 "Nested types by name"},
669 {"extensions", PyUpb_Descriptor_GetExtensions, NULL, "Extensions Sequence"},
670 {"extensions_by_name", PyUpb_Descriptor_GetExtensionsByName, NULL,
671 "Extensions by name"},
672 {"extension_ranges", PyUpb_Descriptor_GetExtensionRanges, NULL,
673 "Extension ranges"},
674 {"enum_types", PyUpb_Descriptor_GetEnumTypes, NULL, "Enum sequence"},
675 {"enum_types_by_name", PyUpb_Descriptor_GetEnumTypesByName, NULL,
676 "Enum types by name"},
677 {"enum_values_by_name", PyUpb_Descriptor_GetEnumValuesByName, NULL,
678 "Enum values by name"},
679 {"oneofs_by_name", PyUpb_Descriptor_GetOneofsByName, NULL,
680 "Oneofs by name"},
681 {"oneofs", PyUpb_Descriptor_GetOneofs, NULL, "Oneofs Sequence"},
682 {"containing_type", PyUpb_Descriptor_GetContainingType, NULL,
683 "Containing type"},
684 {"is_extendable", PyUpb_Descriptor_GetIsExtendable, NULL},
685 {"has_options", PyUpb_Descriptor_GetHasOptions, NULL, "Has Options"},
Adam Cozzette501ecec2023-09-26 14:36:20 -0700686 {NULL}};
687
688static PyMethodDef PyUpb_Descriptor_Methods[] = {
689 {"GetOptions", PyUpb_Descriptor_GetOptions, METH_NOARGS},
Mike Kruskalc23d5332023-11-10 15:18:00 -0800690 {"_GetFeatures", PyUpb_Descriptor_GetFeatures, METH_NOARGS},
Adam Cozzette501ecec2023-09-26 14:36:20 -0700691 {"CopyToProto", PyUpb_Descriptor_CopyToProto, METH_O},
692 {"EnumValueName", PyUpb_Descriptor_EnumValueName, METH_VARARGS},
693 {NULL}};
694
695static PyType_Slot PyUpb_Descriptor_Slots[] = {
696 DESCRIPTOR_BASE_SLOTS,
697 {Py_tp_methods, PyUpb_Descriptor_Methods},
698 {Py_tp_getset, PyUpb_Descriptor_Getters},
699 {Py_tp_traverse, PyUpb_Descriptor_Traverse},
700 {Py_tp_clear, PyUpb_Descriptor_Clear},
701 {0, NULL}};
702
703static PyType_Spec PyUpb_Descriptor_Spec = {
Eric Salob997cb62023-12-21 08:09:54 -0800704 PYUPB_MODULE_NAME ".Descriptor", // tp_name
705 sizeof(PyUpb_DescriptorBase), // tp_basicsize
706 0, // tp_itemsize
707 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
Adam Cozzette501ecec2023-09-26 14:36:20 -0700708 PyUpb_Descriptor_Slots,
709};
710
711const upb_MessageDef* PyUpb_Descriptor_GetDef(PyObject* _self) {
712 PyUpb_DescriptorBase* self =
713 PyUpb_DescriptorBase_Check(_self, kPyUpb_Descriptor);
714 return self ? self->def : NULL;
715}
716
717// -----------------------------------------------------------------------------
718// EnumDescriptor
719// -----------------------------------------------------------------------------
720
721PyObject* PyUpb_EnumDescriptor_Get(const upb_EnumDef* enumdef) {
722 const upb_FileDef* file = upb_EnumDef_File(enumdef);
723 return PyUpb_DescriptorBase_Get(kPyUpb_EnumDescriptor, enumdef, file);
724}
725
726const upb_EnumDef* PyUpb_EnumDescriptor_GetDef(PyObject* _self) {
727 PyUpb_DescriptorBase* self =
728 PyUpb_DescriptorBase_Check(_self, kPyUpb_EnumDescriptor);
729 return self ? self->def : NULL;
730}
731
732static PyObject* PyUpb_EnumDescriptor_GetFullName(PyObject* self,
733 void* closure) {
734 const upb_EnumDef* enumdef = PyUpb_EnumDescriptor_GetDef(self);
735 return PyUnicode_FromString(upb_EnumDef_FullName(enumdef));
736}
737
738static PyObject* PyUpb_EnumDescriptor_GetName(PyObject* self, void* closure) {
739 const upb_EnumDef* enumdef = PyUpb_EnumDescriptor_GetDef(self);
740 return PyUnicode_FromString(upb_EnumDef_Name(enumdef));
741}
742
743static PyObject* PyUpb_EnumDescriptor_GetFile(PyObject* self, void* closure) {
744 const upb_EnumDef* enumdef = PyUpb_EnumDescriptor_GetDef(self);
745 return PyUpb_FileDescriptor_Get(upb_EnumDef_File(enumdef));
746}
747
748static PyObject* PyUpb_EnumDescriptor_GetValues(PyObject* _self,
749 void* closure) {
750 PyUpb_DescriptorBase* self = (void*)_self;
751 static PyUpb_GenericSequence_Funcs funcs = {
752 (void*)&upb_EnumDef_ValueCount,
753 (void*)&upb_EnumDef_Value,
754 (void*)&PyUpb_EnumValueDescriptor_Get,
755 };
756 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
757}
758
759static PyObject* PyUpb_EnumDescriptor_GetValuesByName(PyObject* _self,
760 void* closure) {
761 static PyUpb_ByNameMap_Funcs funcs = {
762 {
763 (void*)&upb_EnumDef_ValueCount,
764 (void*)&upb_EnumDef_Value,
765 (void*)&PyUpb_EnumValueDescriptor_Get,
766 },
767 (void*)&upb_EnumDef_FindValueByName,
768 (void*)&upb_EnumValueDef_Name,
769 };
770 PyUpb_DescriptorBase* self = (void*)_self;
771 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
772}
773
774static PyObject* PyUpb_EnumDescriptor_GetValuesByNumber(PyObject* _self,
775 void* closure) {
776 static PyUpb_ByNumberMap_Funcs funcs = {
777 {
778 (void*)&upb_EnumDef_ValueCount,
779 (void*)&upb_EnumDef_Value,
780 (void*)&PyUpb_EnumValueDescriptor_Get,
781 },
782 (void*)&upb_EnumDef_FindValueByNumber,
783 (void*)&upb_EnumValueDef_Number,
784 };
785 PyUpb_DescriptorBase* self = (void*)_self;
786 return PyUpb_ByNumberMap_New(&funcs, self->def, self->pool);
787}
788
789static PyObject* PyUpb_EnumDescriptor_GetContainingType(PyObject* _self,
790 void* closure) {
791 PyUpb_DescriptorBase* self = (void*)_self;
792 const upb_MessageDef* m = upb_EnumDef_ContainingType(self->def);
793 if (!m) Py_RETURN_NONE;
794 return PyUpb_Descriptor_Get(m);
795}
796
797static PyObject* PyUpb_EnumDescriptor_GetHasOptions(PyObject* _self,
798 void* closure) {
799 PyUpb_DescriptorBase* self = (void*)_self;
800 return PyBool_FromLong(upb_EnumDef_HasOptions(self->def));
801}
802
803static PyObject* PyUpb_EnumDescriptor_GetIsClosed(PyObject* _self,
804 void* closure) {
805 const upb_EnumDef* enumdef = PyUpb_EnumDescriptor_GetDef(_self);
806 return PyBool_FromLong(upb_EnumDef_IsClosed(enumdef));
807}
808
809static PyObject* PyUpb_EnumDescriptor_GetOptions(PyObject* _self,
810 PyObject* args) {
811 PyUpb_DescriptorBase* self = (void*)_self;
812 return PyUpb_DescriptorBase_GetOptions(
Eric Salob997cb62023-12-21 08:09:54 -0800813 &self->options, UPB_UPCAST(upb_EnumDef_Options(self->def)),
Mike Kruskalc23d5332023-11-10 15:18:00 -0800814 &google__protobuf__EnumOptions_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700815 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".EnumOptions");
816}
817
Mike Kruskalc23d5332023-11-10 15:18:00 -0800818static PyObject* PyUpb_EnumDescriptor_GetFeatures(PyObject* _self,
819 PyObject* args) {
820 PyUpb_DescriptorBase* self = (void*)_self;
821 return PyUpb_DescriptorBase_GetFeatures(
Eric Salob997cb62023-12-21 08:09:54 -0800822 &self->features, UPB_UPCAST(upb_EnumDef_ResolvedFeatures(self->def)));
Mike Kruskalc23d5332023-11-10 15:18:00 -0800823}
824
Adam Cozzette501ecec2023-09-26 14:36:20 -0700825static PyObject* PyUpb_EnumDescriptor_CopyToProto(PyObject* _self,
826 PyObject* py_proto) {
827 return PyUpb_DescriptorBase_CopyToProto(
828 _self, (PyUpb_ToProto_Func*)&upb_EnumDef_ToProto,
Eric Salo5b6543e2023-10-07 16:26:40 -0700829 &google__protobuf__EnumDescriptorProto_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700830 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".EnumDescriptorProto", py_proto);
831}
832
833static PyGetSetDef PyUpb_EnumDescriptor_Getters[] = {
834 {"full_name", PyUpb_EnumDescriptor_GetFullName, NULL, "Full name"},
835 {"name", PyUpb_EnumDescriptor_GetName, NULL, "last name"},
836 {"file", PyUpb_EnumDescriptor_GetFile, NULL, "File descriptor"},
837 {"values", PyUpb_EnumDescriptor_GetValues, NULL, "values"},
838 {"values_by_name", PyUpb_EnumDescriptor_GetValuesByName, NULL,
839 "Enum values by name"},
840 {"values_by_number", PyUpb_EnumDescriptor_GetValuesByNumber, NULL,
841 "Enum values by number"},
842 {"containing_type", PyUpb_EnumDescriptor_GetContainingType, NULL,
843 "Containing type"},
844 {"has_options", PyUpb_EnumDescriptor_GetHasOptions, NULL, "Has Options"},
845 {"is_closed", PyUpb_EnumDescriptor_GetIsClosed, NULL,
846 "Checks if the enum is closed"},
847 {NULL}};
848
849static PyMethodDef PyUpb_EnumDescriptor_Methods[] = {
850 {"GetOptions", PyUpb_EnumDescriptor_GetOptions, METH_NOARGS},
Mike Kruskalc23d5332023-11-10 15:18:00 -0800851 {"_GetFeatures", PyUpb_EnumDescriptor_GetFeatures, METH_NOARGS},
Adam Cozzette501ecec2023-09-26 14:36:20 -0700852 {"CopyToProto", PyUpb_EnumDescriptor_CopyToProto, METH_O},
853 {NULL}};
854
855static PyType_Slot PyUpb_EnumDescriptor_Slots[] = {
856 DESCRIPTOR_BASE_SLOTS,
857 {Py_tp_methods, PyUpb_EnumDescriptor_Methods},
858 {Py_tp_getset, PyUpb_EnumDescriptor_Getters},
859 {0, NULL}};
860
861static PyType_Spec PyUpb_EnumDescriptor_Spec = {
862 PYUPB_MODULE_NAME ".EnumDescriptor", // tp_name
863 sizeof(PyUpb_DescriptorBase), // tp_basicsize
864 0, // tp_itemsize
865 Py_TPFLAGS_DEFAULT, // tp_flags
866 PyUpb_EnumDescriptor_Slots,
867};
868
869// -----------------------------------------------------------------------------
870// EnumValueDescriptor
871// -----------------------------------------------------------------------------
872
873PyObject* PyUpb_EnumValueDescriptor_Get(const upb_EnumValueDef* ev) {
874 const upb_FileDef* file = upb_EnumDef_File(upb_EnumValueDef_Enum(ev));
875 return PyUpb_DescriptorBase_Get(kPyUpb_EnumValueDescriptor, ev, file);
876}
877
878static PyObject* PyUpb_EnumValueDescriptor_GetName(PyObject* self,
879 void* closure) {
880 PyUpb_DescriptorBase* base = (PyUpb_DescriptorBase*)self;
881 return PyUnicode_FromString(upb_EnumValueDef_Name(base->def));
882}
883
884static PyObject* PyUpb_EnumValueDescriptor_GetNumber(PyObject* self,
885 void* closure) {
886 PyUpb_DescriptorBase* base = (PyUpb_DescriptorBase*)self;
887 return PyLong_FromLong(upb_EnumValueDef_Number(base->def));
888}
889
890static PyObject* PyUpb_EnumValueDescriptor_GetIndex(PyObject* self,
891 void* closure) {
892 PyUpb_DescriptorBase* base = (PyUpb_DescriptorBase*)self;
893 return PyLong_FromLong(upb_EnumValueDef_Index(base->def));
894}
895
896static PyObject* PyUpb_EnumValueDescriptor_GetType(PyObject* self,
897 void* closure) {
898 PyUpb_DescriptorBase* base = (PyUpb_DescriptorBase*)self;
899 return PyUpb_EnumDescriptor_Get(upb_EnumValueDef_Enum(base->def));
900}
901
902static PyObject* PyUpb_EnumValueDescriptor_GetHasOptions(PyObject* _self,
903 void* closure) {
904 PyUpb_DescriptorBase* self = (void*)_self;
905 return PyBool_FromLong(upb_EnumValueDef_HasOptions(self->def));
906}
907
908static PyObject* PyUpb_EnumValueDescriptor_GetOptions(PyObject* _self,
909 PyObject* args) {
910 PyUpb_DescriptorBase* self = (void*)_self;
911 return PyUpb_DescriptorBase_GetOptions(
Eric Salob997cb62023-12-21 08:09:54 -0800912 &self->options, UPB_UPCAST(upb_EnumValueDef_Options(self->def)),
Eric Salo5b6543e2023-10-07 16:26:40 -0700913 &google__protobuf__EnumValueOptions_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -0700914 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".EnumValueOptions");
915}
916
Mike Kruskalc23d5332023-11-10 15:18:00 -0800917static PyObject* PyUpb_EnumValueDescriptor_GetFeatures(PyObject* _self,
918 PyObject* args) {
919 PyUpb_DescriptorBase* self = (void*)_self;
920 return PyUpb_DescriptorBase_GetFeatures(
Eric Salob997cb62023-12-21 08:09:54 -0800921 &self->features,
922 UPB_UPCAST(upb_EnumValueDef_ResolvedFeatures(self->def)));
Mike Kruskalc23d5332023-11-10 15:18:00 -0800923}
924
Adam Cozzette501ecec2023-09-26 14:36:20 -0700925static PyGetSetDef PyUpb_EnumValueDescriptor_Getters[] = {
926 {"name", PyUpb_EnumValueDescriptor_GetName, NULL, "name"},
927 {"number", PyUpb_EnumValueDescriptor_GetNumber, NULL, "number"},
928 {"index", PyUpb_EnumValueDescriptor_GetIndex, NULL, "index"},
929 {"type", PyUpb_EnumValueDescriptor_GetType, NULL, "index"},
930 {"has_options", PyUpb_EnumValueDescriptor_GetHasOptions, NULL,
931 "Has Options"},
932 {NULL}};
933
934static PyMethodDef PyUpb_EnumValueDescriptor_Methods[] = {
935 {
936 "GetOptions",
937 PyUpb_EnumValueDescriptor_GetOptions,
938 METH_NOARGS,
939 },
Mike Kruskalc23d5332023-11-10 15:18:00 -0800940 {
941 "_GetFeatures",
942 PyUpb_EnumValueDescriptor_GetFeatures,
943 METH_NOARGS,
944 },
Adam Cozzette501ecec2023-09-26 14:36:20 -0700945 {NULL}};
946
947static PyType_Slot PyUpb_EnumValueDescriptor_Slots[] = {
948 DESCRIPTOR_BASE_SLOTS,
949 {Py_tp_methods, PyUpb_EnumValueDescriptor_Methods},
950 {Py_tp_getset, PyUpb_EnumValueDescriptor_Getters},
951 {0, NULL}};
952
953static PyType_Spec PyUpb_EnumValueDescriptor_Spec = {
954 PYUPB_MODULE_NAME ".EnumValueDescriptor", // tp_name
955 sizeof(PyUpb_DescriptorBase), // tp_basicsize
956 0, // tp_itemsize
957 Py_TPFLAGS_DEFAULT, // tp_flags
958 PyUpb_EnumValueDescriptor_Slots,
959};
960
961// -----------------------------------------------------------------------------
962// FieldDescriptor
963// -----------------------------------------------------------------------------
964
965const upb_FieldDef* PyUpb_FieldDescriptor_GetDef(PyObject* _self) {
966 PyUpb_DescriptorBase* self =
967 PyUpb_DescriptorBase_Check(_self, kPyUpb_FieldDescriptor);
968 return self ? self->def : NULL;
969}
970
971PyObject* PyUpb_FieldDescriptor_Get(const upb_FieldDef* field) {
972 const upb_FileDef* file = upb_FieldDef_File(field);
973 return PyUpb_DescriptorBase_Get(kPyUpb_FieldDescriptor, field, file);
974}
975
976static PyObject* PyUpb_FieldDescriptor_GetFullName(PyUpb_DescriptorBase* self,
977 void* closure) {
978 return PyUnicode_FromString(upb_FieldDef_FullName(self->def));
979}
980
981static PyObject* PyUpb_FieldDescriptor_GetName(PyUpb_DescriptorBase* self,
982 void* closure) {
983 return PyUnicode_FromString(upb_FieldDef_Name(self->def));
984}
985
Mike Kruskal9a020c42024-01-31 14:20:03 -0800986static char PyUpb_AsciiIsUpper(char ch) { return ch >= 'A' && ch <= 'Z'; }
987
988static char PyUpb_AsciiToLower(char ch) {
989 assert(PyUpb_AsciiIsUpper(ch));
990 return ch + ('a' - 'A');
991}
992
Adam Cozzette501ecec2023-09-26 14:36:20 -0700993static PyObject* PyUpb_FieldDescriptor_GetCamelCaseName(
994 PyUpb_DescriptorBase* self, void* closure) {
Mike Kruskal9a020c42024-01-31 14:20:03 -0800995 // Camelcase is equivalent to JSON name except for potentially the first
996 // character.
997 const char* name = upb_FieldDef_JsonName(self->def);
998 size_t size = strlen(name);
999 return size > 0 && PyUpb_AsciiIsUpper(name[0])
1000 ? PyUnicode_FromFormat("%c%s", PyUpb_AsciiToLower(name[0]),
1001 name + 1)
1002 : PyUnicode_FromStringAndSize(name, size);
Adam Cozzette501ecec2023-09-26 14:36:20 -07001003}
1004
1005static PyObject* PyUpb_FieldDescriptor_GetJsonName(PyUpb_DescriptorBase* self,
1006 void* closure) {
1007 return PyUnicode_FromString(upb_FieldDef_JsonName(self->def));
1008}
1009
1010static PyObject* PyUpb_FieldDescriptor_GetFile(PyUpb_DescriptorBase* self,
1011 void* closure) {
1012 const upb_FileDef* file = upb_FieldDef_File(self->def);
1013 if (!file) Py_RETURN_NONE;
1014 return PyUpb_FileDescriptor_Get(file);
1015}
1016
1017static PyObject* PyUpb_FieldDescriptor_GetType(PyUpb_DescriptorBase* self,
1018 void* closure) {
1019 return PyLong_FromLong(upb_FieldDef_Type(self->def));
1020}
1021
1022// Enum values copied from descriptor.h in C++.
1023enum CppType {
1024 CPPTYPE_INT32 = 1, // TYPE_INT32, TYPE_SINT32, TYPE_SFIXED32
1025 CPPTYPE_INT64 = 2, // TYPE_INT64, TYPE_SINT64, TYPE_SFIXED64
1026 CPPTYPE_UINT32 = 3, // TYPE_UINT32, TYPE_FIXED32
1027 CPPTYPE_UINT64 = 4, // TYPE_UINT64, TYPE_FIXED64
1028 CPPTYPE_DOUBLE = 5, // TYPE_DOUBLE
1029 CPPTYPE_FLOAT = 6, // TYPE_FLOAT
1030 CPPTYPE_BOOL = 7, // TYPE_BOOL
1031 CPPTYPE_ENUM = 8, // TYPE_ENUM
1032 CPPTYPE_STRING = 9, // TYPE_STRING, TYPE_BYTES
1033 CPPTYPE_MESSAGE = 10, // TYPE_MESSAGE, TYPE_GROUP
1034};
1035
1036static PyObject* PyUpb_FieldDescriptor_GetCppType(PyUpb_DescriptorBase* self,
1037 void* closure) {
1038 static const uint8_t cpp_types[] = {
1039 -1,
1040 [kUpb_CType_Int32] = CPPTYPE_INT32,
1041 [kUpb_CType_Int64] = CPPTYPE_INT64,
1042 [kUpb_CType_UInt32] = CPPTYPE_UINT32,
1043 [kUpb_CType_UInt64] = CPPTYPE_UINT64,
1044 [kUpb_CType_Double] = CPPTYPE_DOUBLE,
1045 [kUpb_CType_Float] = CPPTYPE_FLOAT,
1046 [kUpb_CType_Bool] = CPPTYPE_BOOL,
1047 [kUpb_CType_Enum] = CPPTYPE_ENUM,
1048 [kUpb_CType_String] = CPPTYPE_STRING,
1049 [kUpb_CType_Bytes] = CPPTYPE_STRING,
1050 [kUpb_CType_Message] = CPPTYPE_MESSAGE,
1051 };
1052 return PyLong_FromLong(cpp_types[upb_FieldDef_CType(self->def)]);
1053}
1054
1055static PyObject* PyUpb_FieldDescriptor_GetLabel(PyUpb_DescriptorBase* self,
1056 void* closure) {
1057 return PyLong_FromLong(upb_FieldDef_Label(self->def));
1058}
1059
1060static PyObject* PyUpb_FieldDescriptor_GetIsExtension(
1061 PyUpb_DescriptorBase* self, void* closure) {
1062 return PyBool_FromLong(upb_FieldDef_IsExtension(self->def));
1063}
1064
1065static PyObject* PyUpb_FieldDescriptor_GetNumber(PyUpb_DescriptorBase* self,
1066 void* closure) {
1067 return PyLong_FromLong(upb_FieldDef_Number(self->def));
1068}
1069
1070static PyObject* PyUpb_FieldDescriptor_GetIndex(PyUpb_DescriptorBase* self,
1071 void* closure) {
1072 return PyLong_FromLong(upb_FieldDef_Index(self->def));
1073}
1074
1075static PyObject* PyUpb_FieldDescriptor_GetMessageType(
1076 PyUpb_DescriptorBase* self, void* closure) {
1077 const upb_MessageDef* subdef = upb_FieldDef_MessageSubDef(self->def);
1078 if (!subdef) Py_RETURN_NONE;
1079 return PyUpb_Descriptor_Get(subdef);
1080}
1081
1082static PyObject* PyUpb_FieldDescriptor_GetEnumType(PyUpb_DescriptorBase* self,
1083 void* closure) {
1084 const upb_EnumDef* enumdef = upb_FieldDef_EnumSubDef(self->def);
1085 if (!enumdef) Py_RETURN_NONE;
1086 return PyUpb_EnumDescriptor_Get(enumdef);
1087}
1088
1089static PyObject* PyUpb_FieldDescriptor_GetContainingType(
1090 PyUpb_DescriptorBase* self, void* closure) {
1091 const upb_MessageDef* m = upb_FieldDef_ContainingType(self->def);
1092 if (!m) Py_RETURN_NONE;
1093 return PyUpb_Descriptor_Get(m);
1094}
1095
1096static PyObject* PyUpb_FieldDescriptor_GetExtensionScope(
1097 PyUpb_DescriptorBase* self, void* closure) {
1098 const upb_MessageDef* m = upb_FieldDef_ExtensionScope(self->def);
1099 if (!m) Py_RETURN_NONE;
1100 return PyUpb_Descriptor_Get(m);
1101}
1102
1103static PyObject* PyUpb_FieldDescriptor_HasDefaultValue(
1104 PyUpb_DescriptorBase* self, void* closure) {
1105 return PyBool_FromLong(upb_FieldDef_HasDefault(self->def));
1106}
1107
1108static PyObject* PyUpb_FieldDescriptor_GetDefaultValue(
1109 PyUpb_DescriptorBase* self, void* closure) {
1110 const upb_FieldDef* f = self->def;
1111 if (upb_FieldDef_IsRepeated(f)) return PyList_New(0);
1112 if (upb_FieldDef_IsSubMessage(f)) Py_RETURN_NONE;
1113 return PyUpb_UpbToPy(upb_FieldDef_Default(self->def), self->def, NULL);
1114}
1115
1116static PyObject* PyUpb_FieldDescriptor_GetContainingOneof(
1117 PyUpb_DescriptorBase* self, void* closure) {
1118 const upb_OneofDef* oneof = upb_FieldDef_ContainingOneof(self->def);
1119 if (!oneof) Py_RETURN_NONE;
1120 return PyUpb_OneofDescriptor_Get(oneof);
1121}
1122
1123static PyObject* PyUpb_FieldDescriptor_GetHasOptions(
1124 PyUpb_DescriptorBase* _self, void* closure) {
1125 PyUpb_DescriptorBase* self = (void*)_self;
1126 return PyBool_FromLong(upb_FieldDef_HasOptions(self->def));
1127}
1128
1129static PyObject* PyUpb_FieldDescriptor_GetHasPresence(
1130 PyUpb_DescriptorBase* _self, void* closure) {
1131 PyUpb_DescriptorBase* self = (void*)_self;
1132 return PyBool_FromLong(upb_FieldDef_HasPresence(self->def));
1133}
1134
1135static PyObject* PyUpb_FieldDescriptor_GetOptions(PyObject* _self,
1136 PyObject* args) {
1137 PyUpb_DescriptorBase* self = (void*)_self;
1138 return PyUpb_DescriptorBase_GetOptions(
Eric Salob997cb62023-12-21 08:09:54 -08001139 &self->options, UPB_UPCAST(upb_FieldDef_Options(self->def)),
Mike Kruskalc23d5332023-11-10 15:18:00 -08001140 &google__protobuf__FieldOptions_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -07001141 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".FieldOptions");
1142}
1143
Mike Kruskalc23d5332023-11-10 15:18:00 -08001144static PyObject* PyUpb_FieldDescriptor_GetFeatures(PyObject* _self,
1145 PyObject* args) {
1146 PyUpb_DescriptorBase* self = (void*)_self;
1147 return PyUpb_DescriptorBase_GetFeatures(
Eric Salob997cb62023-12-21 08:09:54 -08001148 &self->features, UPB_UPCAST(upb_FieldDef_ResolvedFeatures(self->def)));
Mike Kruskalc23d5332023-11-10 15:18:00 -08001149}
1150
Adam Cozzette501ecec2023-09-26 14:36:20 -07001151static PyGetSetDef PyUpb_FieldDescriptor_Getters[] = {
1152 {"full_name", (getter)PyUpb_FieldDescriptor_GetFullName, NULL, "Full name"},
1153 {"name", (getter)PyUpb_FieldDescriptor_GetName, NULL, "Unqualified name"},
1154 {"camelcase_name", (getter)PyUpb_FieldDescriptor_GetCamelCaseName, NULL,
1155 "CamelCase name"},
1156 {"json_name", (getter)PyUpb_FieldDescriptor_GetJsonName, NULL, "Json name"},
1157 {"file", (getter)PyUpb_FieldDescriptor_GetFile, NULL, "File Descriptor"},
1158 {"type", (getter)PyUpb_FieldDescriptor_GetType, NULL, "Type"},
1159 {"cpp_type", (getter)PyUpb_FieldDescriptor_GetCppType, NULL, "C++ Type"},
1160 {"label", (getter)PyUpb_FieldDescriptor_GetLabel, NULL, "Label"},
1161 {"number", (getter)PyUpb_FieldDescriptor_GetNumber, NULL, "Number"},
1162 {"index", (getter)PyUpb_FieldDescriptor_GetIndex, NULL, "Index"},
1163 {"default_value", (getter)PyUpb_FieldDescriptor_GetDefaultValue, NULL,
1164 "Default Value"},
1165 {"has_default_value", (getter)PyUpb_FieldDescriptor_HasDefaultValue},
1166 {"is_extension", (getter)PyUpb_FieldDescriptor_GetIsExtension, NULL, "ID"},
1167 // TODO
1168 //{ "id", (getter)GetID, NULL, "ID"},
1169 {"message_type", (getter)PyUpb_FieldDescriptor_GetMessageType, NULL,
1170 "Message type"},
1171 {"enum_type", (getter)PyUpb_FieldDescriptor_GetEnumType, NULL, "Enum type"},
1172 {"containing_type", (getter)PyUpb_FieldDescriptor_GetContainingType, NULL,
1173 "Containing type"},
1174 {"extension_scope", (getter)PyUpb_FieldDescriptor_GetExtensionScope, NULL,
1175 "Extension scope"},
1176 {"containing_oneof", (getter)PyUpb_FieldDescriptor_GetContainingOneof, NULL,
1177 "Containing oneof"},
1178 {"has_options", (getter)PyUpb_FieldDescriptor_GetHasOptions, NULL,
1179 "Has Options"},
1180 {"has_presence", (getter)PyUpb_FieldDescriptor_GetHasPresence, NULL,
1181 "Has Presence"},
1182 // TODO
1183 //{ "_options",
1184 //(getter)NULL, (setter)SetOptions, "Options"}, { "_serialized_options",
1185 //(getter)NULL, (setter)SetSerializedOptions, "Serialized Options"},
1186 {NULL}};
1187
1188static PyMethodDef PyUpb_FieldDescriptor_Methods[] = {
1189 {
1190 "GetOptions",
1191 PyUpb_FieldDescriptor_GetOptions,
1192 METH_NOARGS,
1193 },
Mike Kruskalc23d5332023-11-10 15:18:00 -08001194 {
1195 "_GetFeatures",
1196 PyUpb_FieldDescriptor_GetFeatures,
1197 METH_NOARGS,
1198 },
Adam Cozzette501ecec2023-09-26 14:36:20 -07001199 {NULL}};
1200
1201static PyType_Slot PyUpb_FieldDescriptor_Slots[] = {
1202 DESCRIPTOR_BASE_SLOTS,
1203 {Py_tp_methods, PyUpb_FieldDescriptor_Methods},
1204 {Py_tp_getset, PyUpb_FieldDescriptor_Getters},
1205 {0, NULL}};
1206
1207static PyType_Spec PyUpb_FieldDescriptor_Spec = {
1208 PYUPB_MODULE_NAME ".FieldDescriptor",
1209 sizeof(PyUpb_DescriptorBase),
1210 0, // tp_itemsize
1211 Py_TPFLAGS_DEFAULT,
1212 PyUpb_FieldDescriptor_Slots,
1213};
1214
1215// -----------------------------------------------------------------------------
1216// FileDescriptor
1217// -----------------------------------------------------------------------------
1218
1219PyObject* PyUpb_FileDescriptor_Get(const upb_FileDef* file) {
1220 return PyUpb_DescriptorBase_Get(kPyUpb_FileDescriptor, file, file);
1221}
1222
1223// These are not provided on upb_FileDef because they use the underlying
1224// symtab's hash table. This works for Python because everything happens under
1225// the GIL, but in general the caller has to guarantee that the symtab is not
1226// being mutated concurrently.
1227typedef const void* PyUpb_FileDescriptor_LookupFunc(const upb_DefPool*,
1228 const char*);
1229
1230static const void* PyUpb_FileDescriptor_NestedLookup(
1231 const upb_FileDef* filedef, const char* name,
1232 PyUpb_FileDescriptor_LookupFunc* func) {
1233 const upb_DefPool* symtab = upb_FileDef_Pool(filedef);
1234 const char* package = upb_FileDef_Package(filedef);
1235 if (strlen(package)) {
1236 PyObject* qname = PyUnicode_FromFormat("%s.%s", package, name);
1237 const void* ret = func(symtab, PyUnicode_AsUTF8AndSize(qname, NULL));
1238 Py_DECREF(qname);
1239 return ret;
1240 } else {
1241 return func(symtab, name);
1242 }
1243}
1244
1245static const void* PyUpb_FileDescriptor_LookupMessage(
1246 const upb_FileDef* filedef, const char* name) {
Joshua Habermanc05b3202023-12-01 15:10:41 -08001247 const upb_MessageDef* m = PyUpb_FileDescriptor_NestedLookup(
Adam Cozzette501ecec2023-09-26 14:36:20 -07001248 filedef, name, (void*)&upb_DefPool_FindMessageByName);
Joshua Habermanc05b3202023-12-01 15:10:41 -08001249 if (!m) return NULL;
1250 return upb_MessageDef_File(m) == filedef ? m : NULL;
Adam Cozzette501ecec2023-09-26 14:36:20 -07001251}
1252
1253static const void* PyUpb_FileDescriptor_LookupEnum(const upb_FileDef* filedef,
1254 const char* name) {
Joshua Habermanc05b3202023-12-01 15:10:41 -08001255 const upb_EnumDef* e = PyUpb_FileDescriptor_NestedLookup(
1256 filedef, name, (void*)&upb_DefPool_FindEnumByName);
1257 if (!e) return NULL;
1258 return upb_EnumDef_File(e) == filedef ? e : NULL;
Adam Cozzette501ecec2023-09-26 14:36:20 -07001259}
1260
1261static const void* PyUpb_FileDescriptor_LookupExtension(
1262 const upb_FileDef* filedef, const char* name) {
Joshua Habermanc05b3202023-12-01 15:10:41 -08001263 const upb_FieldDef* f = PyUpb_FileDescriptor_NestedLookup(
Adam Cozzette501ecec2023-09-26 14:36:20 -07001264 filedef, name, (void*)&upb_DefPool_FindExtensionByName);
Joshua Habermanc05b3202023-12-01 15:10:41 -08001265 if (!f) return NULL;
1266 return upb_FieldDef_File(f) == filedef ? f : NULL;
Adam Cozzette501ecec2023-09-26 14:36:20 -07001267}
1268
1269static const void* PyUpb_FileDescriptor_LookupService(
1270 const upb_FileDef* filedef, const char* name) {
Joshua Habermanc05b3202023-12-01 15:10:41 -08001271 const upb_ServiceDef* s = PyUpb_FileDescriptor_NestedLookup(
Adam Cozzette501ecec2023-09-26 14:36:20 -07001272 filedef, name, (void*)&upb_DefPool_FindServiceByName);
Joshua Habermanc05b3202023-12-01 15:10:41 -08001273 if (!s) return NULL;
1274 return upb_ServiceDef_File(s) == filedef ? s : NULL;
Adam Cozzette501ecec2023-09-26 14:36:20 -07001275}
1276
1277static PyObject* PyUpb_FileDescriptor_GetName(PyUpb_DescriptorBase* self,
1278 void* closure) {
1279 return PyUnicode_FromString(upb_FileDef_Name(self->def));
1280}
1281
1282static PyObject* PyUpb_FileDescriptor_GetPool(PyObject* _self, void* closure) {
1283 PyUpb_DescriptorBase* self = (PyUpb_DescriptorBase*)_self;
1284 Py_INCREF(self->pool);
1285 return self->pool;
1286}
1287
1288static PyObject* PyUpb_FileDescriptor_GetPackage(PyObject* _self,
1289 void* closure) {
1290 PyUpb_DescriptorBase* self = (PyUpb_DescriptorBase*)_self;
1291 return PyUnicode_FromString(upb_FileDef_Package(self->def));
1292}
1293
1294static PyObject* PyUpb_FileDescriptor_GetSerializedPb(PyObject* self,
1295 void* closure) {
1296 return PyUpb_DescriptorBase_GetSerializedProto(
1297 self, (PyUpb_ToProto_Func*)&upb_FileDef_ToProto,
Eric Salo5b6543e2023-10-07 16:26:40 -07001298 &google__protobuf__FileDescriptorProto_msg_init);
Adam Cozzette501ecec2023-09-26 14:36:20 -07001299}
1300
1301static PyObject* PyUpb_FileDescriptor_GetMessageTypesByName(PyObject* _self,
1302 void* closure) {
1303 static PyUpb_ByNameMap_Funcs funcs = {
1304 {
1305 (void*)&upb_FileDef_TopLevelMessageCount,
1306 (void*)&upb_FileDef_TopLevelMessage,
1307 (void*)&PyUpb_Descriptor_Get,
1308 },
1309 (void*)&PyUpb_FileDescriptor_LookupMessage,
1310 (void*)&upb_MessageDef_Name,
1311 };
1312 PyUpb_DescriptorBase* self = (void*)_self;
1313 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
1314}
1315
1316static PyObject* PyUpb_FileDescriptor_GetEnumTypesByName(PyObject* _self,
1317 void* closure) {
1318 static PyUpb_ByNameMap_Funcs funcs = {
1319 {
1320 (void*)&upb_FileDef_TopLevelEnumCount,
1321 (void*)&upb_FileDef_TopLevelEnum,
1322 (void*)&PyUpb_EnumDescriptor_Get,
1323 },
1324 (void*)&PyUpb_FileDescriptor_LookupEnum,
1325 (void*)&upb_EnumDef_Name,
1326 };
1327 PyUpb_DescriptorBase* self = (void*)_self;
1328 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
1329}
1330
1331static PyObject* PyUpb_FileDescriptor_GetExtensionsByName(PyObject* _self,
1332 void* closure) {
1333 static PyUpb_ByNameMap_Funcs funcs = {
1334 {
1335 (void*)&upb_FileDef_TopLevelExtensionCount,
1336 (void*)&upb_FileDef_TopLevelExtension,
1337 (void*)&PyUpb_FieldDescriptor_Get,
1338 },
1339 (void*)&PyUpb_FileDescriptor_LookupExtension,
1340 (void*)&upb_FieldDef_Name,
1341 };
1342 PyUpb_DescriptorBase* self = (void*)_self;
1343 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
1344}
1345
1346static PyObject* PyUpb_FileDescriptor_GetServicesByName(PyObject* _self,
1347 void* closure) {
1348 static PyUpb_ByNameMap_Funcs funcs = {
1349 {
1350 (void*)&upb_FileDef_ServiceCount,
1351 (void*)&upb_FileDef_Service,
1352 (void*)&PyUpb_ServiceDescriptor_Get,
1353 },
1354 (void*)&PyUpb_FileDescriptor_LookupService,
1355 (void*)&upb_ServiceDef_Name,
1356 };
1357 PyUpb_DescriptorBase* self = (void*)_self;
1358 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
1359}
1360
1361static PyObject* PyUpb_FileDescriptor_GetDependencies(PyObject* _self,
1362 void* closure) {
1363 PyUpb_DescriptorBase* self = (void*)_self;
1364 static PyUpb_GenericSequence_Funcs funcs = {
1365 (void*)&upb_FileDef_DependencyCount,
1366 (void*)&upb_FileDef_Dependency,
1367 (void*)&PyUpb_FileDescriptor_Get,
1368 };
1369 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
1370}
1371
1372static PyObject* PyUpb_FileDescriptor_GetPublicDependencies(PyObject* _self,
1373 void* closure) {
1374 PyUpb_DescriptorBase* self = (void*)_self;
1375 static PyUpb_GenericSequence_Funcs funcs = {
1376 (void*)&upb_FileDef_PublicDependencyCount,
1377 (void*)&upb_FileDef_PublicDependency,
1378 (void*)&PyUpb_FileDescriptor_Get,
1379 };
1380 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
1381}
1382
Adam Cozzette501ecec2023-09-26 14:36:20 -07001383static PyObject* PyUpb_FileDescriptor_GetHasOptions(PyObject* _self,
1384 void* closure) {
1385 PyUpb_DescriptorBase* self = (void*)_self;
1386 return PyBool_FromLong(upb_FileDef_HasOptions(self->def));
1387}
1388
1389static PyObject* PyUpb_FileDescriptor_GetOptions(PyObject* _self,
1390 PyObject* args) {
1391 PyUpb_DescriptorBase* self = (void*)_self;
1392 return PyUpb_DescriptorBase_GetOptions(
Eric Salob997cb62023-12-21 08:09:54 -08001393 &self->options, UPB_UPCAST(upb_FileDef_Options(self->def)),
Mike Kruskalc23d5332023-11-10 15:18:00 -08001394 &google__protobuf__FileOptions_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -07001395 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".FileOptions");
1396}
1397
Mike Kruskalc23d5332023-11-10 15:18:00 -08001398static PyObject* PyUpb_FileDescriptor_GetFeatures(PyObject* _self,
1399 PyObject* args) {
1400 PyUpb_DescriptorBase* self = (void*)_self;
1401 return PyUpb_DescriptorBase_GetFeatures(
Eric Salob997cb62023-12-21 08:09:54 -08001402 &self->features, UPB_UPCAST(upb_FileDef_ResolvedFeatures(self->def)));
Mike Kruskalc23d5332023-11-10 15:18:00 -08001403}
1404
Adam Cozzette501ecec2023-09-26 14:36:20 -07001405static PyObject* PyUpb_FileDescriptor_CopyToProto(PyObject* _self,
1406 PyObject* py_proto) {
1407 return PyUpb_DescriptorBase_CopyToProto(
1408 _self, (PyUpb_ToProto_Func*)&upb_FileDef_ToProto,
Eric Salo5b6543e2023-10-07 16:26:40 -07001409 &google__protobuf__FileDescriptorProto_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -07001410 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".FileDescriptorProto", py_proto);
1411}
1412
1413static PyGetSetDef PyUpb_FileDescriptor_Getters[] = {
1414 {"pool", PyUpb_FileDescriptor_GetPool, NULL, "pool"},
1415 {"name", (getter)PyUpb_FileDescriptor_GetName, NULL, "name"},
1416 {"package", PyUpb_FileDescriptor_GetPackage, NULL, "package"},
1417 {"serialized_pb", PyUpb_FileDescriptor_GetSerializedPb},
1418 {"message_types_by_name", PyUpb_FileDescriptor_GetMessageTypesByName, NULL,
1419 "Messages by name"},
1420 {"enum_types_by_name", PyUpb_FileDescriptor_GetEnumTypesByName, NULL,
1421 "Enums by name"},
1422 {"extensions_by_name", PyUpb_FileDescriptor_GetExtensionsByName, NULL,
1423 "Extensions by name"},
1424 {"services_by_name", PyUpb_FileDescriptor_GetServicesByName, NULL,
1425 "Services by name"},
1426 {"dependencies", PyUpb_FileDescriptor_GetDependencies, NULL,
1427 "Dependencies"},
1428 {"public_dependencies", PyUpb_FileDescriptor_GetPublicDependencies, NULL,
1429 "Dependencies"},
1430 {"has_options", PyUpb_FileDescriptor_GetHasOptions, NULL, "Has Options"},
Adam Cozzette501ecec2023-09-26 14:36:20 -07001431 {NULL},
1432};
1433
1434static PyMethodDef PyUpb_FileDescriptor_Methods[] = {
1435 {"GetOptions", PyUpb_FileDescriptor_GetOptions, METH_NOARGS},
Mike Kruskalc23d5332023-11-10 15:18:00 -08001436 {"_GetFeatures", PyUpb_FileDescriptor_GetFeatures, METH_NOARGS},
Adam Cozzette501ecec2023-09-26 14:36:20 -07001437 {"CopyToProto", PyUpb_FileDescriptor_CopyToProto, METH_O},
1438 {NULL}};
1439
1440static PyType_Slot PyUpb_FileDescriptor_Slots[] = {
1441 DESCRIPTOR_BASE_SLOTS,
1442 {Py_tp_methods, PyUpb_FileDescriptor_Methods},
1443 {Py_tp_getset, PyUpb_FileDescriptor_Getters},
1444 {0, NULL}};
1445
1446static PyType_Spec PyUpb_FileDescriptor_Spec = {
1447 PYUPB_MODULE_NAME ".FileDescriptor", // tp_name
1448 sizeof(PyUpb_DescriptorBase), // tp_basicsize
1449 0, // tp_itemsize
1450 Py_TPFLAGS_DEFAULT, // tp_flags
1451 PyUpb_FileDescriptor_Slots,
1452};
1453
1454const upb_FileDef* PyUpb_FileDescriptor_GetDef(PyObject* _self) {
1455 PyUpb_DescriptorBase* self =
1456 PyUpb_DescriptorBase_Check(_self, kPyUpb_FileDescriptor);
1457 return self ? self->def : NULL;
1458}
1459
1460// -----------------------------------------------------------------------------
1461// MethodDescriptor
1462// -----------------------------------------------------------------------------
1463
1464const upb_MethodDef* PyUpb_MethodDescriptor_GetDef(PyObject* _self) {
1465 PyUpb_DescriptorBase* self =
1466 PyUpb_DescriptorBase_Check(_self, kPyUpb_MethodDescriptor);
1467 return self ? self->def : NULL;
1468}
1469
1470PyObject* PyUpb_MethodDescriptor_Get(const upb_MethodDef* m) {
1471 const upb_FileDef* file = upb_ServiceDef_File(upb_MethodDef_Service(m));
1472 return PyUpb_DescriptorBase_Get(kPyUpb_MethodDescriptor, m, file);
1473}
1474
1475static PyObject* PyUpb_MethodDescriptor_GetName(PyObject* self, void* closure) {
1476 const upb_MethodDef* m = PyUpb_MethodDescriptor_GetDef(self);
1477 return PyUnicode_FromString(upb_MethodDef_Name(m));
1478}
1479
1480static PyObject* PyUpb_MethodDescriptor_GetFullName(PyObject* self,
1481 void* closure) {
1482 const upb_MethodDef* m = PyUpb_MethodDescriptor_GetDef(self);
1483 return PyUnicode_FromString(upb_MethodDef_FullName(m));
1484}
1485
1486static PyObject* PyUpb_MethodDescriptor_GetIndex(PyObject* self,
1487 void* closure) {
1488 const upb_MethodDef* oneof = PyUpb_MethodDescriptor_GetDef(self);
1489 return PyLong_FromLong(upb_MethodDef_Index(oneof));
1490}
1491
1492static PyObject* PyUpb_MethodDescriptor_GetContainingService(PyObject* self,
1493 void* closure) {
1494 const upb_MethodDef* m = PyUpb_MethodDescriptor_GetDef(self);
1495 return PyUpb_ServiceDescriptor_Get(upb_MethodDef_Service(m));
1496}
1497
1498static PyObject* PyUpb_MethodDescriptor_GetInputType(PyObject* self,
1499 void* closure) {
1500 const upb_MethodDef* m = PyUpb_MethodDescriptor_GetDef(self);
1501 return PyUpb_Descriptor_Get(upb_MethodDef_InputType(m));
1502}
1503
1504static PyObject* PyUpb_MethodDescriptor_GetOutputType(PyObject* self,
1505 void* closure) {
1506 const upb_MethodDef* m = PyUpb_MethodDescriptor_GetDef(self);
1507 return PyUpb_Descriptor_Get(upb_MethodDef_OutputType(m));
1508}
1509
Jie Luo8c8cbc42023-10-13 11:11:13 -07001510static PyObject* PyUpb_MethodDescriptor_GetClientStreaming(PyObject* self,
1511 void* closure) {
1512 const upb_MethodDef* m = PyUpb_MethodDescriptor_GetDef(self);
1513 return PyBool_FromLong(upb_MethodDef_ClientStreaming(m) ? 1 : 0);
1514}
1515
1516static PyObject* PyUpb_MethodDescriptor_GetServerStreaming(PyObject* self,
1517 void* closure) {
1518 const upb_MethodDef* m = PyUpb_MethodDescriptor_GetDef(self);
1519 return PyBool_FromLong(upb_MethodDef_ServerStreaming(m) ? 1 : 0);
1520}
1521
Adam Cozzette501ecec2023-09-26 14:36:20 -07001522static PyObject* PyUpb_MethodDescriptor_GetOptions(PyObject* _self,
1523 PyObject* args) {
1524 PyUpb_DescriptorBase* self = (void*)_self;
1525 return PyUpb_DescriptorBase_GetOptions(
Eric Salob997cb62023-12-21 08:09:54 -08001526 &self->options, UPB_UPCAST(upb_MethodDef_Options(self->def)),
Mike Kruskalc23d5332023-11-10 15:18:00 -08001527 &google__protobuf__MethodOptions_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -07001528 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".MethodOptions");
1529}
1530
Mike Kruskalc23d5332023-11-10 15:18:00 -08001531static PyObject* PyUpb_MethodDescriptor_GetFeatures(PyObject* _self,
1532 PyObject* args) {
1533 PyUpb_DescriptorBase* self = (void*)_self;
1534 return PyUpb_DescriptorBase_GetFeatures(
Eric Salob997cb62023-12-21 08:09:54 -08001535 &self->features, UPB_UPCAST(upb_MethodDef_ResolvedFeatures(self->def)));
Mike Kruskalc23d5332023-11-10 15:18:00 -08001536}
1537
Adam Cozzette501ecec2023-09-26 14:36:20 -07001538static PyObject* PyUpb_MethodDescriptor_CopyToProto(PyObject* _self,
1539 PyObject* py_proto) {
1540 return PyUpb_DescriptorBase_CopyToProto(
1541 _self, (PyUpb_ToProto_Func*)&upb_MethodDef_ToProto,
Eric Salo5b6543e2023-10-07 16:26:40 -07001542 &google__protobuf__MethodDescriptorProto_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -07001543 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".MethodDescriptorProto", py_proto);
1544}
1545
1546static PyGetSetDef PyUpb_MethodDescriptor_Getters[] = {
1547 {"name", PyUpb_MethodDescriptor_GetName, NULL, "Name", NULL},
1548 {"full_name", PyUpb_MethodDescriptor_GetFullName, NULL, "Full name", NULL},
1549 {"index", PyUpb_MethodDescriptor_GetIndex, NULL, "Index", NULL},
1550 {"containing_service", PyUpb_MethodDescriptor_GetContainingService, NULL,
1551 "Containing service", NULL},
1552 {"input_type", PyUpb_MethodDescriptor_GetInputType, NULL, "Input type",
1553 NULL},
1554 {"output_type", PyUpb_MethodDescriptor_GetOutputType, NULL, "Output type",
1555 NULL},
Jie Luo8c8cbc42023-10-13 11:11:13 -07001556 {"client_streaming", PyUpb_MethodDescriptor_GetClientStreaming, NULL,
1557 "Client streaming", NULL},
1558 {"server_streaming", PyUpb_MethodDescriptor_GetServerStreaming, NULL,
1559 "Server streaming", NULL},
Adam Cozzette501ecec2023-09-26 14:36:20 -07001560 {NULL}};
1561
1562static PyMethodDef PyUpb_MethodDescriptor_Methods[] = {
1563 {"GetOptions", PyUpb_MethodDescriptor_GetOptions, METH_NOARGS},
Mike Kruskalc23d5332023-11-10 15:18:00 -08001564 {"_GetFeatures", PyUpb_MethodDescriptor_GetFeatures, METH_NOARGS},
Adam Cozzette501ecec2023-09-26 14:36:20 -07001565 {"CopyToProto", PyUpb_MethodDescriptor_CopyToProto, METH_O},
1566 {NULL}};
1567
1568static PyType_Slot PyUpb_MethodDescriptor_Slots[] = {
1569 DESCRIPTOR_BASE_SLOTS,
1570 {Py_tp_methods, PyUpb_MethodDescriptor_Methods},
1571 {Py_tp_getset, PyUpb_MethodDescriptor_Getters},
1572 {0, NULL}};
1573
1574static PyType_Spec PyUpb_MethodDescriptor_Spec = {
1575 PYUPB_MODULE_NAME ".MethodDescriptor", // tp_name
1576 sizeof(PyUpb_DescriptorBase), // tp_basicsize
1577 0, // tp_itemsize
1578 Py_TPFLAGS_DEFAULT, // tp_flags
1579 PyUpb_MethodDescriptor_Slots,
1580};
1581
1582// -----------------------------------------------------------------------------
1583// OneofDescriptor
1584// -----------------------------------------------------------------------------
1585
1586const upb_OneofDef* PyUpb_OneofDescriptor_GetDef(PyObject* _self) {
1587 PyUpb_DescriptorBase* self =
1588 PyUpb_DescriptorBase_Check(_self, kPyUpb_OneofDescriptor);
1589 return self ? self->def : NULL;
1590}
1591
1592PyObject* PyUpb_OneofDescriptor_Get(const upb_OneofDef* oneof) {
1593 const upb_FileDef* file =
1594 upb_MessageDef_File(upb_OneofDef_ContainingType(oneof));
1595 return PyUpb_DescriptorBase_Get(kPyUpb_OneofDescriptor, oneof, file);
1596}
1597
1598static PyObject* PyUpb_OneofDescriptor_GetName(PyObject* self, void* closure) {
1599 const upb_OneofDef* oneof = PyUpb_OneofDescriptor_GetDef(self);
1600 return PyUnicode_FromString(upb_OneofDef_Name(oneof));
1601}
1602
1603static PyObject* PyUpb_OneofDescriptor_GetFullName(PyObject* self,
1604 void* closure) {
1605 const upb_OneofDef* oneof = PyUpb_OneofDescriptor_GetDef(self);
1606 return PyUnicode_FromFormat(
1607 "%s.%s", upb_MessageDef_FullName(upb_OneofDef_ContainingType(oneof)),
1608 upb_OneofDef_Name(oneof));
1609}
1610
1611static PyObject* PyUpb_OneofDescriptor_GetIndex(PyObject* self, void* closure) {
1612 const upb_OneofDef* oneof = PyUpb_OneofDescriptor_GetDef(self);
1613 return PyLong_FromLong(upb_OneofDef_Index(oneof));
1614}
1615
1616static PyObject* PyUpb_OneofDescriptor_GetContainingType(PyObject* self,
1617 void* closure) {
1618 const upb_OneofDef* oneof = PyUpb_OneofDescriptor_GetDef(self);
1619 return PyUpb_Descriptor_Get(upb_OneofDef_ContainingType(oneof));
1620}
1621
1622static PyObject* PyUpb_OneofDescriptor_GetHasOptions(PyObject* _self,
1623 void* closure) {
1624 PyUpb_DescriptorBase* self = (void*)_self;
1625 return PyBool_FromLong(upb_OneofDef_HasOptions(self->def));
1626}
1627
1628static PyObject* PyUpb_OneofDescriptor_GetFields(PyObject* _self,
1629 void* closure) {
1630 PyUpb_DescriptorBase* self = (void*)_self;
1631 static PyUpb_GenericSequence_Funcs funcs = {
1632 (void*)&upb_OneofDef_FieldCount,
1633 (void*)&upb_OneofDef_Field,
1634 (void*)&PyUpb_FieldDescriptor_Get,
1635 };
1636 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
1637}
1638
1639static PyObject* PyUpb_OneofDescriptor_GetOptions(PyObject* _self,
1640 PyObject* args) {
1641 PyUpb_DescriptorBase* self = (void*)_self;
1642 return PyUpb_DescriptorBase_GetOptions(
Eric Salob997cb62023-12-21 08:09:54 -08001643 &self->options, UPB_UPCAST(upb_OneofDef_Options(self->def)),
Mike Kruskalc23d5332023-11-10 15:18:00 -08001644 &google__protobuf__OneofOptions_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -07001645 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".OneofOptions");
1646}
1647
Mike Kruskalc23d5332023-11-10 15:18:00 -08001648static PyObject* PyUpb_OneofDescriptor_GetFeatures(PyObject* _self,
1649 PyObject* args) {
1650 PyUpb_DescriptorBase* self = (void*)_self;
1651 return PyUpb_DescriptorBase_GetFeatures(
Eric Salob997cb62023-12-21 08:09:54 -08001652 &self->features, UPB_UPCAST(upb_OneofDef_ResolvedFeatures(self->def)));
Mike Kruskalc23d5332023-11-10 15:18:00 -08001653}
1654
Adam Cozzette501ecec2023-09-26 14:36:20 -07001655static PyGetSetDef PyUpb_OneofDescriptor_Getters[] = {
1656 {"name", PyUpb_OneofDescriptor_GetName, NULL, "Name"},
1657 {"full_name", PyUpb_OneofDescriptor_GetFullName, NULL, "Full name"},
1658 {"index", PyUpb_OneofDescriptor_GetIndex, NULL, "Index"},
1659 {"containing_type", PyUpb_OneofDescriptor_GetContainingType, NULL,
1660 "Containing type"},
1661 {"has_options", PyUpb_OneofDescriptor_GetHasOptions, NULL, "Has Options"},
1662 {"fields", PyUpb_OneofDescriptor_GetFields, NULL, "Fields"},
1663 {NULL}};
1664
1665static PyMethodDef PyUpb_OneofDescriptor_Methods[] = {
Mike Kruskalc23d5332023-11-10 15:18:00 -08001666 {"GetOptions", PyUpb_OneofDescriptor_GetOptions, METH_NOARGS},
1667 {"_GetFeatures", PyUpb_OneofDescriptor_GetFeatures, METH_NOARGS},
1668 {NULL}};
Adam Cozzette501ecec2023-09-26 14:36:20 -07001669
1670static PyType_Slot PyUpb_OneofDescriptor_Slots[] = {
1671 DESCRIPTOR_BASE_SLOTS,
1672 {Py_tp_methods, PyUpb_OneofDescriptor_Methods},
1673 {Py_tp_getset, PyUpb_OneofDescriptor_Getters},
1674 {0, NULL}};
1675
1676static PyType_Spec PyUpb_OneofDescriptor_Spec = {
1677 PYUPB_MODULE_NAME ".OneofDescriptor", // tp_name
1678 sizeof(PyUpb_DescriptorBase), // tp_basicsize
1679 0, // tp_itemsize
1680 Py_TPFLAGS_DEFAULT, // tp_flags
1681 PyUpb_OneofDescriptor_Slots,
1682};
1683
1684// -----------------------------------------------------------------------------
1685// ServiceDescriptor
1686// -----------------------------------------------------------------------------
1687
1688const upb_ServiceDef* PyUpb_ServiceDescriptor_GetDef(PyObject* _self) {
1689 PyUpb_DescriptorBase* self =
1690 PyUpb_DescriptorBase_Check(_self, kPyUpb_ServiceDescriptor);
1691 return self ? self->def : NULL;
1692}
1693
1694PyObject* PyUpb_ServiceDescriptor_Get(const upb_ServiceDef* s) {
1695 const upb_FileDef* file = upb_ServiceDef_File(s);
1696 return PyUpb_DescriptorBase_Get(kPyUpb_ServiceDescriptor, s, file);
1697}
1698
1699static PyObject* PyUpb_ServiceDescriptor_GetFullName(PyObject* self,
1700 void* closure) {
1701 const upb_ServiceDef* s = PyUpb_ServiceDescriptor_GetDef(self);
1702 return PyUnicode_FromString(upb_ServiceDef_FullName(s));
1703}
1704
1705static PyObject* PyUpb_ServiceDescriptor_GetName(PyObject* self,
1706 void* closure) {
1707 const upb_ServiceDef* s = PyUpb_ServiceDescriptor_GetDef(self);
1708 return PyUnicode_FromString(upb_ServiceDef_Name(s));
1709}
1710
1711static PyObject* PyUpb_ServiceDescriptor_GetFile(PyObject* self,
1712 void* closure) {
1713 const upb_ServiceDef* s = PyUpb_ServiceDescriptor_GetDef(self);
1714 return PyUpb_FileDescriptor_Get(upb_ServiceDef_File(s));
1715}
1716
1717static PyObject* PyUpb_ServiceDescriptor_GetIndex(PyObject* self,
1718 void* closure) {
1719 const upb_ServiceDef* s = PyUpb_ServiceDescriptor_GetDef(self);
1720 return PyLong_FromLong(upb_ServiceDef_Index(s));
1721}
1722
1723static PyObject* PyUpb_ServiceDescriptor_GetMethods(PyObject* _self,
1724 void* closure) {
1725 PyUpb_DescriptorBase* self = (void*)_self;
1726 static PyUpb_GenericSequence_Funcs funcs = {
1727 (void*)&upb_ServiceDef_MethodCount,
1728 (void*)&upb_ServiceDef_Method,
1729 (void*)&PyUpb_MethodDescriptor_Get,
1730 };
1731 return PyUpb_GenericSequence_New(&funcs, self->def, self->pool);
1732}
1733
1734static PyObject* PyUpb_ServiceDescriptor_GetMethodsByName(PyObject* _self,
1735 void* closure) {
1736 static PyUpb_ByNameMap_Funcs funcs = {
1737 {
1738 (void*)&upb_ServiceDef_MethodCount,
1739 (void*)&upb_ServiceDef_Method,
1740 (void*)&PyUpb_MethodDescriptor_Get,
1741 },
1742 (void*)&upb_ServiceDef_FindMethodByName,
1743 (void*)&upb_MethodDef_Name,
1744 };
1745 PyUpb_DescriptorBase* self = (void*)_self;
1746 return PyUpb_ByNameMap_New(&funcs, self->def, self->pool);
1747}
1748
1749static PyObject* PyUpb_ServiceDescriptor_GetOptions(PyObject* _self,
1750 PyObject* args) {
1751 PyUpb_DescriptorBase* self = (void*)_self;
1752 return PyUpb_DescriptorBase_GetOptions(
Eric Salob997cb62023-12-21 08:09:54 -08001753 &self->options, UPB_UPCAST(upb_ServiceDef_Options(self->def)),
Mike Kruskalc23d5332023-11-10 15:18:00 -08001754 &google__protobuf__ServiceOptions_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -07001755 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".ServiceOptions");
1756}
1757
Mike Kruskalc23d5332023-11-10 15:18:00 -08001758static PyObject* PyUpb_ServiceDescriptor_GetFeatures(PyObject* _self,
1759 PyObject* args) {
1760 PyUpb_DescriptorBase* self = (void*)_self;
1761 return PyUpb_DescriptorBase_GetFeatures(
Eric Salob997cb62023-12-21 08:09:54 -08001762 &self->features, UPB_UPCAST(upb_ServiceDef_ResolvedFeatures(self->def)));
Mike Kruskalc23d5332023-11-10 15:18:00 -08001763}
1764
Adam Cozzette501ecec2023-09-26 14:36:20 -07001765static PyObject* PyUpb_ServiceDescriptor_CopyToProto(PyObject* _self,
1766 PyObject* py_proto) {
1767 return PyUpb_DescriptorBase_CopyToProto(
1768 _self, (PyUpb_ToProto_Func*)&upb_ServiceDef_ToProto,
Eric Salo5b6543e2023-10-07 16:26:40 -07001769 &google__protobuf__ServiceDescriptorProto_msg_init,
Adam Cozzette501ecec2023-09-26 14:36:20 -07001770 PYUPB_DESCRIPTOR_PROTO_PACKAGE ".ServiceDescriptorProto", py_proto);
1771}
1772
1773static PyObject* PyUpb_ServiceDescriptor_FindMethodByName(PyObject* _self,
1774 PyObject* py_name) {
1775 PyUpb_DescriptorBase* self = (void*)_self;
1776 const char* name = PyUnicode_AsUTF8AndSize(py_name, NULL);
1777 if (!name) return NULL;
1778 const upb_MethodDef* method =
1779 upb_ServiceDef_FindMethodByName(self->def, name);
1780 if (method == NULL) {
1781 return PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name);
1782 }
1783 return PyUpb_MethodDescriptor_Get(method);
1784}
1785
1786static PyGetSetDef PyUpb_ServiceDescriptor_Getters[] = {
1787 {"name", PyUpb_ServiceDescriptor_GetName, NULL, "Name", NULL},
1788 {"full_name", PyUpb_ServiceDescriptor_GetFullName, NULL, "Full name", NULL},
1789 {"file", PyUpb_ServiceDescriptor_GetFile, NULL, "File descriptor"},
1790 {"index", PyUpb_ServiceDescriptor_GetIndex, NULL, "Index", NULL},
1791 {"methods", PyUpb_ServiceDescriptor_GetMethods, NULL, "Methods", NULL},
1792 {"methods_by_name", PyUpb_ServiceDescriptor_GetMethodsByName, NULL,
1793 "Methods by name", NULL},
1794 {NULL}};
1795
1796static PyMethodDef PyUpb_ServiceDescriptor_Methods[] = {
1797 {"GetOptions", PyUpb_ServiceDescriptor_GetOptions, METH_NOARGS},
Mike Kruskalc23d5332023-11-10 15:18:00 -08001798 {"_GetFeatures", PyUpb_ServiceDescriptor_GetFeatures, METH_NOARGS},
Adam Cozzette501ecec2023-09-26 14:36:20 -07001799 {"CopyToProto", PyUpb_ServiceDescriptor_CopyToProto, METH_O},
1800 {"FindMethodByName", PyUpb_ServiceDescriptor_FindMethodByName, METH_O},
1801 {NULL}};
1802
1803static PyType_Slot PyUpb_ServiceDescriptor_Slots[] = {
1804 DESCRIPTOR_BASE_SLOTS,
1805 {Py_tp_methods, PyUpb_ServiceDescriptor_Methods},
1806 {Py_tp_getset, PyUpb_ServiceDescriptor_Getters},
1807 {0, NULL}};
1808
1809static PyType_Spec PyUpb_ServiceDescriptor_Spec = {
1810 PYUPB_MODULE_NAME ".ServiceDescriptor", // tp_name
1811 sizeof(PyUpb_DescriptorBase), // tp_basicsize
1812 0, // tp_itemsize
1813 Py_TPFLAGS_DEFAULT, // tp_flags
1814 PyUpb_ServiceDescriptor_Slots,
1815};
1816
1817// -----------------------------------------------------------------------------
1818// Top Level
1819// -----------------------------------------------------------------------------
1820
1821static bool PyUpb_SetIntAttr(PyObject* obj, const char* name, int val) {
1822 PyObject* num = PyLong_FromLong(val);
1823 if (!num) return false;
1824 int status = PyObject_SetAttrString(obj, name, num);
1825 Py_DECREF(num);
1826 return status >= 0;
1827}
1828
1829// These must be in the same order as PyUpb_DescriptorType in the header.
1830static PyType_Spec* desc_specs[] = {
1831 &PyUpb_Descriptor_Spec, &PyUpb_EnumDescriptor_Spec,
1832 &PyUpb_EnumValueDescriptor_Spec, &PyUpb_FieldDescriptor_Spec,
1833 &PyUpb_FileDescriptor_Spec, &PyUpb_MethodDescriptor_Spec,
1834 &PyUpb_OneofDescriptor_Spec, &PyUpb_ServiceDescriptor_Spec,
1835};
1836
1837bool PyUpb_InitDescriptor(PyObject* m) {
1838 PyUpb_ModuleState* s = PyUpb_ModuleState_GetFromModule(m);
1839
1840 for (size_t i = 0; i < kPyUpb_Descriptor_Count; i++) {
1841 s->descriptor_types[i] = PyUpb_AddClass(m, desc_specs[i]);
1842 if (!s->descriptor_types[i]) {
1843 return false;
1844 }
1845 }
1846
1847 PyObject* fd = (PyObject*)s->descriptor_types[kPyUpb_FieldDescriptor];
1848 return PyUpb_SetIntAttr(fd, "LABEL_OPTIONAL", kUpb_Label_Optional) &&
1849 PyUpb_SetIntAttr(fd, "LABEL_REPEATED", kUpb_Label_Repeated) &&
1850 PyUpb_SetIntAttr(fd, "LABEL_REQUIRED", kUpb_Label_Required) &&
1851 PyUpb_SetIntAttr(fd, "TYPE_BOOL", kUpb_FieldType_Bool) &&
1852 PyUpb_SetIntAttr(fd, "TYPE_BYTES", kUpb_FieldType_Bytes) &&
1853 PyUpb_SetIntAttr(fd, "TYPE_DOUBLE", kUpb_FieldType_Double) &&
1854 PyUpb_SetIntAttr(fd, "TYPE_ENUM", kUpb_FieldType_Enum) &&
1855 PyUpb_SetIntAttr(fd, "TYPE_FIXED32", kUpb_FieldType_Fixed32) &&
1856 PyUpb_SetIntAttr(fd, "TYPE_FIXED64", kUpb_FieldType_Fixed64) &&
1857 PyUpb_SetIntAttr(fd, "TYPE_FLOAT", kUpb_FieldType_Float) &&
1858 PyUpb_SetIntAttr(fd, "TYPE_GROUP", kUpb_FieldType_Group) &&
1859 PyUpb_SetIntAttr(fd, "TYPE_INT32", kUpb_FieldType_Int32) &&
1860 PyUpb_SetIntAttr(fd, "TYPE_INT64", kUpb_FieldType_Int64) &&
1861 PyUpb_SetIntAttr(fd, "TYPE_MESSAGE", kUpb_FieldType_Message) &&
1862 PyUpb_SetIntAttr(fd, "TYPE_SFIXED32", kUpb_FieldType_SFixed32) &&
1863 PyUpb_SetIntAttr(fd, "TYPE_SFIXED64", kUpb_FieldType_SFixed64) &&
1864 PyUpb_SetIntAttr(fd, "TYPE_SINT32", kUpb_FieldType_SInt32) &&
1865 PyUpb_SetIntAttr(fd, "TYPE_SINT64", kUpb_FieldType_SInt64) &&
1866 PyUpb_SetIntAttr(fd, "TYPE_STRING", kUpb_FieldType_String) &&
1867 PyUpb_SetIntAttr(fd, "TYPE_UINT32", kUpb_FieldType_UInt32) &&
1868 PyUpb_SetIntAttr(fd, "TYPE_UINT64", kUpb_FieldType_UInt64) &&
1869 PyUpb_SetIntAttr(fd, "CPPTYPE_INT32", CPPTYPE_INT32) &&
1870 PyUpb_SetIntAttr(fd, "CPPTYPE_INT64", CPPTYPE_INT64) &&
1871 PyUpb_SetIntAttr(fd, "CPPTYPE_UINT32", CPPTYPE_UINT32) &&
1872 PyUpb_SetIntAttr(fd, "CPPTYPE_UINT64", CPPTYPE_UINT64) &&
1873 PyUpb_SetIntAttr(fd, "CPPTYPE_DOUBLE", CPPTYPE_DOUBLE) &&
1874 PyUpb_SetIntAttr(fd, "CPPTYPE_FLOAT", CPPTYPE_FLOAT) &&
1875 PyUpb_SetIntAttr(fd, "CPPTYPE_BOOL", CPPTYPE_BOOL) &&
1876 PyUpb_SetIntAttr(fd, "CPPTYPE_ENUM", CPPTYPE_ENUM) &&
1877 PyUpb_SetIntAttr(fd, "CPPTYPE_STRING", CPPTYPE_STRING) &&
1878 PyUpb_SetIntAttr(fd, "CPPTYPE_BYTES", CPPTYPE_STRING) &&
1879 PyUpb_SetIntAttr(fd, "CPPTYPE_MESSAGE", CPPTYPE_MESSAGE);
1880}