Home | History | Annotate | Download | only in pyext
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 // Mappings and Sequences of descriptors.
     32 // Used by Descriptor.fields_by_name, EnumDescriptor.values...
     33 //
     34 // They avoid the allocation of a full dictionary or a full list: they simply
     35 // store a pointer to the parent descriptor, use the C++ Descriptor methods (see
     36 // google/protobuf/descriptor.h) to retrieve other descriptors, and create
     37 // Python objects on the fly.
     38 //
     39 // The containers fully conform to abc.Mapping and abc.Sequence, and behave just
     40 // like read-only dictionaries and lists.
     41 //
     42 // Because the interface of C++ Descriptors is quite regular, this file actually
     43 // defines only three types, the exact behavior of a container is controlled by
     44 // a DescriptorContainerDef structure, which contains functions that uses the
     45 // public Descriptor API.
     46 //
     47 // Note: This DescriptorContainerDef is similar to the "virtual methods table"
     48 // that a C++ compiler generates for a class. We have to make it explicit
     49 // because the Python API is based on C, and does not play well with C++
     50 // inheritance.
     51 
     52 #include <Python.h>
     53 
     54 #include <google/protobuf/descriptor.h>
     55 #include <google/protobuf/pyext/descriptor_containers.h>
     56 #include <google/protobuf/pyext/descriptor_pool.h>
     57 #include <google/protobuf/pyext/descriptor.h>
     58 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
     59 
     60 #if PY_MAJOR_VERSION >= 3
     61   #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
     62   #define PyString_FromFormat PyUnicode_FromFormat
     63   #define PyInt_FromLong PyLong_FromLong
     64   #if PY_VERSION_HEX < 0x03030000
     65     #error "Python 3.0 - 3.2 are not supported."
     66   #endif
     67   #define PyString_AsStringAndSize(ob, charpp, sizep) \
     68     (PyUnicode_Check(ob)? \
     69        ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
     70        PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
     71 #endif
     72 
     73 namespace google {
     74 namespace protobuf {
     75 namespace python {
     76 
     77 struct PyContainer;
     78 
     79 typedef int (*CountMethod)(PyContainer* self);
     80 typedef const void* (*GetByIndexMethod)(PyContainer* self, int index);
     81 typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name);
     82 typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self,
     83                                                 const string& name);
     84 typedef const void* (*GetByNumberMethod)(PyContainer* self, int index);
     85 typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor);
     86 typedef const string& (*GetItemNameMethod)(const void* descriptor);
     87 typedef const string& (*GetItemCamelcaseNameMethod)(const void* descriptor);
     88 typedef int (*GetItemNumberMethod)(const void* descriptor);
     89 typedef int (*GetItemIndexMethod)(const void* descriptor);
     90 
     91 struct DescriptorContainerDef {
     92   const char* mapping_name;
     93   // Returns the number of items in the container.
     94   CountMethod count_fn;
     95   // Retrieve item by index (usually the order of declaration in the proto file)
     96   // Used by sequences, but also iterators. 0 <= index < Count().
     97   GetByIndexMethod get_by_index_fn;
     98   // Retrieve item by name (usually a call to some 'FindByName' method).
     99   // Used by "by_name" mappings.
    100   GetByNameMethod get_by_name_fn;
    101   // Retrieve item by camelcase name (usually a call to some
    102   // 'FindByCamelcaseName' method). Used by "by_camelcase_name" mappings.
    103   GetByCamelcaseNameMethod get_by_camelcase_name_fn;
    104   // Retrieve item by declared number (field tag, or enum value).
    105   // Used by "by_number" mappings.
    106   GetByNumberMethod get_by_number_fn;
    107   // Converts a item C++ descriptor to a Python object. Returns a new reference.
    108   NewObjectFromItemMethod new_object_from_item_fn;
    109   // Retrieve the name of an item. Used by iterators on "by_name" mappings.
    110   GetItemNameMethod get_item_name_fn;
    111   // Retrieve the camelcase name of an item. Used by iterators on
    112   // "by_camelcase_name" mappings.
    113   GetItemCamelcaseNameMethod get_item_camelcase_name_fn;
    114   // Retrieve the number of an item. Used by iterators on "by_number" mappings.
    115   GetItemNumberMethod get_item_number_fn;
    116   // Retrieve the index of an item for the container type.
    117   // Used by "__contains__".
    118   // If not set, "x in sequence" will do a linear search.
    119   GetItemIndexMethod get_item_index_fn;
    120 };
    121 
    122 struct PyContainer {
    123   PyObject_HEAD
    124 
    125   // The proto2 descriptor this container belongs to the global DescriptorPool.
    126   const void* descriptor;
    127 
    128   // A pointer to a static structure with function pointers that control the
    129   // behavior of the container. Very similar to the table of virtual functions
    130   // of a C++ class.
    131   const DescriptorContainerDef* container_def;
    132 
    133   // The kind of container: list, or dict by name or value.
    134   enum ContainerKind {
    135     KIND_SEQUENCE,
    136     KIND_BYNAME,
    137     KIND_BYCAMELCASENAME,
    138     KIND_BYNUMBER,
    139   } kind;
    140 };
    141 
    142 struct PyContainerIterator {
    143   PyObject_HEAD
    144 
    145   // The container we are iterating over. Own a reference.
    146   PyContainer* container;
    147 
    148   // The current index in the iterator.
    149   int index;
    150 
    151   // The kind of container: list, or dict by name or value.
    152   enum IterKind {
    153     KIND_ITERKEY,
    154     KIND_ITERVALUE,
    155     KIND_ITERITEM,
    156     KIND_ITERVALUE_REVERSED,  // For sequences
    157   } kind;
    158 };
    159 
    160 namespace descriptor {
    161 
    162 // Returns the C++ item descriptor for a given Python key.
    163 // When the descriptor is found, return true and set *item.
    164 // When the descriptor is not found, return true, but set *item to NULL.
    165 // On error, returns false with an exception set.
    166 static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) {
    167   switch (self->kind) {
    168     case PyContainer::KIND_BYNAME:
    169       {
    170         char* name;
    171         Py_ssize_t name_size;
    172         if (PyString_AsStringAndSize(key, &name, &name_size) < 0) {
    173           if (PyErr_ExceptionMatches(PyExc_TypeError)) {
    174             // Not a string, cannot be in the container.
    175             PyErr_Clear();
    176             *item = NULL;
    177             return true;
    178           }
    179           return false;
    180         }
    181         *item = self->container_def->get_by_name_fn(
    182             self, string(name, name_size));
    183         return true;
    184       }
    185     case PyContainer::KIND_BYCAMELCASENAME:
    186       {
    187         char* camelcase_name;
    188         Py_ssize_t name_size;
    189         if (PyString_AsStringAndSize(key, &camelcase_name, &name_size) < 0) {
    190           if (PyErr_ExceptionMatches(PyExc_TypeError)) {
    191             // Not a string, cannot be in the container.
    192             PyErr_Clear();
    193             *item = NULL;
    194             return true;
    195           }
    196           return false;
    197         }
    198         *item = self->container_def->get_by_camelcase_name_fn(
    199             self, string(camelcase_name, name_size));
    200         return true;
    201       }
    202     case PyContainer::KIND_BYNUMBER:
    203       {
    204         Py_ssize_t number = PyNumber_AsSsize_t(key, NULL);
    205         if (number == -1 && PyErr_Occurred()) {
    206           if (PyErr_ExceptionMatches(PyExc_TypeError)) {
    207             // Not a number, cannot be in the container.
    208             PyErr_Clear();
    209             *item = NULL;
    210             return true;
    211           }
    212           return false;
    213         }
    214         *item = self->container_def->get_by_number_fn(self, number);
    215         return true;
    216       }
    217     default:
    218       PyErr_SetNone(PyExc_NotImplementedError);
    219       return false;
    220   }
    221 }
    222 
    223 // Returns the key of the object at the given index.
    224 // Used when iterating over mappings.
    225 static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) {
    226   const void* item = self->container_def->get_by_index_fn(self, index);
    227   switch (self->kind) {
    228     case PyContainer::KIND_BYNAME:
    229       {
    230         const string& name(self->container_def->get_item_name_fn(item));
    231         return PyString_FromStringAndSize(name.c_str(), name.size());
    232       }
    233     case PyContainer::KIND_BYCAMELCASENAME:
    234       {
    235         const string& name(
    236             self->container_def->get_item_camelcase_name_fn(item));
    237         return PyString_FromStringAndSize(name.c_str(), name.size());
    238       }
    239     case PyContainer::KIND_BYNUMBER:
    240       {
    241         int value = self->container_def->get_item_number_fn(item);
    242         return PyInt_FromLong(value);
    243       }
    244     default:
    245       PyErr_SetNone(PyExc_NotImplementedError);
    246       return NULL;
    247   }
    248 }
    249 
    250 // Returns the object at the given index.
    251 // Also used when iterating over mappings.
    252 static PyObject* _NewObj_ByIndex(PyContainer* self, Py_ssize_t index) {
    253   return self->container_def->new_object_from_item_fn(
    254       self->container_def->get_by_index_fn(self, index));
    255 }
    256 
    257 static Py_ssize_t Length(PyContainer* self) {
    258   return self->container_def->count_fn(self);
    259 }
    260 
    261 // The DescriptorMapping type.
    262 
    263 static PyObject* Subscript(PyContainer* self, PyObject* key) {
    264   const void* item = NULL;
    265   if (!_GetItemByKey(self, key, &item)) {
    266     return NULL;
    267   }
    268   if (!item) {
    269     PyErr_SetObject(PyExc_KeyError, key);
    270     return NULL;
    271   }
    272   return self->container_def->new_object_from_item_fn(item);
    273 }
    274 
    275 static int AssSubscript(PyContainer* self, PyObject* key, PyObject* value) {
    276   if (_CalledFromGeneratedFile(0)) {
    277     return 0;
    278   }
    279   PyErr_Format(PyExc_TypeError,
    280                "'%.200s' object does not support item assignment",
    281                Py_TYPE(self)->tp_name);
    282   return -1;
    283 }
    284 
    285 static PyMappingMethods MappingMappingMethods = {
    286   (lenfunc)Length,               // mp_length
    287   (binaryfunc)Subscript,         // mp_subscript
    288   (objobjargproc)AssSubscript,   // mp_ass_subscript
    289 };
    290 
    291 static int Contains(PyContainer* self, PyObject* key) {
    292   const void* item = NULL;
    293   if (!_GetItemByKey(self, key, &item)) {
    294     return -1;
    295   }
    296   if (item) {
    297     return 1;
    298   } else {
    299     return 0;
    300   }
    301 }
    302 
    303 static PyObject* ContainerRepr(PyContainer* self) {
    304   const char* kind = "";
    305   switch (self->kind) {
    306     case PyContainer::KIND_SEQUENCE:
    307       kind = "sequence";
    308       break;
    309     case PyContainer::KIND_BYNAME:
    310       kind = "mapping by name";
    311       break;
    312     case PyContainer::KIND_BYCAMELCASENAME:
    313       kind = "mapping by camelCase name";
    314       break;
    315     case PyContainer::KIND_BYNUMBER:
    316       kind = "mapping by number";
    317       break;
    318   }
    319   return PyString_FromFormat(
    320       "<%s %s>", self->container_def->mapping_name, kind);
    321 }
    322 
    323 extern PyTypeObject DescriptorMapping_Type;
    324 extern PyTypeObject DescriptorSequence_Type;
    325 
    326 // A sequence container can only be equal to another sequence container, or (for
    327 // backward compatibility) to a list containing the same items.
    328 // Returns 1 if equal, 0 if unequal, -1 on error.
    329 static int DescriptorSequence_Equal(PyContainer* self, PyObject* other) {
    330   // Check the identity of C++ pointers.
    331   if (PyObject_TypeCheck(other, &DescriptorSequence_Type)) {
    332     PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
    333     if (self->descriptor == other_container->descriptor &&
    334         self->container_def == other_container->container_def &&
    335         self->kind == other_container->kind) {
    336       return 1;
    337     } else {
    338       return 0;
    339     }
    340   }
    341 
    342   // If other is a list
    343   if (PyList_Check(other)) {
    344     // return list(self) == other
    345     int size = Length(self);
    346     if (size != PyList_Size(other)) {
    347       return false;
    348     }
    349     for (int index = 0; index < size; index++) {
    350       ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
    351       if (value1 == NULL) {
    352         return -1;
    353       }
    354       PyObject* value2 = PyList_GetItem(other, index);
    355       if (value2 == NULL) {
    356         return -1;
    357       }
    358       int cmp = PyObject_RichCompareBool(value1.get(), value2, Py_EQ);
    359       if (cmp != 1)  // error or not equal
    360           return cmp;
    361     }
    362     // All items were found and equal
    363     return 1;
    364   }
    365 
    366   // Any other object is different.
    367   return 0;
    368 }
    369 
    370 // A mapping container can only be equal to another mapping container, or (for
    371 // backward compatibility) to a dict containing the same items.
    372 // Returns 1 if equal, 0 if unequal, -1 on error.
    373 static int DescriptorMapping_Equal(PyContainer* self, PyObject* other) {
    374   // Check the identity of C++ pointers.
    375   if (PyObject_TypeCheck(other, &DescriptorMapping_Type)) {
    376     PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
    377     if (self->descriptor == other_container->descriptor &&
    378         self->container_def == other_container->container_def &&
    379         self->kind == other_container->kind) {
    380       return 1;
    381     } else {
    382       return 0;
    383     }
    384   }
    385 
    386   // If other is a dict
    387   if (PyDict_Check(other)) {
    388     // equivalent to dict(self.items()) == other
    389     int size = Length(self);
    390     if (size != PyDict_Size(other)) {
    391       return false;
    392     }
    393     for (int index = 0; index < size; index++) {
    394       ScopedPyObjectPtr key(_NewKey_ByIndex(self, index));
    395       if (key == NULL) {
    396         return -1;
    397       }
    398       ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
    399       if (value1 == NULL) {
    400         return -1;
    401       }
    402       PyObject* value2 = PyDict_GetItem(other, key.get());
    403       if (value2 == NULL) {
    404         // Not found in the other dictionary
    405         return 0;
    406       }
    407       int cmp = PyObject_RichCompareBool(value1.get(), value2, Py_EQ);
    408       if (cmp != 1)  // error or not equal
    409           return cmp;
    410     }
    411     // All items were found and equal
    412     return 1;
    413   }
    414 
    415   // Any other object is different.
    416   return 0;
    417 }
    418 
    419 static PyObject* RichCompare(PyContainer* self, PyObject* other, int opid) {
    420   if (opid != Py_EQ && opid != Py_NE) {
    421     Py_INCREF(Py_NotImplemented);
    422     return Py_NotImplemented;
    423   }
    424 
    425   int result;
    426 
    427   if (self->kind == PyContainer::KIND_SEQUENCE) {
    428     result = DescriptorSequence_Equal(self, other);
    429   } else {
    430     result = DescriptorMapping_Equal(self, other);
    431   }
    432   if (result < 0) {
    433     return NULL;
    434   }
    435   if (result ^ (opid == Py_NE)) {
    436     Py_RETURN_TRUE;
    437   } else {
    438     Py_RETURN_FALSE;
    439   }
    440 }
    441 
    442 static PySequenceMethods MappingSequenceMethods = {
    443     0,                      // sq_length
    444     0,                      // sq_concat
    445     0,                      // sq_repeat
    446     0,                      // sq_item
    447     0,                      // sq_slice
    448     0,                      // sq_ass_item
    449     0,                      // sq_ass_slice
    450     (objobjproc)Contains,   // sq_contains
    451 };
    452 
    453 static PyObject* Get(PyContainer* self, PyObject* args) {
    454   PyObject* key;
    455   PyObject* default_value = Py_None;
    456   if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
    457     return NULL;
    458   }
    459 
    460   const void* item;
    461   if (!_GetItemByKey(self, key, &item)) {
    462     return NULL;
    463   }
    464   if (item == NULL) {
    465     Py_INCREF(default_value);
    466     return default_value;
    467   }
    468   return self->container_def->new_object_from_item_fn(item);
    469 }
    470 
    471 static PyObject* Keys(PyContainer* self, PyObject* args) {
    472   Py_ssize_t count = Length(self);
    473   ScopedPyObjectPtr list(PyList_New(count));
    474   if (list == NULL) {
    475     return NULL;
    476   }
    477   for (Py_ssize_t index = 0; index < count; ++index) {
    478     PyObject* key = _NewKey_ByIndex(self, index);
    479     if (key == NULL) {
    480       return NULL;
    481     }
    482     PyList_SET_ITEM(list.get(), index, key);
    483   }
    484   return list.release();
    485 }
    486 
    487 static PyObject* Values(PyContainer* self, PyObject* args) {
    488   Py_ssize_t count = Length(self);
    489   ScopedPyObjectPtr list(PyList_New(count));
    490   if (list == NULL) {
    491     return NULL;
    492   }
    493   for (Py_ssize_t index = 0; index < count; ++index) {
    494     PyObject* value = _NewObj_ByIndex(self, index);
    495     if (value == NULL) {
    496       return NULL;
    497     }
    498     PyList_SET_ITEM(list.get(), index, value);
    499   }
    500   return list.release();
    501 }
    502 
    503 static PyObject* Items(PyContainer* self, PyObject* args) {
    504   Py_ssize_t count = Length(self);
    505   ScopedPyObjectPtr list(PyList_New(count));
    506   if (list == NULL) {
    507     return NULL;
    508   }
    509   for (Py_ssize_t index = 0; index < count; ++index) {
    510     ScopedPyObjectPtr obj(PyTuple_New(2));
    511     if (obj == NULL) {
    512       return NULL;
    513     }
    514     PyObject* key = _NewKey_ByIndex(self, index);
    515     if (key == NULL) {
    516       return NULL;
    517     }
    518     PyTuple_SET_ITEM(obj.get(), 0, key);
    519     PyObject* value = _NewObj_ByIndex(self, index);
    520     if (value == NULL) {
    521       return NULL;
    522     }
    523     PyTuple_SET_ITEM(obj.get(), 1, value);
    524     PyList_SET_ITEM(list.get(), index, obj.release());
    525   }
    526   return list.release();
    527 }
    528 
    529 static PyObject* NewContainerIterator(PyContainer* mapping,
    530                                       PyContainerIterator::IterKind kind);
    531 
    532 static PyObject* Iter(PyContainer* self) {
    533   return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
    534 }
    535 static PyObject* IterKeys(PyContainer* self, PyObject* args) {
    536   return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
    537 }
    538 static PyObject* IterValues(PyContainer* self, PyObject* args) {
    539   return NewContainerIterator(self, PyContainerIterator::KIND_ITERVALUE);
    540 }
    541 static PyObject* IterItems(PyContainer* self, PyObject* args) {
    542   return NewContainerIterator(self, PyContainerIterator::KIND_ITERITEM);
    543 }
    544 
    545 static PyMethodDef MappingMethods[] = {
    546   { "get", (PyCFunction)Get, METH_VARARGS, },
    547   { "keys", (PyCFunction)Keys, METH_NOARGS, },
    548   { "values", (PyCFunction)Values, METH_NOARGS, },
    549   { "items", (PyCFunction)Items, METH_NOARGS, },
    550   { "iterkeys", (PyCFunction)IterKeys, METH_NOARGS, },
    551   { "itervalues", (PyCFunction)IterValues, METH_NOARGS, },
    552   { "iteritems", (PyCFunction)IterItems, METH_NOARGS, },
    553   {NULL}
    554 };
    555 
    556 PyTypeObject DescriptorMapping_Type = {
    557   PyVarObject_HEAD_INIT(&PyType_Type, 0)
    558   "DescriptorMapping",                  // tp_name
    559   sizeof(PyContainer),                  // tp_basicsize
    560   0,                                    // tp_itemsize
    561   0,                                    // tp_dealloc
    562   0,                                    // tp_print
    563   0,                                    // tp_getattr
    564   0,                                    // tp_setattr
    565   0,                                    // tp_compare
    566   (reprfunc)ContainerRepr,              // tp_repr
    567   0,                                    // tp_as_number
    568   &MappingSequenceMethods,              // tp_as_sequence
    569   &MappingMappingMethods,               // tp_as_mapping
    570   0,                                    // tp_hash
    571   0,                                    // tp_call
    572   0,                                    // tp_str
    573   0,                                    // tp_getattro
    574   0,                                    // tp_setattro
    575   0,                                    // tp_as_buffer
    576   Py_TPFLAGS_DEFAULT,                   // tp_flags
    577   0,                                    // tp_doc
    578   0,                                    // tp_traverse
    579   0,                                    // tp_clear
    580   (richcmpfunc)RichCompare,             // tp_richcompare
    581   0,                                    // tp_weaklistoffset
    582   (getiterfunc)Iter,                    // tp_iter
    583   0,                                    // tp_iternext
    584   MappingMethods,                       // tp_methods
    585   0,                                    // tp_members
    586   0,                                    // tp_getset
    587   0,                                    // tp_base
    588   0,                                    // tp_dict
    589   0,                                    // tp_descr_get
    590   0,                                    // tp_descr_set
    591   0,                                    // tp_dictoffset
    592   0,                                    // tp_init
    593   0,                                    // tp_alloc
    594   0,                                    // tp_new
    595   0,                                    // tp_free
    596 };
    597 
    598 // The DescriptorSequence type.
    599 
    600 static PyObject* GetItem(PyContainer* self, Py_ssize_t index) {
    601   if (index < 0) {
    602     index += Length(self);
    603   }
    604   if (index < 0 || index >= Length(self)) {
    605     PyErr_SetString(PyExc_IndexError, "index out of range");
    606     return NULL;
    607   }
    608   return _NewObj_ByIndex(self, index);
    609 }
    610 
    611 // Returns the position of the item in the sequence, of -1 if not found.
    612 // This function never fails.
    613 int Find(PyContainer* self, PyObject* item) {
    614   // The item can only be in one position: item.index.
    615   // Check that self[item.index] == item, it's faster than a linear search.
    616   //
    617   // This assumes that sequences are only defined by syntax of the .proto file:
    618   // a specific item belongs to only one sequence, depending on its position in
    619   // the .proto file definition.
    620   const void* descriptor_ptr = PyDescriptor_AsVoidPtr(item);
    621   if (descriptor_ptr == NULL) {
    622     // Not a descriptor, it cannot be in the list.
    623     return -1;
    624   }
    625   if (self->container_def->get_item_index_fn) {
    626     int index = self->container_def->get_item_index_fn(descriptor_ptr);
    627     if (index < 0 || index >= Length(self)) {
    628       // This index is not from this collection.
    629       return -1;
    630     }
    631     if (self->container_def->get_by_index_fn(self, index) != descriptor_ptr) {
    632       // The descriptor at this index is not the same.
    633       return -1;
    634     }
    635     // self[item.index] == item, so return the index.
    636     return index;
    637   } else {
    638     // Fall back to linear search.
    639     int length = Length(self);
    640     for (int index=0; index < length; index++) {
    641       if (self->container_def->get_by_index_fn(self, index) == descriptor_ptr) {
    642         return index;
    643       }
    644     }
    645     // Not found
    646     return -1;
    647   }
    648 }
    649 
    650 // Implements list.index(): the position of the item is in the sequence.
    651 static PyObject* Index(PyContainer* self, PyObject* item) {
    652   int position = Find(self, item);
    653   if (position < 0) {
    654     // Not found
    655     PyErr_SetNone(PyExc_ValueError);
    656     return NULL;
    657   } else {
    658     return PyInt_FromLong(position);
    659   }
    660 }
    661 // Implements "list.__contains__()": is the object in the sequence.
    662 static int SeqContains(PyContainer* self, PyObject* item) {
    663   int position = Find(self, item);
    664   if (position < 0) {
    665     return 0;
    666   } else {
    667     return 1;
    668   }
    669 }
    670 
    671 // Implements list.count(): number of occurrences of the item in the sequence.
    672 // An item can only appear once in a sequence. If it exists, return 1.
    673 static PyObject* Count(PyContainer* self, PyObject* item) {
    674   int position = Find(self, item);
    675   if (position < 0) {
    676     return PyInt_FromLong(0);
    677   } else {
    678     return PyInt_FromLong(1);
    679   }
    680 }
    681 
    682 static PyObject* Append(PyContainer* self, PyObject* args) {
    683   if (_CalledFromGeneratedFile(0)) {
    684     Py_RETURN_NONE;
    685   }
    686   PyErr_Format(PyExc_TypeError,
    687                "'%.200s' object is not a mutable sequence",
    688                Py_TYPE(self)->tp_name);
    689   return NULL;
    690 }
    691 
    692 static PyObject* Reversed(PyContainer* self, PyObject* args) {
    693   return NewContainerIterator(self,
    694                               PyContainerIterator::KIND_ITERVALUE_REVERSED);
    695 }
    696 
    697 static PyMethodDef SeqMethods[] = {
    698   { "index", (PyCFunction)Index, METH_O, },
    699   { "count", (PyCFunction)Count, METH_O, },
    700   { "append", (PyCFunction)Append, METH_O, },
    701   { "__reversed__", (PyCFunction)Reversed, METH_NOARGS, },
    702   {NULL}
    703 };
    704 
    705 static PySequenceMethods SeqSequenceMethods = {
    706     (lenfunc)Length,          // sq_length
    707     0,                        // sq_concat
    708     0,                        // sq_repeat
    709     (ssizeargfunc)GetItem,    // sq_item
    710     0,                        // sq_slice
    711     0,                        // sq_ass_item
    712     0,                        // sq_ass_slice
    713     (objobjproc)SeqContains,  // sq_contains
    714 };
    715 
    716 PyTypeObject DescriptorSequence_Type = {
    717   PyVarObject_HEAD_INIT(&PyType_Type, 0)
    718   "DescriptorSequence",                 // tp_name
    719   sizeof(PyContainer),                  // tp_basicsize
    720   0,                                    // tp_itemsize
    721   0,                                    // tp_dealloc
    722   0,                                    // tp_print
    723   0,                                    // tp_getattr
    724   0,                                    // tp_setattr
    725   0,                                    // tp_compare
    726   (reprfunc)ContainerRepr,              // tp_repr
    727   0,                                    // tp_as_number
    728   &SeqSequenceMethods,                  // tp_as_sequence
    729   0,                                    // tp_as_mapping
    730   0,                                    // tp_hash
    731   0,                                    // tp_call
    732   0,                                    // tp_str
    733   0,                                    // tp_getattro
    734   0,                                    // tp_setattro
    735   0,                                    // tp_as_buffer
    736   Py_TPFLAGS_DEFAULT,                   // tp_flags
    737   0,                                    // tp_doc
    738   0,                                    // tp_traverse
    739   0,                                    // tp_clear
    740   (richcmpfunc)RichCompare,             // tp_richcompare
    741   0,                                    // tp_weaklistoffset
    742   0,                                    // tp_iter
    743   0,                                    // tp_iternext
    744   SeqMethods,                           // tp_methods
    745   0,                                    // tp_members
    746   0,                                    // tp_getset
    747   0,                                    // tp_base
    748   0,                                    // tp_dict
    749   0,                                    // tp_descr_get
    750   0,                                    // tp_descr_set
    751   0,                                    // tp_dictoffset
    752   0,                                    // tp_init
    753   0,                                    // tp_alloc
    754   0,                                    // tp_new
    755   0,                                    // tp_free
    756 };
    757 
    758 static PyObject* NewMappingByName(
    759     DescriptorContainerDef* container_def, const void* descriptor) {
    760   PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
    761   if (self == NULL) {
    762     return NULL;
    763   }
    764   self->descriptor = descriptor;
    765   self->container_def = container_def;
    766   self->kind = PyContainer::KIND_BYNAME;
    767   return reinterpret_cast<PyObject*>(self);
    768 }
    769 
    770 static PyObject* NewMappingByCamelcaseName(
    771     DescriptorContainerDef* container_def, const void* descriptor) {
    772   PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
    773   if (self == NULL) {
    774     return NULL;
    775   }
    776   self->descriptor = descriptor;
    777   self->container_def = container_def;
    778   self->kind = PyContainer::KIND_BYCAMELCASENAME;
    779   return reinterpret_cast<PyObject*>(self);
    780 }
    781 
    782 static PyObject* NewMappingByNumber(
    783     DescriptorContainerDef* container_def, const void* descriptor) {
    784   if (container_def->get_by_number_fn == NULL ||
    785       container_def->get_item_number_fn == NULL) {
    786     PyErr_SetNone(PyExc_NotImplementedError);
    787     return NULL;
    788   }
    789   PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
    790   if (self == NULL) {
    791     return NULL;
    792   }
    793   self->descriptor = descriptor;
    794   self->container_def = container_def;
    795   self->kind = PyContainer::KIND_BYNUMBER;
    796   return reinterpret_cast<PyObject*>(self);
    797 }
    798 
    799 static PyObject* NewSequence(
    800     DescriptorContainerDef* container_def, const void* descriptor) {
    801   PyContainer* self = PyObject_New(PyContainer, &DescriptorSequence_Type);
    802   if (self == NULL) {
    803     return NULL;
    804   }
    805   self->descriptor = descriptor;
    806   self->container_def = container_def;
    807   self->kind = PyContainer::KIND_SEQUENCE;
    808   return reinterpret_cast<PyObject*>(self);
    809 }
    810 
    811 // Implement iterators over PyContainers.
    812 
    813 static void Iterator_Dealloc(PyContainerIterator* self) {
    814   Py_CLEAR(self->container);
    815   Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
    816 }
    817 
    818 static PyObject* Iterator_Next(PyContainerIterator* self) {
    819   int count = self->container->container_def->count_fn(self->container);
    820   if (self->index >= count) {
    821     // Return NULL with no exception to indicate the end.
    822     return NULL;
    823   }
    824   int index = self->index;
    825   self->index += 1;
    826   switch (self->kind) {
    827     case PyContainerIterator::KIND_ITERKEY:
    828       return _NewKey_ByIndex(self->container, index);
    829     case PyContainerIterator::KIND_ITERVALUE:
    830       return _NewObj_ByIndex(self->container, index);
    831     case PyContainerIterator::KIND_ITERVALUE_REVERSED:
    832       return _NewObj_ByIndex(self->container, count - index - 1);
    833     case PyContainerIterator::KIND_ITERITEM:
    834       {
    835         PyObject* obj = PyTuple_New(2);
    836         if (obj == NULL) {
    837           return NULL;
    838         }
    839         PyObject* key = _NewKey_ByIndex(self->container, index);
    840         if (key == NULL) {
    841           Py_DECREF(obj);
    842           return NULL;
    843         }
    844         PyTuple_SET_ITEM(obj, 0, key);
    845         PyObject* value = _NewObj_ByIndex(self->container, index);
    846         if (value == NULL) {
    847           Py_DECREF(obj);
    848           return NULL;
    849         }
    850         PyTuple_SET_ITEM(obj, 1, value);
    851         return obj;
    852       }
    853     default:
    854       PyErr_SetNone(PyExc_NotImplementedError);
    855       return NULL;
    856   }
    857 }
    858 
    859 static PyTypeObject ContainerIterator_Type = {
    860   PyVarObject_HEAD_INIT(&PyType_Type, 0)
    861   "DescriptorContainerIterator",        // tp_name
    862   sizeof(PyContainerIterator),          // tp_basicsize
    863   0,                                    // tp_itemsize
    864   (destructor)Iterator_Dealloc,         // tp_dealloc
    865   0,                                    // tp_print
    866   0,                                    // tp_getattr
    867   0,                                    // tp_setattr
    868   0,                                    // tp_compare
    869   0,                                    // tp_repr
    870   0,                                    // tp_as_number
    871   0,                                    // tp_as_sequence
    872   0,                                    // tp_as_mapping
    873   0,                                    // tp_hash
    874   0,                                    // tp_call
    875   0,                                    // tp_str
    876   0,                                    // tp_getattro
    877   0,                                    // tp_setattro
    878   0,                                    // tp_as_buffer
    879   Py_TPFLAGS_DEFAULT,                   // tp_flags
    880   0,                                    // tp_doc
    881   0,                                    // tp_traverse
    882   0,                                    // tp_clear
    883   0,                                    // tp_richcompare
    884   0,                                    // tp_weaklistoffset
    885   PyObject_SelfIter,                    // tp_iter
    886   (iternextfunc)Iterator_Next,          // tp_iternext
    887   0,                                    // tp_methods
    888   0,                                    // tp_members
    889   0,                                    // tp_getset
    890   0,                                    // tp_base
    891   0,                                    // tp_dict
    892   0,                                    // tp_descr_get
    893   0,                                    // tp_descr_set
    894   0,                                    // tp_dictoffset
    895   0,                                    // tp_init
    896   0,                                    // tp_alloc
    897   0,                                    // tp_new
    898   0,                                    // tp_free
    899 };
    900 
    901 static PyObject* NewContainerIterator(PyContainer* container,
    902                                       PyContainerIterator::IterKind kind) {
    903   PyContainerIterator* self = PyObject_New(PyContainerIterator,
    904                                            &ContainerIterator_Type);
    905   if (self == NULL) {
    906     return NULL;
    907   }
    908   Py_INCREF(container);
    909   self->container = container;
    910   self->kind = kind;
    911   self->index = 0;
    912 
    913   return reinterpret_cast<PyObject*>(self);
    914 }
    915 
    916 }  // namespace descriptor
    917 
    918 // Now define the real collections!
    919 
    920 namespace message_descriptor {
    921 
    922 typedef const Descriptor* ParentDescriptor;
    923 
    924 static ParentDescriptor GetDescriptor(PyContainer* self) {
    925   return reinterpret_cast<ParentDescriptor>(self->descriptor);
    926 }
    927 
    928 namespace fields {
    929 
    930 typedef const FieldDescriptor* ItemDescriptor;
    931 
    932 static int Count(PyContainer* self) {
    933   return GetDescriptor(self)->field_count();
    934 }
    935 
    936 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
    937   return GetDescriptor(self)->FindFieldByName(name);
    938 }
    939 
    940 static ItemDescriptor GetByCamelcaseName(PyContainer* self,
    941                                          const string& name) {
    942   return GetDescriptor(self)->FindFieldByCamelcaseName(name);
    943 }
    944 
    945 static ItemDescriptor GetByNumber(PyContainer* self, int number) {
    946   return GetDescriptor(self)->FindFieldByNumber(number);
    947 }
    948 
    949 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
    950   return GetDescriptor(self)->field(index);
    951 }
    952 
    953 static PyObject* NewObjectFromItem(ItemDescriptor item) {
    954   return PyFieldDescriptor_FromDescriptor(item);
    955 }
    956 
    957 static const string& GetItemName(ItemDescriptor item) {
    958   return item->name();
    959 }
    960 
    961 static const string& GetItemCamelcaseName(ItemDescriptor item) {
    962   return item->camelcase_name();
    963 }
    964 
    965 static int GetItemNumber(ItemDescriptor item) {
    966   return item->number();
    967 }
    968 
    969 static int GetItemIndex(ItemDescriptor item) {
    970   return item->index();
    971 }
    972 
    973 static DescriptorContainerDef ContainerDef = {
    974   "MessageFields",
    975   (CountMethod)Count,
    976   (GetByIndexMethod)GetByIndex,
    977   (GetByNameMethod)GetByName,
    978   (GetByCamelcaseNameMethod)GetByCamelcaseName,
    979   (GetByNumberMethod)GetByNumber,
    980   (NewObjectFromItemMethod)NewObjectFromItem,
    981   (GetItemNameMethod)GetItemName,
    982   (GetItemCamelcaseNameMethod)GetItemCamelcaseName,
    983   (GetItemNumberMethod)GetItemNumber,
    984   (GetItemIndexMethod)GetItemIndex,
    985 };
    986 
    987 }  // namespace fields
    988 
    989 PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) {
    990   return descriptor::NewMappingByName(&fields::ContainerDef, descriptor);
    991 }
    992 
    993 PyObject* NewMessageFieldsByCamelcaseName(ParentDescriptor descriptor) {
    994   return descriptor::NewMappingByCamelcaseName(&fields::ContainerDef,
    995                                                descriptor);
    996 }
    997 
    998 PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) {
    999   return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor);
   1000 }
   1001 
   1002 PyObject* NewMessageFieldsSeq(ParentDescriptor descriptor) {
   1003   return descriptor::NewSequence(&fields::ContainerDef, descriptor);
   1004 }
   1005 
   1006 namespace nested_types {
   1007 
   1008 typedef const Descriptor* ItemDescriptor;
   1009 
   1010 static int Count(PyContainer* self) {
   1011   return GetDescriptor(self)->nested_type_count();
   1012 }
   1013 
   1014 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
   1015   return GetDescriptor(self)->FindNestedTypeByName(name);
   1016 }
   1017 
   1018 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1019   return GetDescriptor(self)->nested_type(index);
   1020 }
   1021 
   1022 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1023   return PyMessageDescriptor_FromDescriptor(item);
   1024 }
   1025 
   1026 static const string& GetItemName(ItemDescriptor item) {
   1027   return item->name();
   1028 }
   1029 
   1030 static int GetItemIndex(ItemDescriptor item) {
   1031   return item->index();
   1032 }
   1033 
   1034 static DescriptorContainerDef ContainerDef = {
   1035   "MessageNestedTypes",
   1036   (CountMethod)Count,
   1037   (GetByIndexMethod)GetByIndex,
   1038   (GetByNameMethod)GetByName,
   1039   (GetByCamelcaseNameMethod)NULL,
   1040   (GetByNumberMethod)NULL,
   1041   (NewObjectFromItemMethod)NewObjectFromItem,
   1042   (GetItemNameMethod)GetItemName,
   1043   (GetItemCamelcaseNameMethod)NULL,
   1044   (GetItemNumberMethod)NULL,
   1045   (GetItemIndexMethod)GetItemIndex,
   1046 };
   1047 
   1048 }  // namespace nested_types
   1049 
   1050 PyObject* NewMessageNestedTypesSeq(ParentDescriptor descriptor) {
   1051   return descriptor::NewSequence(&nested_types::ContainerDef, descriptor);
   1052 }
   1053 
   1054 PyObject* NewMessageNestedTypesByName(ParentDescriptor descriptor) {
   1055   return descriptor::NewMappingByName(&nested_types::ContainerDef, descriptor);
   1056 }
   1057 
   1058 namespace enums {
   1059 
   1060 typedef const EnumDescriptor* ItemDescriptor;
   1061 
   1062 static int Count(PyContainer* self) {
   1063   return GetDescriptor(self)->enum_type_count();
   1064 }
   1065 
   1066 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
   1067   return GetDescriptor(self)->FindEnumTypeByName(name);
   1068 }
   1069 
   1070 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1071   return GetDescriptor(self)->enum_type(index);
   1072 }
   1073 
   1074 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1075   return PyEnumDescriptor_FromDescriptor(item);
   1076 }
   1077 
   1078 static const string& GetItemName(ItemDescriptor item) {
   1079   return item->name();
   1080 }
   1081 
   1082 static int GetItemIndex(ItemDescriptor item) {
   1083   return item->index();
   1084 }
   1085 
   1086 static DescriptorContainerDef ContainerDef = {
   1087   "MessageNestedEnums",
   1088   (CountMethod)Count,
   1089   (GetByIndexMethod)GetByIndex,
   1090   (GetByNameMethod)GetByName,
   1091   (GetByCamelcaseNameMethod)NULL,
   1092   (GetByNumberMethod)NULL,
   1093   (NewObjectFromItemMethod)NewObjectFromItem,
   1094   (GetItemNameMethod)GetItemName,
   1095   (GetItemCamelcaseNameMethod)NULL,
   1096   (GetItemNumberMethod)NULL,
   1097   (GetItemIndexMethod)GetItemIndex,
   1098 };
   1099 
   1100 }  // namespace enums
   1101 
   1102 PyObject* NewMessageEnumsByName(ParentDescriptor descriptor) {
   1103   return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
   1104 }
   1105 
   1106 PyObject* NewMessageEnumsSeq(ParentDescriptor descriptor) {
   1107   return descriptor::NewSequence(&enums::ContainerDef, descriptor);
   1108 }
   1109 
   1110 namespace enumvalues {
   1111 
   1112 // This is the "enum_values_by_name" mapping, which collects values from all
   1113 // enum types in a message.
   1114 //
   1115 // Note that the behavior of the C++ descriptor is different: it will search and
   1116 // return the first value that matches the name, whereas the Python
   1117 // implementation retrieves the last one.
   1118 
   1119 typedef const EnumValueDescriptor* ItemDescriptor;
   1120 
   1121 static int Count(PyContainer* self) {
   1122   int count = 0;
   1123   for (int i = 0; i < GetDescriptor(self)->enum_type_count(); ++i) {
   1124     count += GetDescriptor(self)->enum_type(i)->value_count();
   1125   }
   1126   return count;
   1127 }
   1128 
   1129 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
   1130   return GetDescriptor(self)->FindEnumValueByName(name);
   1131 }
   1132 
   1133 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1134   // This is not optimal, but the number of enums *types* in a given message
   1135   // is small.  This function is only used when iterating over the mapping.
   1136   const EnumDescriptor* enum_type = NULL;
   1137   int enum_type_count = GetDescriptor(self)->enum_type_count();
   1138   for (int i = 0; i < enum_type_count; ++i) {
   1139     enum_type = GetDescriptor(self)->enum_type(i);
   1140     int enum_value_count = enum_type->value_count();
   1141     if (index < enum_value_count) {
   1142       // Found it!
   1143       break;
   1144     }
   1145     index -= enum_value_count;
   1146   }
   1147   // The next statement cannot overflow, because this function is only called by
   1148   // internal iterators which ensure that 0 <= index < Count().
   1149   return enum_type->value(index);
   1150 }
   1151 
   1152 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1153   return PyEnumValueDescriptor_FromDescriptor(item);
   1154 }
   1155 
   1156 static const string& GetItemName(ItemDescriptor item) {
   1157   return item->name();
   1158 }
   1159 
   1160 static DescriptorContainerDef ContainerDef = {
   1161   "MessageEnumValues",
   1162   (CountMethod)Count,
   1163   (GetByIndexMethod)GetByIndex,
   1164   (GetByNameMethod)GetByName,
   1165   (GetByCamelcaseNameMethod)NULL,
   1166   (GetByNumberMethod)NULL,
   1167   (NewObjectFromItemMethod)NewObjectFromItem,
   1168   (GetItemNameMethod)GetItemName,
   1169   (GetItemCamelcaseNameMethod)NULL,
   1170   (GetItemNumberMethod)NULL,
   1171   (GetItemIndexMethod)NULL,
   1172 };
   1173 
   1174 }  // namespace enumvalues
   1175 
   1176 PyObject* NewMessageEnumValuesByName(ParentDescriptor descriptor) {
   1177   return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
   1178 }
   1179 
   1180 namespace extensions {
   1181 
   1182 typedef const FieldDescriptor* ItemDescriptor;
   1183 
   1184 static int Count(PyContainer* self) {
   1185   return GetDescriptor(self)->extension_count();
   1186 }
   1187 
   1188 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
   1189   return GetDescriptor(self)->FindExtensionByName(name);
   1190 }
   1191 
   1192 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1193   return GetDescriptor(self)->extension(index);
   1194 }
   1195 
   1196 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1197   return PyFieldDescriptor_FromDescriptor(item);
   1198 }
   1199 
   1200 static const string& GetItemName(ItemDescriptor item) {
   1201   return item->name();
   1202 }
   1203 
   1204 static int GetItemIndex(ItemDescriptor item) {
   1205   return item->index();
   1206 }
   1207 
   1208 static DescriptorContainerDef ContainerDef = {
   1209   "MessageExtensions",
   1210   (CountMethod)Count,
   1211   (GetByIndexMethod)GetByIndex,
   1212   (GetByNameMethod)GetByName,
   1213   (GetByCamelcaseNameMethod)NULL,
   1214   (GetByNumberMethod)NULL,
   1215   (NewObjectFromItemMethod)NewObjectFromItem,
   1216   (GetItemNameMethod)GetItemName,
   1217   (GetItemCamelcaseNameMethod)NULL,
   1218   (GetItemNumberMethod)NULL,
   1219   (GetItemIndexMethod)GetItemIndex,
   1220 };
   1221 
   1222 }  // namespace extensions
   1223 
   1224 PyObject* NewMessageExtensionsByName(ParentDescriptor descriptor) {
   1225   return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
   1226 }
   1227 
   1228 PyObject* NewMessageExtensionsSeq(ParentDescriptor descriptor) {
   1229   return descriptor::NewSequence(&extensions::ContainerDef, descriptor);
   1230 }
   1231 
   1232 namespace oneofs {
   1233 
   1234 typedef const OneofDescriptor* ItemDescriptor;
   1235 
   1236 static int Count(PyContainer* self) {
   1237   return GetDescriptor(self)->oneof_decl_count();
   1238 }
   1239 
   1240 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
   1241   return GetDescriptor(self)->FindOneofByName(name);
   1242 }
   1243 
   1244 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1245   return GetDescriptor(self)->oneof_decl(index);
   1246 }
   1247 
   1248 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1249   return PyOneofDescriptor_FromDescriptor(item);
   1250 }
   1251 
   1252 static const string& GetItemName(ItemDescriptor item) {
   1253   return item->name();
   1254 }
   1255 
   1256 static int GetItemIndex(ItemDescriptor item) {
   1257   return item->index();
   1258 }
   1259 
   1260 static DescriptorContainerDef ContainerDef = {
   1261   "MessageOneofs",
   1262   (CountMethod)Count,
   1263   (GetByIndexMethod)GetByIndex,
   1264   (GetByNameMethod)GetByName,
   1265   (GetByCamelcaseNameMethod)NULL,
   1266   (GetByNumberMethod)NULL,
   1267   (NewObjectFromItemMethod)NewObjectFromItem,
   1268   (GetItemNameMethod)GetItemName,
   1269   (GetItemCamelcaseNameMethod)NULL,
   1270   (GetItemNumberMethod)NULL,
   1271   (GetItemIndexMethod)GetItemIndex,
   1272 };
   1273 
   1274 }  // namespace oneofs
   1275 
   1276 PyObject* NewMessageOneofsByName(ParentDescriptor descriptor) {
   1277   return descriptor::NewMappingByName(&oneofs::ContainerDef, descriptor);
   1278 }
   1279 
   1280 PyObject* NewMessageOneofsSeq(ParentDescriptor descriptor) {
   1281   return descriptor::NewSequence(&oneofs::ContainerDef, descriptor);
   1282 }
   1283 
   1284 }  // namespace message_descriptor
   1285 
   1286 namespace enum_descriptor {
   1287 
   1288 typedef const EnumDescriptor* ParentDescriptor;
   1289 
   1290 static ParentDescriptor GetDescriptor(PyContainer* self) {
   1291   return reinterpret_cast<ParentDescriptor>(self->descriptor);
   1292 }
   1293 
   1294 namespace enumvalues {
   1295 
   1296 typedef const EnumValueDescriptor* ItemDescriptor;
   1297 
   1298 static int Count(PyContainer* self) {
   1299   return GetDescriptor(self)->value_count();
   1300 }
   1301 
   1302 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1303   return GetDescriptor(self)->value(index);
   1304 }
   1305 
   1306 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
   1307   return GetDescriptor(self)->FindValueByName(name);
   1308 }
   1309 
   1310 static ItemDescriptor GetByNumber(PyContainer* self, int number) {
   1311   return GetDescriptor(self)->FindValueByNumber(number);
   1312 }
   1313 
   1314 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1315   return PyEnumValueDescriptor_FromDescriptor(item);
   1316 }
   1317 
   1318 static const string& GetItemName(ItemDescriptor item) {
   1319   return item->name();
   1320 }
   1321 
   1322 static int GetItemNumber(ItemDescriptor item) {
   1323   return item->number();
   1324 }
   1325 
   1326 static int GetItemIndex(ItemDescriptor item) {
   1327   return item->index();
   1328 }
   1329 
   1330 static DescriptorContainerDef ContainerDef = {
   1331   "EnumValues",
   1332   (CountMethod)Count,
   1333   (GetByIndexMethod)GetByIndex,
   1334   (GetByNameMethod)GetByName,
   1335   (GetByCamelcaseNameMethod)NULL,
   1336   (GetByNumberMethod)GetByNumber,
   1337   (NewObjectFromItemMethod)NewObjectFromItem,
   1338   (GetItemNameMethod)GetItemName,
   1339   (GetItemCamelcaseNameMethod)NULL,
   1340   (GetItemNumberMethod)GetItemNumber,
   1341   (GetItemIndexMethod)GetItemIndex,
   1342 };
   1343 
   1344 }  // namespace enumvalues
   1345 
   1346 PyObject* NewEnumValuesByName(ParentDescriptor descriptor) {
   1347   return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
   1348 }
   1349 
   1350 PyObject* NewEnumValuesByNumber(ParentDescriptor descriptor) {
   1351   return descriptor::NewMappingByNumber(&enumvalues::ContainerDef, descriptor);
   1352 }
   1353 
   1354 PyObject* NewEnumValuesSeq(ParentDescriptor descriptor) {
   1355   return descriptor::NewSequence(&enumvalues::ContainerDef, descriptor);
   1356 }
   1357 
   1358 }  // namespace enum_descriptor
   1359 
   1360 namespace oneof_descriptor {
   1361 
   1362 typedef const OneofDescriptor* ParentDescriptor;
   1363 
   1364 static ParentDescriptor GetDescriptor(PyContainer* self) {
   1365   return reinterpret_cast<ParentDescriptor>(self->descriptor);
   1366 }
   1367 
   1368 namespace fields {
   1369 
   1370 typedef const FieldDescriptor* ItemDescriptor;
   1371 
   1372 static int Count(PyContainer* self) {
   1373   return GetDescriptor(self)->field_count();
   1374 }
   1375 
   1376 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1377   return GetDescriptor(self)->field(index);
   1378 }
   1379 
   1380 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1381   return PyFieldDescriptor_FromDescriptor(item);
   1382 }
   1383 
   1384 static int GetItemIndex(ItemDescriptor item) {
   1385   return item->index_in_oneof();
   1386 }
   1387 
   1388 static DescriptorContainerDef ContainerDef = {
   1389   "OneofFields",
   1390   (CountMethod)Count,
   1391   (GetByIndexMethod)GetByIndex,
   1392   (GetByNameMethod)NULL,
   1393   (GetByCamelcaseNameMethod)NULL,
   1394   (GetByNumberMethod)NULL,
   1395   (NewObjectFromItemMethod)NewObjectFromItem,
   1396   (GetItemNameMethod)NULL,
   1397   (GetItemCamelcaseNameMethod)NULL,
   1398   (GetItemNumberMethod)NULL,
   1399   (GetItemIndexMethod)GetItemIndex,
   1400 };
   1401 
   1402 }  // namespace fields
   1403 
   1404 PyObject* NewOneofFieldsSeq(ParentDescriptor descriptor) {
   1405   return descriptor::NewSequence(&fields::ContainerDef, descriptor);
   1406 }
   1407 
   1408 }  // namespace oneof_descriptor
   1409 
   1410 namespace file_descriptor {
   1411 
   1412 typedef const FileDescriptor* ParentDescriptor;
   1413 
   1414 static ParentDescriptor GetDescriptor(PyContainer* self) {
   1415   return reinterpret_cast<ParentDescriptor>(self->descriptor);
   1416 }
   1417 
   1418 namespace messages {
   1419 
   1420 typedef const Descriptor* ItemDescriptor;
   1421 
   1422 static int Count(PyContainer* self) {
   1423   return GetDescriptor(self)->message_type_count();
   1424 }
   1425 
   1426 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
   1427   return GetDescriptor(self)->FindMessageTypeByName(name);
   1428 }
   1429 
   1430 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1431   return GetDescriptor(self)->message_type(index);
   1432 }
   1433 
   1434 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1435   return PyMessageDescriptor_FromDescriptor(item);
   1436 }
   1437 
   1438 static const string& GetItemName(ItemDescriptor item) {
   1439   return item->name();
   1440 }
   1441 
   1442 static int GetItemIndex(ItemDescriptor item) {
   1443   return item->index();
   1444 }
   1445 
   1446 static DescriptorContainerDef ContainerDef = {
   1447   "FileMessages",
   1448   (CountMethod)Count,
   1449   (GetByIndexMethod)GetByIndex,
   1450   (GetByNameMethod)GetByName,
   1451   (GetByCamelcaseNameMethod)NULL,
   1452   (GetByNumberMethod)NULL,
   1453   (NewObjectFromItemMethod)NewObjectFromItem,
   1454   (GetItemNameMethod)GetItemName,
   1455   (GetItemCamelcaseNameMethod)NULL,
   1456   (GetItemNumberMethod)NULL,
   1457   (GetItemIndexMethod)GetItemIndex,
   1458 };
   1459 
   1460 }  // namespace messages
   1461 
   1462 PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor) {
   1463   return descriptor::NewMappingByName(&messages::ContainerDef, descriptor);
   1464 }
   1465 
   1466 namespace enums {
   1467 
   1468 typedef const EnumDescriptor* ItemDescriptor;
   1469 
   1470 static int Count(PyContainer* self) {
   1471   return GetDescriptor(self)->enum_type_count();
   1472 }
   1473 
   1474 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
   1475   return GetDescriptor(self)->FindEnumTypeByName(name);
   1476 }
   1477 
   1478 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1479   return GetDescriptor(self)->enum_type(index);
   1480 }
   1481 
   1482 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1483   return PyEnumDescriptor_FromDescriptor(item);
   1484 }
   1485 
   1486 static const string& GetItemName(ItemDescriptor item) {
   1487   return item->name();
   1488 }
   1489 
   1490 static int GetItemIndex(ItemDescriptor item) {
   1491   return item->index();
   1492 }
   1493 
   1494 static DescriptorContainerDef ContainerDef = {
   1495   "FileEnums",
   1496   (CountMethod)Count,
   1497   (GetByIndexMethod)GetByIndex,
   1498   (GetByNameMethod)GetByName,
   1499   (GetByCamelcaseNameMethod)NULL,
   1500   (GetByNumberMethod)NULL,
   1501   (NewObjectFromItemMethod)NewObjectFromItem,
   1502   (GetItemNameMethod)GetItemName,
   1503   (GetItemCamelcaseNameMethod)NULL,
   1504   (GetItemNumberMethod)NULL,
   1505   (GetItemIndexMethod)GetItemIndex,
   1506 };
   1507 
   1508 }  // namespace enums
   1509 
   1510 PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor) {
   1511   return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
   1512 }
   1513 
   1514 namespace extensions {
   1515 
   1516 typedef const FieldDescriptor* ItemDescriptor;
   1517 
   1518 static int Count(PyContainer* self) {
   1519   return GetDescriptor(self)->extension_count();
   1520 }
   1521 
   1522 static ItemDescriptor GetByName(PyContainer* self, const string& name) {
   1523   return GetDescriptor(self)->FindExtensionByName(name);
   1524 }
   1525 
   1526 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1527   return GetDescriptor(self)->extension(index);
   1528 }
   1529 
   1530 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1531   return PyFieldDescriptor_FromDescriptor(item);
   1532 }
   1533 
   1534 static const string& GetItemName(ItemDescriptor item) {
   1535   return item->name();
   1536 }
   1537 
   1538 static int GetItemIndex(ItemDescriptor item) {
   1539   return item->index();
   1540 }
   1541 
   1542 static DescriptorContainerDef ContainerDef = {
   1543   "FileExtensions",
   1544   (CountMethod)Count,
   1545   (GetByIndexMethod)GetByIndex,
   1546   (GetByNameMethod)GetByName,
   1547   (GetByCamelcaseNameMethod)NULL,
   1548   (GetByNumberMethod)NULL,
   1549   (NewObjectFromItemMethod)NewObjectFromItem,
   1550   (GetItemNameMethod)GetItemName,
   1551   (GetItemCamelcaseNameMethod)NULL,
   1552   (GetItemNumberMethod)NULL,
   1553   (GetItemIndexMethod)GetItemIndex,
   1554 };
   1555 
   1556 }  // namespace extensions
   1557 
   1558 PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor) {
   1559   return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
   1560 }
   1561 
   1562 namespace dependencies {
   1563 
   1564 typedef const FileDescriptor* ItemDescriptor;
   1565 
   1566 static int Count(PyContainer* self) {
   1567   return GetDescriptor(self)->dependency_count();
   1568 }
   1569 
   1570 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1571   return GetDescriptor(self)->dependency(index);
   1572 }
   1573 
   1574 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1575   return PyFileDescriptor_FromDescriptor(item);
   1576 }
   1577 
   1578 static DescriptorContainerDef ContainerDef = {
   1579   "FileDependencies",
   1580   (CountMethod)Count,
   1581   (GetByIndexMethod)GetByIndex,
   1582   (GetByNameMethod)NULL,
   1583   (GetByCamelcaseNameMethod)NULL,
   1584   (GetByNumberMethod)NULL,
   1585   (NewObjectFromItemMethod)NewObjectFromItem,
   1586   (GetItemNameMethod)NULL,
   1587   (GetItemCamelcaseNameMethod)NULL,
   1588   (GetItemNumberMethod)NULL,
   1589   (GetItemIndexMethod)NULL,
   1590 };
   1591 
   1592 }  // namespace dependencies
   1593 
   1594 PyObject* NewFileDependencies(const FileDescriptor* descriptor) {
   1595   return descriptor::NewSequence(&dependencies::ContainerDef, descriptor);
   1596 }
   1597 
   1598 namespace public_dependencies {
   1599 
   1600 typedef const FileDescriptor* ItemDescriptor;
   1601 
   1602 static int Count(PyContainer* self) {
   1603   return GetDescriptor(self)->public_dependency_count();
   1604 }
   1605 
   1606 static ItemDescriptor GetByIndex(PyContainer* self, int index) {
   1607   return GetDescriptor(self)->public_dependency(index);
   1608 }
   1609 
   1610 static PyObject* NewObjectFromItem(ItemDescriptor item) {
   1611   return PyFileDescriptor_FromDescriptor(item);
   1612 }
   1613 
   1614 static DescriptorContainerDef ContainerDef = {
   1615   "FilePublicDependencies",
   1616   (CountMethod)Count,
   1617   (GetByIndexMethod)GetByIndex,
   1618   (GetByNameMethod)NULL,
   1619   (GetByCamelcaseNameMethod)NULL,
   1620   (GetByNumberMethod)NULL,
   1621   (NewObjectFromItemMethod)NewObjectFromItem,
   1622   (GetItemNameMethod)NULL,
   1623   (GetItemCamelcaseNameMethod)NULL,
   1624   (GetItemNumberMethod)NULL,
   1625   (GetItemIndexMethod)NULL,
   1626 };
   1627 
   1628 }  // namespace public_dependencies
   1629 
   1630 PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor) {
   1631   return descriptor::NewSequence(&public_dependencies::ContainerDef,
   1632                                  descriptor);
   1633 }
   1634 
   1635 }  // namespace file_descriptor
   1636 
   1637 
   1638 // Register all implementations
   1639 
   1640 bool InitDescriptorMappingTypes() {
   1641   if (PyType_Ready(&descriptor::DescriptorMapping_Type) < 0)
   1642     return false;
   1643   if (PyType_Ready(&descriptor::DescriptorSequence_Type) < 0)
   1644     return false;
   1645   if (PyType_Ready(&descriptor::ContainerIterator_Type) < 0)
   1646     return false;
   1647   return true;
   1648 }
   1649 
   1650 }  // namespace python
   1651 }  // namespace protobuf
   1652 }  // namespace google
   1653