34 #include <google/protobuf/pyext/repeated_composite_container.h>
38 #include <google/protobuf/stubs/logging.h>
39 #include <google/protobuf/stubs/common.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/message_factory.h>
47 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
48 #include <google/protobuf/reflection.h>
49 #include <google/protobuf/stubs/map_util.h>
55 namespace repeated_composite_container {
60 static Py_ssize_t
Length(PyObject* pself) {
66 self->parent_field_descriptor);
78 message->GetReflection()->AddMessage(
80 self->parent_field_descriptor,
81 self->child_message_class->py_message_factory->message_factory);
83 self->parent_field_descriptor, sub_message,
self->child_message_class);
86 message->GetReflection()->RemoveLast(
95 static PyObject*
AddMethod(PyObject*
self, PyObject*
args, PyObject* kwargs) {
107 py_cmsg =
Add(
self,
nullptr,
nullptr);
108 if (py_cmsg ==
nullptr)
return nullptr;
123 if (py_cmsg ==
nullptr) {
143 if (py_cmsg ==
nullptr) {
150 const FieldDescriptor* field_descriptor =
self->parent_field_descriptor;
152 Py_ssize_t end_index =
index;
153 if (end_index < 0) end_index +=
length;
154 if (end_index < 0) end_index = 0;
155 for (Py_ssize_t
i =
length;
i > end_index;
i --) {
168 if (
iter ==
nullptr) {
169 PyErr_SetString(PyExc_TypeError,
"Value must be iterable");
173 while ((
next.reset(PyIter_Next(
iter.get()))) !=
nullptr) {
175 PyErr_SetString(PyExc_TypeError,
"Not a cmessage");
179 if (new_message ==
nullptr) {
188 if (PyErr_Occurred()) {
199 return Extend(
self, other);
214 if (index < 0 || index >=
length) {
215 PyErr_Format(PyExc_IndexError,
"list index (%zd) out of range",
index);
219 Message* sub_message =
message->GetReflection()->MutableRepeatedMessage(
222 ->BuildSubMessageFromPointer(
self->parent_field_descriptor, sub_message,
223 self->child_message_class)
233 if (PyIndex_Check(item)) {
235 index = PyNumber_AsSsize_t(item, PyExc_IndexError);
236 if (
index == -1 && PyErr_Occurred())
return nullptr;
239 }
else if (PySlice_Check(item)) {
248 if (slicelength <= 0) {
249 return PyList_New(0);
251 result = PyList_New(slicelength);
252 if (!
result)
return nullptr;
261 PyErr_Format(PyExc_TypeError,
"indices must be integers, not %.200s",
262 item->ob_type->tp_name);
274 if (
value !=
nullptr) {
275 PyErr_SetString(PyExc_TypeError,
"does not support assignment");
292 Py_ssize_t
len =
Length(
reinterpret_cast<PyObject*
>(
self));
294 for (Py_ssize_t
i = 0;
i <
len;
i++) {
296 if (item ==
nullptr) {
311 PyErr_SetString(PyExc_ValueError,
"Item to delete not in list");
315 static PyObject*
RichCompare(PyObject* pself, PyObject* other,
int opid) {
320 PyErr_SetString(PyExc_TypeError,
321 "Can only compare repeated composite fields "
322 "against other repeated composite fields.");
325 if (opid == Py_EQ || opid == Py_NE) {
328 if (full_slice ==
nullptr) {
332 if (list ==
nullptr) {
338 if (other_list ==
nullptr) {
341 return PyObject_RichCompare(list.
get(), other_list.
get(), opid);
343 Py_INCREF(Py_NotImplemented);
344 return Py_NotImplemented;
348 static PyObject*
ToStr(PyObject* pself) {
350 if (full_slice ==
nullptr) {
355 if (list ==
nullptr) {
358 return PyObject_Repr(list.
get());
365 PyObject* child_list) {
369 const Py_ssize_t
length =
Length(
reinterpret_cast<PyObject*
>(
self));
374 for (Py_ssize_t
i = 0;
i <
length; ++
i) {
377 for (Py_ssize_t j =
i; j <
length; ++j) {
393 PySequence_List(
reinterpret_cast<PyObject*
>(
self)));
394 if (child_list ==
nullptr) {
398 if (
m ==
nullptr)
return -1;
405 static PyObject*
Sort(PyObject* pself, PyObject*
args, PyObject* kwds) {
411 if (kwds !=
nullptr) {
412 PyObject* sort_func = PyDict_GetItemString(kwds,
"sort_function");
413 if (sort_func !=
nullptr) {
416 PyDict_SetItemString(kwds,
"cmp", sort_func);
417 PyDict_DelItemString(kwds,
"sort_function");
434 PySequence_List(
reinterpret_cast<PyObject*
>(
self)));
435 if (child_list ==
nullptr) {
439 PyObject_CallMethod(child_list.
get(),
"reverse",
nullptr)) ==
nullptr)
457 static PyObject*
Item(PyObject* pself, Py_ssize_t
index) {
463 static PyObject*
Pop(PyObject* pself, PyObject*
args) {
467 Py_ssize_t
index = -1;
468 if (!PyArg_ParseTuple(
args,
"|n", &
index)) {
474 if (item ==
nullptr) {
484 PyObject*
DeepCopy(PyObject* pself, PyObject*
arg) {
492 CMessageClass* child_message_class) {
500 if (
self ==
nullptr) {
505 self->parent = parent;
506 self->parent_field_descriptor = parent_field_descriptor;
507 Py_INCREF(child_message_class);
508 self->child_message_class = child_message_class;
516 Py_CLEAR(
self->child_message_class);
534 {
"__deepcopy__",
DeepCopy, METH_VARARGS,
"Makes a deep copy of the class."},
535 {
"add",
reinterpret_cast<PyCFunction
>(
AddMethod),
536 METH_VARARGS | METH_KEYWORDS,
"Adds an object to the repeated container."},
538 "Appends a message to the end of the repeated container."},
539 {
"insert",
Insert, METH_VARARGS,
540 "Inserts a message before the specified index."},
541 {
"extend",
ExtendMethod, METH_O,
"Adds objects to the repeated container."},
542 {
"pop",
Pop, METH_VARARGS,
543 "Removes an object from the repeated container and returns it."},
544 {
"remove",
Remove, METH_O,
545 "Removes an object from the repeated container."},
546 {
"sort",
reinterpret_cast<PyCFunction
>(
Sort), METH_VARARGS | METH_KEYWORDS,
547 "Sorts the repeated container."},
548 {
"reverse",
reinterpret_cast<PyCFunction
>(
Reverse), METH_NOARGS,
549 "Reverses elements order of the repeated container."},
551 "Adds objects to the repeated container."},
561 repeated_composite_container::
Dealloc,
562 #if PY_VERSION_HEX >= 0x03080000
574 PyObject_HashNotImplemented,
581 "A Repeated scalar container",