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