• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: anuraag@google.com (Anuraag Agrawal)
32 // Author: tibell@google.com (Johan Tibell)
33 
34 #include <google/protobuf/pyext/repeated_scalar_container.h>
35 
36 #include <memory>
37 
38 #include <google/protobuf/stubs/common.h>
39 #include <google/protobuf/stubs/logging.h>
40 #include <google/protobuf/descriptor.h>
41 #include <google/protobuf/dynamic_message.h>
42 #include <google/protobuf/message.h>
43 #include <google/protobuf/pyext/descriptor.h>
44 #include <google/protobuf/pyext/descriptor_pool.h>
45 #include <google/protobuf/pyext/message.h>
46 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
47 
48 #if PY_MAJOR_VERSION >= 3
49   #define PyInt_FromLong PyLong_FromLong
50   #if PY_VERSION_HEX < 0x03030000
51     #error "Python 3.0 - 3.2 are not supported."
52   #else
53   #define PyString_AsString(ob) \
54     (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
55   #endif
56 #endif
57 
58 namespace google {
59 namespace protobuf {
60 namespace python {
61 
62 namespace repeated_scalar_container {
63 
InternalAssignRepeatedField(RepeatedScalarContainer * self,PyObject * list)64 static int InternalAssignRepeatedField(
65     RepeatedScalarContainer* self, PyObject* list) {
66   Message* message = self->parent->message;
67   message->GetReflection()->ClearField(message, self->parent_field_descriptor);
68   for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) {
69     PyObject* value = PyList_GET_ITEM(list, i);
70     if (ScopedPyObjectPtr(Append(self, value)) == NULL) {
71       return -1;
72     }
73   }
74   return 0;
75 }
76 
Len(PyObject * pself)77 static Py_ssize_t Len(PyObject* pself) {
78   RepeatedScalarContainer* self =
79       reinterpret_cast<RepeatedScalarContainer*>(pself);
80   Message* message = self->parent->message;
81   return message->GetReflection()->FieldSize(*message,
82                                              self->parent_field_descriptor);
83 }
84 
AssignItem(PyObject * pself,Py_ssize_t index,PyObject * arg)85 static int AssignItem(PyObject* pself, Py_ssize_t index, PyObject* arg) {
86   RepeatedScalarContainer* self =
87       reinterpret_cast<RepeatedScalarContainer*>(pself);
88 
89   cmessage::AssureWritable(self->parent);
90   Message* message = self->parent->message;
91   const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
92 
93   const Reflection* reflection = message->GetReflection();
94   int field_size = reflection->FieldSize(*message, field_descriptor);
95   if (index < 0) {
96     index = field_size + index;
97   }
98   if (index < 0 || index >= field_size) {
99     PyErr_Format(PyExc_IndexError,
100                  "list assignment index (%d) out of range",
101                  static_cast<int>(index));
102     return -1;
103   }
104 
105   if (arg == NULL) {
106     ScopedPyObjectPtr py_index(PyLong_FromLong(index));
107     return cmessage::DeleteRepeatedField(self->parent, field_descriptor,
108                                          py_index.get());
109   }
110 
111   if (PySequence_Check(arg) && !(PyBytes_Check(arg) || PyUnicode_Check(arg))) {
112     PyErr_SetString(PyExc_TypeError, "Value must be scalar");
113     return -1;
114   }
115 
116   switch (field_descriptor->cpp_type()) {
117     case FieldDescriptor::CPPTYPE_INT32: {
118       GOOGLE_CHECK_GET_INT32(arg, value, -1);
119       reflection->SetRepeatedInt32(message, field_descriptor, index, value);
120       break;
121     }
122     case FieldDescriptor::CPPTYPE_INT64: {
123       GOOGLE_CHECK_GET_INT64(arg, value, -1);
124       reflection->SetRepeatedInt64(message, field_descriptor, index, value);
125       break;
126     }
127     case FieldDescriptor::CPPTYPE_UINT32: {
128       GOOGLE_CHECK_GET_UINT32(arg, value, -1);
129       reflection->SetRepeatedUInt32(message, field_descriptor, index, value);
130       break;
131     }
132     case FieldDescriptor::CPPTYPE_UINT64: {
133       GOOGLE_CHECK_GET_UINT64(arg, value, -1);
134       reflection->SetRepeatedUInt64(message, field_descriptor, index, value);
135       break;
136     }
137     case FieldDescriptor::CPPTYPE_FLOAT: {
138       GOOGLE_CHECK_GET_FLOAT(arg, value, -1);
139       reflection->SetRepeatedFloat(message, field_descriptor, index, value);
140       break;
141     }
142     case FieldDescriptor::CPPTYPE_DOUBLE: {
143       GOOGLE_CHECK_GET_DOUBLE(arg, value, -1);
144       reflection->SetRepeatedDouble(message, field_descriptor, index, value);
145       break;
146     }
147     case FieldDescriptor::CPPTYPE_BOOL: {
148       GOOGLE_CHECK_GET_BOOL(arg, value, -1);
149       reflection->SetRepeatedBool(message, field_descriptor, index, value);
150       break;
151     }
152     case FieldDescriptor::CPPTYPE_STRING: {
153       if (!CheckAndSetString(
154           arg, message, field_descriptor, reflection, false, index)) {
155         return -1;
156       }
157       break;
158     }
159     case FieldDescriptor::CPPTYPE_ENUM: {
160       GOOGLE_CHECK_GET_INT32(arg, value, -1);
161       if (reflection->SupportsUnknownEnumValues()) {
162         reflection->SetRepeatedEnumValue(message, field_descriptor, index,
163                                          value);
164       } else {
165         const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
166         const EnumValueDescriptor* enum_value =
167             enum_descriptor->FindValueByNumber(value);
168         if (enum_value != NULL) {
169           reflection->SetRepeatedEnum(message, field_descriptor, index,
170                                       enum_value);
171         } else {
172           ScopedPyObjectPtr s(PyObject_Str(arg));
173           if (s != NULL) {
174             PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
175                          PyString_AsString(s.get()));
176           }
177           return -1;
178         }
179       }
180       break;
181     }
182     default:
183       PyErr_Format(
184           PyExc_SystemError, "Adding value to a field of unknown type %d",
185           field_descriptor->cpp_type());
186       return -1;
187   }
188   return 0;
189 }
190 
Item(PyObject * pself,Py_ssize_t index)191 static PyObject* Item(PyObject* pself, Py_ssize_t index) {
192   RepeatedScalarContainer* self =
193       reinterpret_cast<RepeatedScalarContainer*>(pself);
194 
195   Message* message = self->parent->message;
196   const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
197   const Reflection* reflection = message->GetReflection();
198 
199   int field_size = reflection->FieldSize(*message, field_descriptor);
200   if (index < 0) {
201     index = field_size + index;
202   }
203   if (index < 0 || index >= field_size) {
204     PyErr_Format(PyExc_IndexError,
205                  "list index (%zd) out of range",
206                  index);
207     return NULL;
208   }
209 
210   PyObject* result = NULL;
211   switch (field_descriptor->cpp_type()) {
212     case FieldDescriptor::CPPTYPE_INT32: {
213       int32 value = reflection->GetRepeatedInt32(
214           *message, field_descriptor, index);
215       result = PyInt_FromLong(value);
216       break;
217     }
218     case FieldDescriptor::CPPTYPE_INT64: {
219       int64 value = reflection->GetRepeatedInt64(
220           *message, field_descriptor, index);
221       result = PyLong_FromLongLong(value);
222       break;
223     }
224     case FieldDescriptor::CPPTYPE_UINT32: {
225       uint32 value = reflection->GetRepeatedUInt32(
226           *message, field_descriptor, index);
227       result = PyLong_FromLongLong(value);
228       break;
229     }
230     case FieldDescriptor::CPPTYPE_UINT64: {
231       uint64 value = reflection->GetRepeatedUInt64(
232           *message, field_descriptor, index);
233       result = PyLong_FromUnsignedLongLong(value);
234       break;
235     }
236     case FieldDescriptor::CPPTYPE_FLOAT: {
237       float value = reflection->GetRepeatedFloat(
238           *message, field_descriptor, index);
239       result = PyFloat_FromDouble(value);
240       break;
241     }
242     case FieldDescriptor::CPPTYPE_DOUBLE: {
243       double value = reflection->GetRepeatedDouble(
244           *message, field_descriptor, index);
245       result = PyFloat_FromDouble(value);
246       break;
247     }
248     case FieldDescriptor::CPPTYPE_BOOL: {
249       bool value = reflection->GetRepeatedBool(
250           *message, field_descriptor, index);
251       result = PyBool_FromLong(value ? 1 : 0);
252       break;
253     }
254     case FieldDescriptor::CPPTYPE_ENUM: {
255       const EnumValueDescriptor* enum_value =
256           message->GetReflection()->GetRepeatedEnum(
257               *message, field_descriptor, index);
258       result = PyInt_FromLong(enum_value->number());
259       break;
260     }
261     case FieldDescriptor::CPPTYPE_STRING: {
262       std::string scratch;
263       const std::string& value = reflection->GetRepeatedStringReference(
264           *message, field_descriptor, index, &scratch);
265       result = ToStringObject(field_descriptor, value);
266       break;
267     }
268     default:
269       PyErr_Format(
270           PyExc_SystemError,
271           "Getting value from a repeated field of unknown type %d",
272           field_descriptor->cpp_type());
273   }
274 
275   return result;
276 }
277 
Subscript(PyObject * pself,PyObject * slice)278 static PyObject* Subscript(PyObject* pself, PyObject* slice) {
279   Py_ssize_t from;
280   Py_ssize_t to;
281   Py_ssize_t step;
282   Py_ssize_t length;
283   Py_ssize_t slicelength;
284   bool return_list = false;
285 #if PY_MAJOR_VERSION < 3
286   if (PyInt_Check(slice)) {
287     from = to = PyInt_AsLong(slice);
288   } else  // NOLINT
289 #endif
290   if (PyLong_Check(slice)) {
291     from = to = PyLong_AsLong(slice);
292   } else if (PySlice_Check(slice)) {
293     length = Len(pself);
294 #if PY_MAJOR_VERSION >= 3
295     if (PySlice_GetIndicesEx(slice,
296                              length, &from, &to, &step, &slicelength) == -1) {
297 #else
298     if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
299                              length, &from, &to, &step, &slicelength) == -1) {
300 #endif
301       return NULL;
302     }
303     return_list = true;
304   } else {
305     PyErr_SetString(PyExc_TypeError, "list indices must be integers");
306     return NULL;
307   }
308 
309   if (!return_list) {
310     return Item(pself, from);
311   }
312 
313   PyObject* list = PyList_New(0);
314   if (list == NULL) {
315     return NULL;
316   }
317   if (from <= to) {
318     if (step < 0) {
319       return list;
320     }
321     for (Py_ssize_t index = from; index < to; index += step) {
322       if (index < 0 || index >= length) {
323         break;
324       }
325       ScopedPyObjectPtr s(Item(pself, index));
326       PyList_Append(list, s.get());
327     }
328   } else {
329     if (step > 0) {
330       return list;
331     }
332     for (Py_ssize_t index = from; index > to; index += step) {
333       if (index < 0 || index >= length) {
334         break;
335       }
336       ScopedPyObjectPtr s(Item(pself, index));
337       PyList_Append(list, s.get());
338     }
339   }
340   return list;
341 }
342 
343 PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
344   cmessage::AssureWritable(self->parent);
345   Message* message = self->parent->message;
346   const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
347 
348   const Reflection* reflection = message->GetReflection();
349   switch (field_descriptor->cpp_type()) {
350     case FieldDescriptor::CPPTYPE_INT32: {
351       GOOGLE_CHECK_GET_INT32(item, value, NULL);
352       reflection->AddInt32(message, field_descriptor, value);
353       break;
354     }
355     case FieldDescriptor::CPPTYPE_INT64: {
356       GOOGLE_CHECK_GET_INT64(item, value, NULL);
357       reflection->AddInt64(message, field_descriptor, value);
358       break;
359     }
360     case FieldDescriptor::CPPTYPE_UINT32: {
361       GOOGLE_CHECK_GET_UINT32(item, value, NULL);
362       reflection->AddUInt32(message, field_descriptor, value);
363       break;
364     }
365     case FieldDescriptor::CPPTYPE_UINT64: {
366       GOOGLE_CHECK_GET_UINT64(item, value, NULL);
367       reflection->AddUInt64(message, field_descriptor, value);
368       break;
369     }
370     case FieldDescriptor::CPPTYPE_FLOAT: {
371       GOOGLE_CHECK_GET_FLOAT(item, value, NULL);
372       reflection->AddFloat(message, field_descriptor, value);
373       break;
374     }
375     case FieldDescriptor::CPPTYPE_DOUBLE: {
376       GOOGLE_CHECK_GET_DOUBLE(item, value, NULL);
377       reflection->AddDouble(message, field_descriptor, value);
378       break;
379     }
380     case FieldDescriptor::CPPTYPE_BOOL: {
381       GOOGLE_CHECK_GET_BOOL(item, value, NULL);
382       reflection->AddBool(message, field_descriptor, value);
383       break;
384     }
385     case FieldDescriptor::CPPTYPE_STRING: {
386       if (!CheckAndSetString(
387           item, message, field_descriptor, reflection, true, -1)) {
388         return NULL;
389       }
390       break;
391     }
392     case FieldDescriptor::CPPTYPE_ENUM: {
393       GOOGLE_CHECK_GET_INT32(item, value, NULL);
394       if (reflection->SupportsUnknownEnumValues()) {
395         reflection->AddEnumValue(message, field_descriptor, value);
396       } else {
397         const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
398         const EnumValueDescriptor* enum_value =
399             enum_descriptor->FindValueByNumber(value);
400         if (enum_value != NULL) {
401           reflection->AddEnum(message, field_descriptor, enum_value);
402         } else {
403           ScopedPyObjectPtr s(PyObject_Str(item));
404           if (s != NULL) {
405             PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
406                          PyString_AsString(s.get()));
407           }
408           return NULL;
409         }
410       }
411       break;
412     }
413     default:
414       PyErr_Format(
415           PyExc_SystemError, "Adding value to a field of unknown type %d",
416           field_descriptor->cpp_type());
417       return NULL;
418   }
419 
420   Py_RETURN_NONE;
421 }
422 
423 static PyObject* AppendMethod(PyObject* self, PyObject* item) {
424   return Append(reinterpret_cast<RepeatedScalarContainer*>(self), item);
425 }
426 
427 static int AssSubscript(PyObject* pself, PyObject* slice, PyObject* value) {
428   RepeatedScalarContainer* self =
429       reinterpret_cast<RepeatedScalarContainer*>(pself);
430 
431   Py_ssize_t from;
432   Py_ssize_t to;
433   Py_ssize_t step;
434   Py_ssize_t length;
435   Py_ssize_t slicelength;
436   bool create_list = false;
437 
438   cmessage::AssureWritable(self->parent);
439   Message* message = self->parent->message;
440   const FieldDescriptor* field_descriptor =
441       self->parent_field_descriptor;
442 
443 #if PY_MAJOR_VERSION < 3
444   if (PyInt_Check(slice)) {
445     from = to = PyInt_AsLong(slice);
446   } else  // NOLINT
447 #endif
448   if (PyLong_Check(slice)) {
449     from = to = PyLong_AsLong(slice);
450   } else if (PySlice_Check(slice)) {
451     const Reflection* reflection = message->GetReflection();
452     length = reflection->FieldSize(*message, field_descriptor);
453 #if PY_MAJOR_VERSION >= 3
454     if (PySlice_GetIndicesEx(slice,
455                              length, &from, &to, &step, &slicelength) == -1) {
456 #else
457     if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
458                              length, &from, &to, &step, &slicelength) == -1) {
459 #endif
460       return -1;
461     }
462     create_list = true;
463   } else {
464     PyErr_SetString(PyExc_TypeError, "list indices must be integers");
465     return -1;
466   }
467 
468   if (value == NULL) {
469     return cmessage::DeleteRepeatedField(self->parent, field_descriptor, slice);
470   }
471 
472   if (!create_list) {
473     return AssignItem(pself, from, value);
474   }
475 
476   ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
477   if (full_slice == NULL) {
478     return -1;
479   }
480   ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
481   if (new_list == NULL) {
482     return -1;
483   }
484   if (PySequence_SetSlice(new_list.get(), from, to, value) < 0) {
485     return -1;
486   }
487 
488   return InternalAssignRepeatedField(self, new_list.get());
489 }
490 
491 PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
492   cmessage::AssureWritable(self->parent);
493 
494   // TODO(ptucker): Deprecate this behavior. b/18413862
495   if (value == Py_None) {
496     Py_RETURN_NONE;
497   }
498   if ((Py_TYPE(value)->tp_as_sequence == NULL) && PyObject_Not(value)) {
499     Py_RETURN_NONE;
500   }
501 
502   ScopedPyObjectPtr iter(PyObject_GetIter(value));
503   if (iter == NULL) {
504     PyErr_SetString(PyExc_TypeError, "Value must be iterable");
505     return NULL;
506   }
507   ScopedPyObjectPtr next;
508   while ((next.reset(PyIter_Next(iter.get()))) != NULL) {
509     if (ScopedPyObjectPtr(Append(self, next.get())) == NULL) {
510       return NULL;
511     }
512   }
513   if (PyErr_Occurred()) {
514     return NULL;
515   }
516   Py_RETURN_NONE;
517 }
518 
519 static PyObject* Insert(PyObject* pself, PyObject* args) {
520   RepeatedScalarContainer* self =
521       reinterpret_cast<RepeatedScalarContainer*>(pself);
522 
523   Py_ssize_t index;
524   PyObject* value;
525   if (!PyArg_ParseTuple(args, "lO", &index, &value)) {
526     return NULL;
527   }
528   ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
529   ScopedPyObjectPtr new_list(Subscript(pself, full_slice.get()));
530   if (PyList_Insert(new_list.get(), index, value) < 0) {
531     return NULL;
532   }
533   int ret = InternalAssignRepeatedField(self, new_list.get());
534   if (ret < 0) {
535     return NULL;
536   }
537   Py_RETURN_NONE;
538 }
539 
540 static PyObject* Remove(PyObject* pself, PyObject* value) {
541   Py_ssize_t match_index = -1;
542   for (Py_ssize_t i = 0; i < Len(pself); ++i) {
543     ScopedPyObjectPtr elem(Item(pself, i));
544     if (PyObject_RichCompareBool(elem.get(), value, Py_EQ)) {
545       match_index = i;
546       break;
547     }
548   }
549   if (match_index == -1) {
550     PyErr_SetString(PyExc_ValueError, "remove(x): x not in container");
551     return NULL;
552   }
553   if (AssignItem(pself, match_index, NULL) < 0) {
554     return NULL;
555   }
556   Py_RETURN_NONE;
557 }
558 
559 static PyObject* ExtendMethod(PyObject* self, PyObject* value) {
560   return Extend(reinterpret_cast<RepeatedScalarContainer*>(self), value);
561 }
562 
563 static PyObject* RichCompare(PyObject* pself, PyObject* other, int opid) {
564   if (opid != Py_EQ && opid != Py_NE) {
565     Py_INCREF(Py_NotImplemented);
566     return Py_NotImplemented;
567   }
568 
569   // Copy the contents of this repeated scalar container, and other if it is
570   // also a repeated scalar container, into Python lists so we can delegate
571   // to the list's compare method.
572 
573   ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
574   if (full_slice == NULL) {
575     return NULL;
576   }
577 
578   ScopedPyObjectPtr other_list_deleter;
579   if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) {
580     other_list_deleter.reset(Subscript(other, full_slice.get()));
581     other = other_list_deleter.get();
582   }
583 
584   ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
585   if (list == NULL) {
586     return NULL;
587   }
588   return PyObject_RichCompare(list.get(), other, opid);
589 }
590 
591 PyObject* Reduce(PyObject* unused_self, PyObject* unused_other) {
592   PyErr_Format(
593       PickleError_class,
594       "can't pickle repeated message fields, convert to list first");
595   return NULL;
596 }
597 
598 static PyObject* Sort(PyObject* pself, PyObject* args, PyObject* kwds) {
599   // Support the old sort_function argument for backwards
600   // compatibility.
601   if (kwds != NULL) {
602     PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
603     if (sort_func != NULL) {
604       // Must set before deleting as sort_func is a borrowed reference
605       // and kwds might be the only thing keeping it alive.
606       if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1)
607         return NULL;
608       if (PyDict_DelItemString(kwds, "sort_function") == -1)
609         return NULL;
610     }
611   }
612 
613   ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
614   if (full_slice == NULL) {
615     return NULL;
616   }
617   ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
618   if (list == NULL) {
619     return NULL;
620   }
621   ScopedPyObjectPtr m(PyObject_GetAttrString(list.get(), "sort"));
622   if (m == NULL) {
623     return NULL;
624   }
625   ScopedPyObjectPtr res(PyObject_Call(m.get(), args, kwds));
626   if (res == NULL) {
627     return NULL;
628   }
629   int ret = InternalAssignRepeatedField(
630       reinterpret_cast<RepeatedScalarContainer*>(pself), list.get());
631   if (ret < 0) {
632     return NULL;
633   }
634   Py_RETURN_NONE;
635 }
636 
637 static PyObject* Pop(PyObject* pself, PyObject* args) {
638   Py_ssize_t index = -1;
639   if (!PyArg_ParseTuple(args, "|n", &index)) {
640     return NULL;
641   }
642   PyObject* item = Item(pself, index);
643   if (item == NULL) {
644     PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
645     return NULL;
646   }
647   if (AssignItem(pself, index, NULL) < 0) {
648     return NULL;
649   }
650   return item;
651 }
652 
653 static PyObject* ToStr(PyObject* pself) {
654   ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
655   if (full_slice == NULL) {
656     return NULL;
657   }
658   ScopedPyObjectPtr list(Subscript(pself, full_slice.get()));
659   if (list == NULL) {
660     return NULL;
661   }
662   return PyObject_Repr(list.get());
663 }
664 
665 static PyObject* MergeFrom(PyObject* pself, PyObject* arg) {
666   return Extend(reinterpret_cast<RepeatedScalarContainer*>(pself), arg);
667 }
668 
669 // The private constructor of RepeatedScalarContainer objects.
670 RepeatedScalarContainer* NewContainer(
671     CMessage* parent, const FieldDescriptor* parent_field_descriptor) {
672   if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
673     return NULL;
674   }
675 
676   RepeatedScalarContainer* self = reinterpret_cast<RepeatedScalarContainer*>(
677       PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0));
678   if (self == NULL) {
679     return NULL;
680   }
681 
682   Py_INCREF(parent);
683   self->parent = parent;
684   self->parent_field_descriptor = parent_field_descriptor;
685 
686   return self;
687 }
688 
689 PyObject* DeepCopy(PyObject* pself, PyObject* arg) {
690   return reinterpret_cast<RepeatedScalarContainer*>(pself)->DeepCopy();
691 }
692 
693 static void Dealloc(PyObject* pself) {
694   reinterpret_cast<RepeatedScalarContainer*>(pself)->RemoveFromParentCache();
695   Py_TYPE(pself)->tp_free(pself);
696 }
697 
698 static PySequenceMethods SqMethods = {
699   Len,        /* sq_length */
700   0,          /* sq_concat */
701   0,          /* sq_repeat */
702   Item,       /* sq_item */
703   0,          /* sq_slice */
704   AssignItem  /* sq_ass_item */
705 };
706 
707 static PyMappingMethods MpMethods = {
708   Len,               /* mp_length */
709   Subscript,      /* mp_subscript */
710   AssSubscript, /* mp_ass_subscript */
711 };
712 
713 static PyMethodDef Methods[] = {
714   { "__deepcopy__", DeepCopy, METH_VARARGS,
715     "Makes a deep copy of the class." },
716   { "__reduce__", Reduce, METH_NOARGS,
717     "Outputs picklable representation of the repeated field." },
718   { "append", AppendMethod, METH_O,
719     "Appends an object to the repeated container." },
720   { "extend", ExtendMethod, METH_O,
721     "Appends objects to the repeated container." },
722   { "insert", Insert, METH_VARARGS,
723     "Inserts an object at the specified position in the container." },
724   { "pop", Pop, METH_VARARGS,
725     "Removes an object from the repeated container and returns it." },
726   { "remove", Remove, METH_O,
727     "Removes an object from the repeated container." },
728   { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS,
729     "Sorts the repeated container."},
730   { "MergeFrom", (PyCFunction)MergeFrom, METH_O,
731     "Merges a repeated container into the current container." },
732   { NULL, NULL }
733 };
734 
735 }  // namespace repeated_scalar_container
736 
737 PyTypeObject RepeatedScalarContainer_Type = {
738   PyVarObject_HEAD_INIT(&PyType_Type, 0)
739   FULL_MODULE_NAME ".RepeatedScalarContainer",  // tp_name
740   sizeof(RepeatedScalarContainer),     // tp_basicsize
741   0,                                   //  tp_itemsize
742   repeated_scalar_container::Dealloc,  //  tp_dealloc
743   0,                                   //  tp_print
744   0,                                   //  tp_getattr
745   0,                                   //  tp_setattr
746   0,                                   //  tp_compare
747   repeated_scalar_container::ToStr,    //  tp_repr
748   0,                                   //  tp_as_number
749   &repeated_scalar_container::SqMethods,   //  tp_as_sequence
750   &repeated_scalar_container::MpMethods,   //  tp_as_mapping
751   PyObject_HashNotImplemented,         //  tp_hash
752   0,                                   //  tp_call
753   0,                                   //  tp_str
754   0,                                   //  tp_getattro
755   0,                                   //  tp_setattro
756   0,                                   //  tp_as_buffer
757   Py_TPFLAGS_DEFAULT,                  //  tp_flags
758   "A Repeated scalar container",       //  tp_doc
759   0,                                   //  tp_traverse
760   0,                                   //  tp_clear
761   repeated_scalar_container::RichCompare,  //  tp_richcompare
762   0,                                   //  tp_weaklistoffset
763   0,                                   //  tp_iter
764   0,                                   //  tp_iternext
765   repeated_scalar_container::Methods,      //  tp_methods
766   0,                                   //  tp_members
767   0,                                   //  tp_getset
768   0,                                   //  tp_base
769   0,                                   //  tp_dict
770   0,                                   //  tp_descr_get
771   0,                                   //  tp_descr_set
772   0,                                   //  tp_dictoffset
773   0,                                   //  tp_init
774 };
775 
776 }  // namespace python
777 }  // namespace protobuf
778 }  // namespace google
779