123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- /*
- * Copyright (c) 2009-2021, Google LLC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of Google LLC nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "python/map.h"
- #include "python/convert.h"
- #include "python/message.h"
- #include "python/protobuf.h"
- // -----------------------------------------------------------------------------
- // MapContainer
- // -----------------------------------------------------------------------------
- typedef struct {
- PyObject_HEAD;
- PyObject* arena;
- // The field descriptor (upb_FieldDef*).
- // The low bit indicates whether the container is reified (see ptr below).
- // - low bit set: repeated field is a stub (empty map, no underlying data).
- // - low bit clear: repeated field is reified (points to upb_Array).
- uintptr_t field;
- union {
- PyObject* parent; // stub: owning pointer to parent message.
- upb_Map* map; // reified: the data for this array.
- } ptr;
- int version;
- } PyUpb_MapContainer;
- static PyObject* PyUpb_MapIterator_New(PyUpb_MapContainer* map);
- static bool PyUpb_MapContainer_IsStub(PyUpb_MapContainer* self) {
- return self->field & 1;
- }
- // If the map is reified, returns it. Otherwise, returns NULL.
- // If NULL is returned, the object is empty and has no underlying data.
- static upb_Map* PyUpb_MapContainer_GetIfReified(PyUpb_MapContainer* self) {
- return PyUpb_MapContainer_IsStub(self) ? NULL : self->ptr.map;
- }
- static const upb_FieldDef* PyUpb_MapContainer_GetField(
- PyUpb_MapContainer* self) {
- return (const upb_FieldDef*)(self->field & ~(uintptr_t)1);
- }
- static void PyUpb_MapContainer_Dealloc(void* _self) {
- PyUpb_MapContainer* self = _self;
- Py_DECREF(self->arena);
- if (PyUpb_MapContainer_IsStub(self)) {
- PyUpb_CMessage_CacheDelete(self->ptr.parent,
- PyUpb_MapContainer_GetField(self));
- Py_DECREF(self->ptr.parent);
- } else {
- PyUpb_ObjCache_Delete(self->ptr.map);
- }
- PyUpb_Dealloc(_self);
- }
- PyTypeObject* PyUpb_MapContainer_GetClass(const upb_FieldDef* f) {
- assert(upb_FieldDef_IsMap(f));
- PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
- return upb_FieldDef_IsSubMessage(f) ? state->message_map_container_type
- : state->scalar_map_container_type;
- }
- PyObject* PyUpb_MapContainer_NewStub(PyObject* parent, const upb_FieldDef* f,
- PyObject* arena) {
- // We only create stubs when the parent is reified, by convention. However
- // this is not an invariant: the parent could become reified at any time.
- assert(PyUpb_CMessage_GetIfReified(parent) == NULL);
- PyTypeObject* cls = PyUpb_MapContainer_GetClass(f);
- PyUpb_MapContainer* map = (void*)PyType_GenericAlloc(cls, 0);
- map->arena = arena;
- map->field = (uintptr_t)f | 1;
- map->ptr.parent = parent;
- map->version = 0;
- Py_INCREF(arena);
- Py_INCREF(parent);
- return &map->ob_base;
- }
- void PyUpb_MapContainer_Reify(PyObject* _self, upb_Map* map) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- if (!map) {
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
- upb_Arena* arena = PyUpb_Arena_Get(self->arena);
- const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
- const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
- const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
- map = upb_Map_New(arena, upb_FieldDef_CType(key_f),
- upb_FieldDef_CType(val_f));
- }
- PyUpb_ObjCache_Add(map, &self->ob_base);
- Py_DECREF(self->ptr.parent);
- self->ptr.map = map; // Overwrites self->ptr.parent.
- self->field &= ~(uintptr_t)1;
- assert(!PyUpb_MapContainer_IsStub(self));
- }
- void PyUpb_MapContainer_Invalidate(PyObject* obj) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)obj;
- self->version++;
- }
- upb_Map* PyUpb_MapContainer_EnsureReified(PyObject* _self) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- self->version++;
- upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
- if (map) return map; // Already writable.
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
- upb_Arena* arena = PyUpb_Arena_Get(self->arena);
- const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
- const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
- const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
- map =
- upb_Map_New(arena, upb_FieldDef_CType(key_f), upb_FieldDef_CType(val_f));
- upb_MessageValue msgval = {.map_val = map};
- PyUpb_CMessage_SetConcreteSubobj(self->ptr.parent, f, msgval);
- PyUpb_MapContainer_Reify((PyObject*)self, map);
- return map;
- }
- int PyUpb_MapContainer_AssignSubscript(PyObject* _self, PyObject* key,
- PyObject* val) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- upb_Map* map = PyUpb_MapContainer_EnsureReified(_self);
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
- const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
- const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
- const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
- upb_Arena* arena = PyUpb_Arena_Get(self->arena);
- upb_MessageValue u_key, u_val;
- if (!PyUpb_PyToUpb(key, key_f, &u_key, arena)) return -1;
- if (val) {
- if (!PyUpb_PyToUpb(val, val_f, &u_val, arena)) return -1;
- upb_Map_Set(map, u_key, u_val, arena);
- } else {
- if (!upb_Map_Delete(map, u_key)) {
- PyErr_Format(PyExc_KeyError, "Key not present in map");
- return -1;
- }
- }
- return 0;
- }
- PyObject* PyUpb_MapContainer_Subscript(PyObject* _self, PyObject* key) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
- const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
- const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
- const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
- upb_Arena* arena = PyUpb_Arena_Get(self->arena);
- upb_MessageValue u_key, u_val;
- if (!PyUpb_PyToUpb(key, key_f, &u_key, arena)) return NULL;
- if (!map || !upb_Map_Get(map, u_key, &u_val)) {
- map = PyUpb_MapContainer_EnsureReified(_self);
- upb_Arena* arena = PyUpb_Arena_Get(self->arena);
- if (upb_FieldDef_IsSubMessage(val_f)) {
- u_val.msg_val = upb_Message_New(upb_FieldDef_MessageSubDef(val_f), arena);
- } else {
- memset(&u_val, 0, sizeof(u_val));
- }
- upb_Map_Set(map, u_key, u_val, arena);
- }
- return PyUpb_UpbToPy(u_val, val_f, self->arena);
- }
- PyObject* PyUpb_MapContainer_Contains(PyObject* _self, PyObject* key) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
- if (!map) Py_RETURN_FALSE;
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
- const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
- const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
- upb_MessageValue u_key;
- if (!PyUpb_PyToUpb(key, key_f, &u_key, NULL)) return NULL;
- if (upb_Map_Get(map, u_key, NULL)) {
- Py_RETURN_TRUE;
- } else {
- Py_RETURN_FALSE;
- }
- }
- PyObject* PyUpb_MapContainer_Clear(PyObject* _self, PyObject* key) {
- upb_Map* map = PyUpb_MapContainer_EnsureReified(_self);
- upb_Map_Clear(map);
- Py_RETURN_NONE;
- }
- static PyObject* PyUpb_MapContainer_Get(PyObject* _self, PyObject* args,
- PyObject* kwargs) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- static const char* kwlist[] = {"key", "default", NULL};
- PyObject* key;
- PyObject* default_value = NULL;
- upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", (char**)kwlist, &key,
- &default_value)) {
- return NULL;
- }
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
- const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
- const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
- const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
- upb_Arena* arena = PyUpb_Arena_Get(self->arena);
- upb_MessageValue u_key, u_val;
- if (!PyUpb_PyToUpb(key, key_f, &u_key, arena)) return NULL;
- if (map && upb_Map_Get(map, u_key, &u_val)) {
- return PyUpb_UpbToPy(u_val, val_f, self->arena);
- }
- if (default_value) {
- Py_INCREF(default_value);
- return default_value;
- }
- Py_RETURN_NONE;
- }
- static PyObject* PyUpb_MapContainer_GetEntryClass(PyObject* _self,
- PyObject* arg) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
- const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
- return PyUpb_Descriptor_GetClass(entry_m);
- }
- Py_ssize_t PyUpb_MapContainer_Length(PyObject* _self) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
- return map ? upb_Map_Size(map) : 0;
- }
- PyUpb_MapContainer* PyUpb_MapContainer_Check(PyObject* _self) {
- PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
- if (!PyObject_TypeCheck(_self, state->message_map_container_type) &&
- !PyObject_TypeCheck(_self, state->scalar_map_container_type)) {
- PyErr_Format(PyExc_TypeError, "Expected protobuf map, but got %R", _self);
- return NULL;
- }
- return (PyUpb_MapContainer*)_self;
- }
- int PyUpb_CMessage_InitMapAttributes(PyObject* map, PyObject* value,
- const upb_FieldDef* f);
- static PyObject* PyUpb_MapContainer_MergeFrom(PyObject* _self, PyObject* _arg) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
- if (PyDict_Check(_arg)) {
- return PyErr_Format(PyExc_AttributeError, "Merging of dict is not allowed");
- }
- if (PyUpb_CMessage_InitMapAttributes(_self, _arg, f) < 0) {
- return NULL;
- }
- Py_RETURN_NONE;
- }
- static PyObject* PyUpb_MapContainer_Repr(PyObject* _self) {
- PyUpb_MapContainer* self = (PyUpb_MapContainer*)_self;
- upb_Map* map = PyUpb_MapContainer_GetIfReified(self);
- PyObject* dict = PyDict_New();
- if (map) {
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self);
- const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
- const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
- const upb_FieldDef* val_f = upb_MessageDef_Field(entry_m, 1);
- size_t iter = kUpb_Map_Begin;
- while (upb_MapIterator_Next(map, &iter)) {
- PyObject* key =
- PyUpb_UpbToPy(upb_MapIterator_Key(map, iter), key_f, self->arena);
- PyObject* val =
- PyUpb_UpbToPy(upb_MapIterator_Value(map, iter), val_f, self->arena);
- if (!key || !val) {
- Py_XDECREF(key);
- Py_XDECREF(val);
- Py_DECREF(dict);
- return NULL;
- }
- PyDict_SetItem(dict, key, val);
- Py_DECREF(key);
- Py_DECREF(val);
- }
- }
- PyObject* repr = PyObject_Repr(dict);
- Py_DECREF(dict);
- return repr;
- }
- PyObject* PyUpb_MapContainer_GetOrCreateWrapper(upb_Map* map,
- const upb_FieldDef* f,
- PyObject* arena) {
- PyUpb_MapContainer* ret = (void*)PyUpb_ObjCache_Get(map);
- if (ret) return &ret->ob_base;
- PyTypeObject* cls = PyUpb_MapContainer_GetClass(f);
- ret = (void*)PyType_GenericAlloc(cls, 0);
- ret->arena = arena;
- ret->field = (uintptr_t)f;
- ret->ptr.map = map;
- ret->version = 0;
- Py_INCREF(arena);
- PyUpb_ObjCache_Add(map, &ret->ob_base);
- return &ret->ob_base;
- }
- // -----------------------------------------------------------------------------
- // ScalarMapContainer
- // -----------------------------------------------------------------------------
- static PyMethodDef PyUpb_ScalarMapContainer_Methods[] = {
- {"__contains__", PyUpb_MapContainer_Contains, METH_O,
- "Tests whether a key is a member of the map."},
- {"clear", PyUpb_MapContainer_Clear, METH_NOARGS,
- "Removes all elements from the map."},
- {"get", (PyCFunction)PyUpb_MapContainer_Get, METH_VARARGS | METH_KEYWORDS,
- "Gets the value for the given key if present, or otherwise a default"},
- {"GetEntryClass", PyUpb_MapContainer_GetEntryClass, METH_NOARGS,
- "Return the class used to build Entries of (key, value) pairs."},
- {"MergeFrom", PyUpb_MapContainer_MergeFrom, METH_O,
- "Merges a map into the current map."},
- /*
- { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
- "Makes a deep copy of the class." },
- { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
- "Outputs picklable representation of the repeated field." },
- */
- {NULL, NULL},
- };
- static PyType_Slot PyUpb_ScalarMapContainer_Slots[] = {
- {Py_tp_dealloc, PyUpb_MapContainer_Dealloc},
- {Py_mp_length, PyUpb_MapContainer_Length},
- {Py_mp_subscript, PyUpb_MapContainer_Subscript},
- {Py_mp_ass_subscript, PyUpb_MapContainer_AssignSubscript},
- {Py_tp_methods, PyUpb_ScalarMapContainer_Methods},
- {Py_tp_iter, PyUpb_MapIterator_New},
- {Py_tp_repr, PyUpb_MapContainer_Repr},
- {Py_tp_hash, PyObject_HashNotImplemented},
- {0, NULL},
- };
- static PyType_Spec PyUpb_ScalarMapContainer_Spec = {
- PYUPB_MODULE_NAME ".ScalarMapContainer",
- sizeof(PyUpb_MapContainer),
- 0,
- Py_TPFLAGS_DEFAULT,
- PyUpb_ScalarMapContainer_Slots,
- };
- // -----------------------------------------------------------------------------
- // MessageMapContainer
- // -----------------------------------------------------------------------------
- static PyMethodDef PyUpb_MessageMapContainer_Methods[] = {
- {"__contains__", PyUpb_MapContainer_Contains, METH_O,
- "Tests whether the map contains this element."},
- {"clear", PyUpb_MapContainer_Clear, METH_NOARGS,
- "Removes all elements from the map."},
- {"get", (PyCFunction)PyUpb_MapContainer_Get, METH_VARARGS | METH_KEYWORDS,
- "Gets the value for the given key if present, or otherwise a default"},
- {"get_or_create", PyUpb_MapContainer_Subscript, METH_O,
- "Alias for getitem, useful to make explicit that the map is mutated."},
- {"GetEntryClass", PyUpb_MapContainer_GetEntryClass, METH_NOARGS,
- "Return the class used to build Entries of (key, value) pairs."},
- {"MergeFrom", PyUpb_MapContainer_MergeFrom, METH_O,
- "Merges a map into the current map."},
- /*
- { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
- "Makes a deep copy of the class." },
- { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
- "Outputs picklable representation of the repeated field." },
- */
- {NULL, NULL},
- };
- static PyType_Slot PyUpb_MessageMapContainer_Slots[] = {
- {Py_tp_dealloc, PyUpb_MapContainer_Dealloc},
- {Py_mp_length, PyUpb_MapContainer_Length},
- {Py_mp_subscript, PyUpb_MapContainer_Subscript},
- {Py_mp_ass_subscript, PyUpb_MapContainer_AssignSubscript},
- {Py_tp_methods, PyUpb_MessageMapContainer_Methods},
- {Py_tp_iter, PyUpb_MapIterator_New},
- {Py_tp_repr, PyUpb_MapContainer_Repr},
- {Py_tp_hash, PyObject_HashNotImplemented},
- {0, NULL}};
- static PyType_Spec PyUpb_MessageMapContainer_Spec = {
- PYUPB_MODULE_NAME ".MessageMapContainer", sizeof(PyUpb_MapContainer), 0,
- Py_TPFLAGS_DEFAULT, PyUpb_MessageMapContainer_Slots};
- // -----------------------------------------------------------------------------
- // MapIterator
- // -----------------------------------------------------------------------------
- typedef struct {
- PyObject_HEAD;
- PyUpb_MapContainer* map; // We own a reference.
- size_t iter;
- int version;
- } PyUpb_MapIterator;
- static PyObject* PyUpb_MapIterator_New(PyUpb_MapContainer* map) {
- PyUpb_ModuleState* state = PyUpb_ModuleState_Get();
- PyUpb_MapIterator* iter =
- (void*)PyType_GenericAlloc(state->map_iterator_type, 0);
- iter->map = map;
- iter->iter = kUpb_Map_Begin;
- iter->version = map->version;
- Py_INCREF(map);
- return &iter->ob_base;
- }
- static void PyUpb_MapIterator_Dealloc(void* _self) {
- PyUpb_MapIterator* self = (PyUpb_MapIterator*)_self;
- Py_DECREF(&self->map->ob_base);
- PyUpb_Dealloc(_self);
- }
- PyObject* PyUpb_MapIterator_IterNext(PyObject* _self) {
- PyUpb_MapIterator* self = (PyUpb_MapIterator*)_self;
- if (self->version != self->map->version) {
- return PyErr_Format(PyExc_RuntimeError, "Map modified during iteration.");
- }
- upb_Map* map = PyUpb_MapContainer_GetIfReified(self->map);
- if (!map) return NULL;
- if (!upb_MapIterator_Next(map, &self->iter)) return NULL;
- upb_MessageValue key = upb_MapIterator_Key(map, self->iter);
- const upb_FieldDef* f = PyUpb_MapContainer_GetField(self->map);
- const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
- const upb_FieldDef* key_f = upb_MessageDef_Field(entry_m, 0);
- return PyUpb_UpbToPy(key, key_f, self->map->arena);
- }
- static PyType_Slot PyUpb_MapIterator_Slots[] = {
- {Py_tp_dealloc, PyUpb_MapIterator_Dealloc},
- {Py_tp_iter, PyObject_SelfIter},
- {Py_tp_iternext, PyUpb_MapIterator_IterNext},
- {0, NULL}};
- static PyType_Spec PyUpb_MapIterator_Spec = {
- PYUPB_MODULE_NAME ".MapIterator", sizeof(PyUpb_MapIterator), 0,
- Py_TPFLAGS_DEFAULT, PyUpb_MapIterator_Slots};
- // -----------------------------------------------------------------------------
- // Top Level
- // -----------------------------------------------------------------------------
- static PyObject* GetMutableMappingBase(void) {
- PyObject* collections = NULL;
- PyObject* mapping = NULL;
- PyObject* bases = NULL;
- if ((collections = PyImport_ImportModule("collections.abc")) &&
- (mapping = PyObject_GetAttrString(collections, "MutableMapping"))) {
- bases = Py_BuildValue("(O)", mapping);
- }
- Py_XDECREF(collections);
- Py_XDECREF(mapping);
- return bases;
- }
- bool PyUpb_Map_Init(PyObject* m) {
- PyUpb_ModuleState* state = PyUpb_ModuleState_GetFromModule(m);
- PyObject* bases = GetMutableMappingBase();
- if (!bases) return false;
- state->message_map_container_type =
- PyUpb_AddClassWithBases(m, &PyUpb_MessageMapContainer_Spec, bases);
- state->scalar_map_container_type =
- PyUpb_AddClassWithBases(m, &PyUpb_ScalarMapContainer_Spec, bases);
- state->map_iterator_type = PyUpb_AddClass(m, &PyUpb_MapIterator_Spec);
- Py_DECREF(bases);
- return state->message_map_container_type &&
- state->scalar_map_container_type && state->map_iterator_type;
- }
|