repeated.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2021, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of Google LLC nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "python/repeated.h"
29 
30 #include "python/convert.h"
31 #include "python/message.h"
32 #include "python/protobuf.h"
33 
34 static PyObject* PyUpb_RepeatedCompositeContainer_Append(PyObject* _self,
35  PyObject* value);
36 static PyObject* PyUpb_RepeatedScalarContainer_Append(PyObject* _self,
37  PyObject* value);
38 
39 // For an expression like:
40 // foo[index]
41 //
42 // Converts `index` to an effective i/count/step, for a repeated field
43 // field of size `size`.
44 static bool IndexToRange(PyObject* index, Py_ssize_t size, Py_ssize_t* i,
45  Py_ssize_t* count, Py_ssize_t* step) {
46  assert(i && count && step);
47  if (PySlice_Check(index)) {
48  Py_ssize_t start, stop;
49  if (PySlice_Unpack(index, &start, &stop, step) < 0) return false;
50  *count = PySlice_AdjustIndices(size, &start, &stop, *step);
51  *i = start;
52  } else {
53  *i = PyNumber_AsSsize_t(index, PyExc_IndexError);
54 
55  if (*i == -1 && PyErr_Occurred()) {
56  PyErr_SetString(PyExc_TypeError, "list indices must be integers");
57  return false;
58  }
59 
60  if (*i < 0) *i += size;
61  *step = 0;
62  *count = 1;
63 
64  if (*i < 0 || size <= *i) {
65  PyErr_Format(PyExc_IndexError, "list index out of range");
66  return false;
67  }
68  }
69  return true;
70 }
71 
72 // Wrapper for a repeated field.
73 typedef struct {
75  PyObject* arena;
76  // The field descriptor (PyObject*).
77  // The low bit indicates whether the container is reified (see ptr below).
78  // - low bit set: repeated field is a stub (no underlying data).
79  // - low bit clear: repeated field is reified (points to upb_Array).
81  union {
82  PyObject* parent; // stub: owning pointer to parent message.
83  upb_Array* arr; // reified: the data for this array.
84  } ptr;
86 
88  return self->field & 1;
89 }
90 
93  return (PyObject*)(self->field & ~(uintptr_t)1);
94 }
95 
100 }
101 
102 // If the repeated field is reified, returns it. Otherwise, returns NULL.
103 // If NULL is returned, the object is empty and has no underlying data.
105  PyUpb_RepeatedContainer* self) {
106  return PyUpb_RepeatedContainer_IsStub(self) ? NULL : self->ptr.arr;
107 }
108 
109 void PyUpb_RepeatedContainer_Reify(PyObject* _self, upb_Array* arr) {
111  assert(PyUpb_RepeatedContainer_IsStub(self));
112  if (!arr) {
114  upb_Arena* arena = PyUpb_Arena_Get(self->arena);
116  }
117  PyUpb_ObjCache_Add(arr, &self->ob_base);
118  Py_DECREF(self->ptr.parent);
119  self->ptr.arr = arr; // Overwrites self->ptr.parent.
120  self->field &= ~(uintptr_t)1;
121  assert(!PyUpb_RepeatedContainer_IsStub(self));
122 }
123 
127  if (arr) return arr; // Already writable.
128 
130  upb_Arena* arena = PyUpb_Arena_Get(self->arena);
133  (upb_MessageValue){.array_val = arr});
134  PyUpb_RepeatedContainer_Reify((PyObject*)self, arr);
135  return arr;
136 }
137 
138 static void PyUpb_RepeatedContainer_Dealloc(PyObject* _self) {
140  Py_DECREF(self->arena);
141  if (PyUpb_RepeatedContainer_IsStub(self)) {
142  PyUpb_CMessage_CacheDelete(self->ptr.parent,
144  Py_DECREF(self->ptr.parent);
145  } else {
146  PyUpb_ObjCache_Delete(self->ptr.arr);
147  }
149  PyUpb_Dealloc(self);
150 }
151 
152 static PyTypeObject* PyUpb_RepeatedContainer_GetClass(const upb_FieldDef* f) {
155  return upb_FieldDef_IsSubMessage(f) ? state->repeated_composite_container_type
156  : state->repeated_scalar_container_type;
157 }
158 
159 static Py_ssize_t PyUpb_RepeatedContainer_Length(PyObject* self) {
160  upb_Array* arr =
162  return arr ? upb_Array_Size(arr) : 0;
163 }
164 
165 PyObject* PyUpb_RepeatedContainer_NewStub(PyObject* parent,
166  const upb_FieldDef* f,
167  PyObject* arena) {
168  // We only create stubs when the parent is reified, by convention. However
169  // this is not an invariant: the parent could become reified at any time.
170  assert(PyUpb_CMessage_GetIfReified(parent) == NULL);
171  PyTypeObject* cls = PyUpb_RepeatedContainer_GetClass(f);
172  PyUpb_RepeatedContainer* repeated = (void*)PyType_GenericAlloc(cls, 0);
173  repeated->arena = arena;
175  repeated->ptr.parent = parent;
176  Py_INCREF(arena);
177  Py_INCREF(parent);
178  return &repeated->ob_base;
179 }
180 
182  const upb_FieldDef* f,
183  PyObject* arena) {
184  PyObject* ret = PyUpb_ObjCache_Get(arr);
185  if (ret) return ret;
186 
187  PyTypeObject* cls = PyUpb_RepeatedContainer_GetClass(f);
188  PyUpb_RepeatedContainer* repeated = (void*)PyType_GenericAlloc(cls, 0);
189  repeated->arena = arena;
191  repeated->ptr.arr = arr;
192  ret = &repeated->ob_base;
193  Py_INCREF(arena);
194  PyUpb_ObjCache_Add(arr, ret);
195  return ret;
196 }
197 
198 static PyObject* PyUpb_RepeatedContainer_MergeFrom(PyObject* _self,
199  PyObject* args);
200 
201 PyObject* PyUpb_RepeatedContainer_DeepCopy(PyObject* _self, PyObject* value) {
203  PyUpb_RepeatedContainer* clone =
204  (void*)PyType_GenericAlloc(Py_TYPE(_self), 0);
205  if (clone == NULL) return NULL;
207  clone->arena = PyUpb_Arena_New();
209  clone->ptr.arr =
211  PyUpb_ObjCache_Add(clone->ptr.arr, (PyObject*)clone);
212  PyObject* result = PyUpb_RepeatedContainer_MergeFrom((PyObject*)clone, _self);
213  if (!result) {
214  Py_DECREF(clone);
215  return NULL;
216  }
217  Py_DECREF(result);
218  return (PyObject*)clone;
219 }
220 
221 PyObject* PyUpb_RepeatedContainer_Extend(PyObject* _self, PyObject* value) {
224  size_t start_size = upb_Array_Size(arr);
225  PyObject* it = PyObject_GetIter(value);
226  if (!it) {
227  PyErr_SetString(PyExc_TypeError, "Value must be iterable");
228  return NULL;
229  }
230 
232  bool submsg = upb_FieldDef_IsSubMessage(f);
233  PyObject* e;
234 
235  while ((e = PyIter_Next(it))) {
236  PyObject* ret;
237  if (submsg) {
239  } else {
241  }
242  Py_XDECREF(ret);
243  Py_DECREF(e);
244  }
245 
246  Py_DECREF(it);
247 
248  if (PyErr_Occurred()) {
249  upb_Array_Resize(arr, start_size, NULL);
250  return NULL;
251  }
252 
253  Py_RETURN_NONE;
254 }
255 
256 static PyObject* PyUpb_RepeatedContainer_Item(PyObject* _self,
257  Py_ssize_t index) {
260  Py_ssize_t size = arr ? upb_Array_Size(arr) : 0;
261  if (index < 0 || index >= size) {
262  PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
263  return NULL;
264  }
266  return PyUpb_UpbToPy(upb_Array_Get(arr, index), f, self->arena);
267 }
268 
269 PyObject* PyUpb_RepeatedContainer_ToList(PyObject* _self) {
272  if (!arr) return PyList_New(0);
273 
275  size_t n = upb_Array_Size(arr);
276  PyObject* list = PyList_New(n);
277  for (size_t i = 0; i < n; i++) {
278  PyObject* val = PyUpb_UpbToPy(upb_Array_Get(arr, i), f, self->arena);
279  if (!val) {
280  Py_DECREF(list);
281  return NULL;
282  }
283  PyList_SetItem(list, i, val);
284  }
285  return list;
286 }
287 
288 static PyObject* PyUpb_RepeatedContainer_Repr(PyObject* _self) {
289  PyObject* list = PyUpb_RepeatedContainer_ToList(_self);
290  if (!list) return NULL;
291  assert(!PyErr_Occurred());
292  PyObject* repr = PyObject_Repr(list);
293  Py_DECREF(list);
294  return repr;
295 }
296 
297 static PyObject* PyUpb_RepeatedContainer_RichCompare(PyObject* _self,
298  PyObject* _other,
299  int opid) {
300  if (opid != Py_EQ && opid != Py_NE) {
301  Py_INCREF(Py_NotImplemented);
302  return Py_NotImplemented;
303  }
304  PyObject* list1 = PyUpb_RepeatedContainer_ToList(_self);
305  PyObject* list2 = _other;
306  PyObject* del = NULL;
307  if (PyObject_TypeCheck(_other, _self->ob_type)) {
308  del = list2 = PyUpb_RepeatedContainer_ToList(_other);
309  }
310  PyObject* ret = PyObject_RichCompare(list1, list2, opid);
311  Py_DECREF(list1);
312  Py_XDECREF(del);
313  return ret;
314 }
315 
316 static PyObject* PyUpb_RepeatedContainer_Subscript(PyObject* _self,
317  PyObject* key) {
320  Py_ssize_t size = arr ? upb_Array_Size(arr) : 0;
321  Py_ssize_t idx, count, step;
322  if (!IndexToRange(key, size, &idx, &count, &step)) return NULL;
324  if (step == 0) {
325  return PyUpb_UpbToPy(upb_Array_Get(arr, idx), f, self->arena);
326  } else {
327  PyObject* list = PyList_New(count);
328  for (Py_ssize_t i = 0; i < count; i++, idx += step) {
329  upb_MessageValue msgval = upb_Array_Get(self->ptr.arr, idx);
330  PyObject* item = PyUpb_UpbToPy(msgval, f, self->arena);
331  if (!item) {
332  Py_DECREF(list);
333  return NULL;
334  }
335  PyList_SetItem(list, i, item);
336  }
337  return list;
338  }
339 }
340 
342  PyUpb_RepeatedContainer* self, upb_Array* arr, const upb_FieldDef* f,
343  Py_ssize_t idx, Py_ssize_t count, Py_ssize_t step, PyObject* value) {
344  upb_Arena* arena = PyUpb_Arena_Get(self->arena);
346  PyErr_SetString(PyExc_TypeError, "does not support assignment");
347  return -1;
348  }
349 
350  if (step == 0) {
351  // Set single value.
352  upb_MessageValue msgval;
353  if (!PyUpb_PyToUpb(value, f, &msgval, arena)) return -1;
354  upb_Array_Set(arr, idx, msgval);
355  return 0;
356  }
357 
358  // Set range.
359  PyObject* seq =
360  PySequence_Fast(value, "must assign iterable to extended slice");
361  PyObject* item = NULL;
362  int ret = -1;
363  if (!seq) goto err;
364  Py_ssize_t seq_size = PySequence_Size(seq);
365  if (seq_size != count) {
366  if (step == 1) {
367  // We must shift the tail elements (either right or left).
368  size_t tail = upb_Array_Size(arr) - (idx + count);
369  upb_Array_Resize(arr, idx + seq_size + tail, arena);
370  upb_Array_Move(arr, idx + seq_size, idx + count, tail);
371  count = seq_size;
372  } else {
373  PyErr_Format(PyExc_ValueError,
374  "attempt to assign sequence of %zd to extended slice "
375  "of size %zd",
376  seq_size, count);
377  goto err;
378  }
379  }
380  for (Py_ssize_t i = 0; i < count; i++, idx += step) {
381  upb_MessageValue msgval;
382  item = PySequence_GetItem(seq, i);
383  if (!item) goto err;
384  // XXX: if this fails we can leave the list partially mutated.
385  if (!PyUpb_PyToUpb(item, f, &msgval, arena)) goto err;
386  Py_DECREF(item);
387  item = NULL;
388  upb_Array_Set(arr, idx, msgval);
389  }
390  ret = 0;
391 
392 err:
393  Py_XDECREF(seq);
394  Py_XDECREF(item);
395  return ret;
396 }
397 
399  Py_ssize_t idx,
400  Py_ssize_t count,
401  Py_ssize_t step) {
402  // Normalize direction: deletion is order-independent.
403  Py_ssize_t start = idx;
404  if (step < 0) {
405  Py_ssize_t end = start + step * (count - 1);
406  start = end;
407  step = -step;
408  }
409 
410  size_t dst = start;
411  size_t src;
412  if (step > 1) {
413  // Move elements between steps:
414  //
415  // src
416  // |
417  // |------X---X---X---X------------------------------|
418  // |
419  // dst <-------- tail -------------->
420  src = start + 1;
421  for (Py_ssize_t i = 1; i < count; i++, dst += step - 1, src += step) {
422  upb_Array_Move(arr, dst, src, step);
423  }
424  } else {
425  src = start + count;
426  }
427 
428  // Move tail.
429  size_t tail = upb_Array_Size(arr) - src;
430  size_t new_size = dst + tail;
431  assert(new_size == upb_Array_Size(arr) - count);
432  upb_Array_Move(arr, dst, src, tail);
433  upb_Array_Resize(arr, new_size, NULL);
434  return 0;
435 }
436 
437 static int PyUpb_RepeatedContainer_AssignSubscript(PyObject* _self,
438  PyObject* key,
439  PyObject* value) {
443  Py_ssize_t size = arr ? upb_Array_Size(arr) : 0;
444  Py_ssize_t idx, count, step;
445  if (!IndexToRange(key, size, &idx, &count, &step)) return -1;
446  if (value) {
447  return PyUpb_RepeatedContainer_SetSubscript(self, arr, f, idx, count, step,
448  value);
449  } else {
451  }
452 }
453 
454 static PyObject* PyUpb_RepeatedContainer_Pop(PyObject* _self, PyObject* args) {
456  Py_ssize_t index = -1;
457  if (!PyArg_ParseTuple(args, "|n", &index)) return NULL;
459  size_t size = upb_Array_Size(arr);
460  if (index < 0) index += size;
461  if (index >= size) index = size - 1;
462  PyObject* ret = PyUpb_RepeatedContainer_Item(_self, index);
463  if (!ret) return NULL;
464  upb_Array_Delete(self->ptr.arr, index, 1);
465  return ret;
466 }
467 
468 static PyObject* PyUpb_RepeatedContainer_Remove(PyObject* _self,
469  PyObject* value) {
471  Py_ssize_t match_index = -1;
472  Py_ssize_t n = PyUpb_RepeatedContainer_Length(_self);
473  for (Py_ssize_t i = 0; i < n; ++i) {
474  PyObject* elem = PyUpb_RepeatedContainer_Item(_self, i);
475  if (!elem) return NULL;
476  int eq = PyObject_RichCompareBool(elem, value, Py_EQ);
477  Py_DECREF(elem);
478  if (eq) {
479  match_index = i;
480  break;
481  }
482  }
483  if (match_index == -1) {
484  PyErr_SetString(PyExc_ValueError, "remove(x): x not in container");
485  return NULL;
486  }
487  if (PyUpb_RepeatedContainer_DeleteSubscript(arr, match_index, 1, 1) < 0) {
488  return NULL;
489  }
490  Py_RETURN_NONE;
491 }
492 
493 // A helper function used only for Sort().
494 static bool PyUpb_RepeatedContainer_Assign(PyObject* _self, PyObject* list) {
498  Py_ssize_t size = PyList_Size(list);
499  bool submsg = upb_FieldDef_IsSubMessage(f);
500  upb_Arena* arena = PyUpb_Arena_Get(self->arena);
501  for (Py_ssize_t i = 0; i < size; ++i) {
502  PyObject* obj = PyList_GetItem(list, i);
503  upb_MessageValue msgval;
504  if (submsg) {
506  assert(msgval.msg_val);
507  } else {
508  if (!PyUpb_PyToUpb(obj, f, &msgval, arena)) return false;
509  }
510  upb_Array_Set(arr, i, msgval);
511  }
512  return true;
513 }
514 
515 static PyObject* PyUpb_RepeatedContainer_Sort(PyObject* pself, PyObject* args,
516  PyObject* kwds) {
517  // Support the old sort_function argument for backwards
518  // compatibility.
519  if (kwds != NULL) {
520  PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function");
521  if (sort_func != NULL) {
522  // Must set before deleting as sort_func is a borrowed reference
523  // and kwds might be the only thing keeping it alive.
524  if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) return NULL;
525  if (PyDict_DelItemString(kwds, "sort_function") == -1) return NULL;
526  }
527  }
528 
529  PyObject* ret = NULL;
530  PyObject* full_slice = NULL;
531  PyObject* list = NULL;
532  PyObject* m = NULL;
533  PyObject* res = NULL;
534  if ((full_slice = PySlice_New(NULL, NULL, NULL)) &&
535  (list = PyUpb_RepeatedContainer_Subscript(pself, full_slice)) &&
536  (m = PyObject_GetAttrString(list, "sort")) &&
537  (res = PyObject_Call(m, args, kwds)) &&
538  PyUpb_RepeatedContainer_Assign(pself, list)) {
539  Py_INCREF(Py_None);
540  ret = Py_None;
541  }
542 
543  Py_XDECREF(full_slice);
544  Py_XDECREF(list);
545  Py_XDECREF(m);
546  Py_XDECREF(res);
547  return ret;
548 }
549 
550 static PyObject* PyUpb_RepeatedContainer_Reverse(PyObject* _self) {
552  size_t n = upb_Array_Size(arr);
553  size_t half = n / 2; // Rounds down.
554  for (size_t i = 0; i < half; i++) {
555  size_t i2 = n - i - 1;
558  upb_Array_Set(arr, i, val2);
559  upb_Array_Set(arr, i2, val1);
560  }
561  Py_RETURN_NONE;
562 }
563 
564 static PyObject* PyUpb_RepeatedContainer_MergeFrom(PyObject* _self,
565  PyObject* args) {
566  return PyUpb_RepeatedContainer_Extend(_self, args);
567 }
568 
569 // -----------------------------------------------------------------------------
570 // RepeatedCompositeContainer
571 // -----------------------------------------------------------------------------
572 
573 static PyObject* PyUpb_RepeatedCompositeContainer_AppendNew(PyObject* _self) {
576  if (!arr) return NULL;
578  upb_Arena* arena = PyUpb_Arena_Get(self->arena);
581  upb_MessageValue msgval = {.msg_val = msg};
582  upb_Array_Append(arr, msgval, arena);
583  return PyUpb_CMessage_Get(msg, m, self->arena);
584 }
585 
586 PyObject* PyUpb_RepeatedCompositeContainer_Add(PyObject* _self, PyObject* args,
587  PyObject* kwargs) {
589  PyObject* py_msg = PyUpb_RepeatedCompositeContainer_AppendNew(_self);
590  if (!py_msg) return NULL;
591  if (PyUpb_CMessage_InitAttributes(py_msg, args, kwargs) < 0) {
592  Py_DECREF(py_msg);
593  upb_Array_Delete(self->ptr.arr, upb_Array_Size(self->ptr.arr) - 1, 1);
594  return NULL;
595  }
596  return py_msg;
597 }
598 
599 static PyObject* PyUpb_RepeatedCompositeContainer_Append(PyObject* _self,
600  PyObject* value) {
601  if (!PyUpb_CMessage_Verify(value)) return NULL;
602  PyObject* py_msg = PyUpb_RepeatedCompositeContainer_AppendNew(_self);
603  if (!py_msg) return NULL;
604  PyObject* none = PyUpb_CMessage_MergeFrom(py_msg, value);
605  if (!none) {
606  Py_DECREF(py_msg);
607  return NULL;
608  }
609  Py_DECREF(none);
610  return py_msg;
611 }
612 
613 static PyObject* PyUpb_RepeatedContainer_Insert(PyObject* _self,
614  PyObject* args) {
616  Py_ssize_t index;
617  PyObject* value;
618  if (!PyArg_ParseTuple(args, "nO", &index, &value)) return NULL;
620  if (!arr) return NULL;
621 
622  // Normalize index.
623  Py_ssize_t size = upb_Array_Size(arr);
624  if (index < 0) index += size;
625  if (index < 0) index = 0;
626  if (index > size) index = size;
627 
629  upb_MessageValue msgval;
630  upb_Arena* arena = PyUpb_Arena_Get(self->arena);
632  // Create message.
635  PyObject* py_msg = PyUpb_CMessage_Get(msg, m, self->arena);
636  PyObject* ret = PyUpb_CMessage_MergeFrom(py_msg, value);
637  Py_DECREF(py_msg);
638  if (!ret) return NULL;
639  Py_DECREF(ret);
640  msgval.msg_val = msg;
641  } else {
642  if (!PyUpb_PyToUpb(value, f, &msgval, arena)) return NULL;
643  }
644 
645  upb_Array_Insert(arr, index, 1, arena);
646  upb_Array_Set(arr, index, msgval);
647 
648  Py_RETURN_NONE;
649 }
650 
652  // TODO(https://github.com/protocolbuffers/upb/issues/459)
653  {"__deepcopy__", PyUpb_RepeatedContainer_DeepCopy, METH_VARARGS,
654  "Makes a deep copy of the class."},
655  {"add", (PyCFunction)PyUpb_RepeatedCompositeContainer_Add,
656  METH_VARARGS | METH_KEYWORDS, "Adds an object to the repeated container."},
657  {"append", PyUpb_RepeatedCompositeContainer_Append, METH_O,
658  "Appends a message to the end of the repeated container."},
659  {"insert", PyUpb_RepeatedContainer_Insert, METH_VARARGS,
660  "Inserts a message before the specified index."},
661  {"extend", PyUpb_RepeatedContainer_Extend, METH_O,
662  "Adds objects to the repeated container."},
663  {"pop", PyUpb_RepeatedContainer_Pop, METH_VARARGS,
664  "Removes an object from the repeated container and returns it."},
665  {"remove", PyUpb_RepeatedContainer_Remove, METH_O,
666  "Removes an object from the repeated container."},
667  {"sort", (PyCFunction)PyUpb_RepeatedContainer_Sort,
668  METH_VARARGS | METH_KEYWORDS, "Sorts the repeated container."},
669  {"reverse", (PyCFunction)PyUpb_RepeatedContainer_Reverse, METH_NOARGS,
670  "Reverses elements order of the repeated container."},
671  {"MergeFrom", PyUpb_RepeatedContainer_MergeFrom, METH_O,
672  "Adds objects to the repeated container."},
673  {NULL, NULL}};
674 
676  {Py_tp_dealloc, PyUpb_RepeatedContainer_Dealloc},
678  {Py_sq_length, PyUpb_RepeatedContainer_Length},
679  {Py_sq_item, PyUpb_RepeatedContainer_Item},
680  {Py_mp_length, PyUpb_RepeatedContainer_Length},
681  {Py_tp_repr, PyUpb_RepeatedContainer_Repr},
682  {Py_mp_subscript, PyUpb_RepeatedContainer_Subscript},
683  {Py_mp_ass_subscript, PyUpb_RepeatedContainer_AssignSubscript},
684  {Py_tp_new, PyUpb_Forbidden_New},
685  {Py_tp_hash, PyObject_HashNotImplemented},
686  {0, NULL}};
687 
689  PYUPB_MODULE_NAME ".RepeatedCompositeContainer",
690  sizeof(PyUpb_RepeatedContainer),
691  0, // tp_itemsize
692  Py_TPFLAGS_DEFAULT,
694 };
695 
696 // -----------------------------------------------------------------------------
697 // RepeatedScalarContainer
698 // -----------------------------------------------------------------------------
699 
700 static PyObject* PyUpb_RepeatedScalarContainer_Append(PyObject* _self,
701  PyObject* value) {
704  upb_Arena* arena = PyUpb_Arena_Get(self->arena);
706  upb_MessageValue msgval;
707  if (!PyUpb_PyToUpb(value, f, &msgval, arena)) {
708  return NULL;
709  }
710  upb_Array_Append(arr, msgval, arena);
711  Py_RETURN_NONE;
712 }
713 
714 static int PyUpb_RepeatedScalarContainer_AssignItem(PyObject* _self,
715  Py_ssize_t index,
716  PyObject* item) {
719  Py_ssize_t size = arr ? upb_Array_Size(arr) : 0;
720  if (index < 0 || index >= size) {
721  PyErr_Format(PyExc_IndexError, "list index (%zd) out of range", index);
722  return -1;
723  }
725  upb_MessageValue msgval;
726  upb_Arena* arena = PyUpb_Arena_Get(self->arena);
727  if (!PyUpb_PyToUpb(item, f, &msgval, arena)) {
728  return -1;
729  }
730  upb_Array_Set(self->ptr.arr, index, msgval);
731  return 0;
732 }
733 
735  // TODO(https://github.com/protocolbuffers/upb/issues/459)
736  {"__deepcopy__", PyUpb_RepeatedContainer_DeepCopy, METH_VARARGS,
737  "Makes a deep copy of the class."},
738  // {"__reduce__", Reduce, METH_NOARGS,
739  // "Outputs picklable representation of the repeated field."},
740  {"append", PyUpb_RepeatedScalarContainer_Append, METH_O,
741  "Appends an object to the repeated container."},
742  {"extend", PyUpb_RepeatedContainer_Extend, METH_O,
743  "Appends objects to the repeated container."},
744  {"insert", PyUpb_RepeatedContainer_Insert, METH_VARARGS,
745  "Inserts an object at the specified position in the container."},
746  {"pop", PyUpb_RepeatedContainer_Pop, METH_VARARGS,
747  "Removes an object from the repeated container and returns it."},
748  {"remove", PyUpb_RepeatedContainer_Remove, METH_O,
749  "Removes an object from the repeated container."},
750  {"sort", (PyCFunction)PyUpb_RepeatedContainer_Sort,
751  METH_VARARGS | METH_KEYWORDS, "Sorts the repeated container."},
752  {"reverse", (PyCFunction)PyUpb_RepeatedContainer_Reverse, METH_NOARGS,
753  "Reverses elements order of the repeated container."},
754  {"MergeFrom", PyUpb_RepeatedContainer_MergeFrom, METH_O,
755  "Merges a repeated container into the current container."},
756  {NULL, NULL}};
757 
758 static PyType_Slot PyUpb_RepeatedScalarContainer_Slots[] = {
759  {Py_tp_dealloc, PyUpb_RepeatedContainer_Dealloc},
760  {Py_tp_methods, PyUpb_RepeatedScalarContainer_Methods},
761  {Py_tp_new, PyUpb_Forbidden_New},
762  {Py_tp_repr, PyUpb_RepeatedContainer_Repr},
763  {Py_sq_length, PyUpb_RepeatedContainer_Length},
764  {Py_sq_item, PyUpb_RepeatedContainer_Item},
766  {Py_mp_length, PyUpb_RepeatedContainer_Length},
767  {Py_mp_subscript, PyUpb_RepeatedContainer_Subscript},
768  {Py_mp_ass_subscript, PyUpb_RepeatedContainer_AssignSubscript},
769  {Py_tp_richcompare, PyUpb_RepeatedContainer_RichCompare},
770  {Py_tp_hash, PyObject_HashNotImplemented},
771  {0, NULL}};
772 
774  PYUPB_MODULE_NAME ".RepeatedScalarContainer",
775  sizeof(PyUpb_RepeatedContainer),
776  0, // tp_itemsize
777  Py_TPFLAGS_DEFAULT,
779 };
780 
781 // -----------------------------------------------------------------------------
782 // Top Level
783 // -----------------------------------------------------------------------------
784 
786  PyObject* collections = NULL;
787  PyObject* seq = NULL;
788  PyObject* ret1 = NULL;
789  PyObject* ret2 = NULL;
790  PyTypeObject* type1 = state->repeated_scalar_container_type;
791  PyTypeObject* type2 = state->repeated_composite_container_type;
792 
793  bool ok = (collections = PyImport_ImportModule("collections.abc")) &&
794  (seq = PyObject_GetAttrString(collections, "MutableSequence")) &&
795  (ret1 = PyObject_CallMethod(seq, "register", "O", type1)) &&
796  (ret2 = PyObject_CallMethod(seq, "register", "O", type2));
797 
798  Py_XDECREF(collections);
799  Py_XDECREF(seq);
800  Py_XDECREF(ret1);
801  Py_XDECREF(ret2);
802  return ok;
803 }
804 
805 bool PyUpb_Repeated_Init(PyObject* m) {
807 
808  state->repeated_composite_container_type =
810  state->repeated_scalar_container_type =
812 
813  return state->repeated_composite_container_type &&
814  state->repeated_scalar_container_type &&
816 }
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
convert.h
upb_Array_New
upb_Array * upb_Array_New(upb_Arena *a, upb_CType type)
Definition: reflection.c:358
PyUpb_RepeatedContainer_SetSubscript
static int PyUpb_RepeatedContainer_SetSubscript(PyUpb_RepeatedContainer *self, upb_Array *arr, const upb_FieldDef *f, Py_ssize_t idx, Py_ssize_t count, Py_ssize_t step, PyObject *value)
Definition: repeated.c:341
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
obj
OPENSSL_EXPORT const ASN1_OBJECT * obj
Definition: x509.h:1671
grpc::testing::val1
const char val1[]
Definition: client_context_test_peer_test.cc:34
dst
static const char dst[]
Definition: test-fs-copyfile.c:37
PyUpb_RepeatedContainer::PyObject_HEAD
PyObject_HEAD
Definition: repeated.c:74
upb_Array_Delete
void upb_Array_Delete(upb_Array *arr, size_t i, size_t count)
Definition: reflection.c:411
regen-readme.it
it
Definition: regen-readme.py:15
PyUpb_CMessage_MergeFrom
PyObject * PyUpb_CMessage_MergeFrom(PyObject *self, PyObject *arg)
Definition: upb/python/message.c:1097
PyUpb_RepeatedContainer_GetClass
static PyTypeObject * PyUpb_RepeatedContainer_GetClass(const upb_FieldDef *f)
Definition: repeated.c:152
PyUpb_RepeatedContainer_RichCompare
static PyObject * PyUpb_RepeatedContainer_RichCompare(PyObject *_self, PyObject *_other, int opid)
Definition: repeated.c:297
PyUpb_RepeatedContainer::arr
upb_Array * arr
Definition: repeated.c:83
upb_Array_Resize
bool upb_Array_Resize(upb_Array *arr, size_t size, upb_Arena *arena)
Definition: reflection.c:419
PyUpb_RepeatedContainer_MergeFrom
static PyObject * PyUpb_RepeatedContainer_MergeFrom(PyObject *_self, PyObject *args)
Definition: repeated.c:564
PyUpb_CMessage_Verify
bool PyUpb_CMessage_Verify(PyObject *self)
Definition: upb/python/message.c:235
upb_MessageDef
Definition: upb/upb/def.c:100
PyUpb_RepeatedContainer_GetFieldDescriptor
static PyObject * PyUpb_RepeatedContainer_GetFieldDescriptor(PyUpb_RepeatedContainer *self)
Definition: repeated.c:91
elem
Timer elem
Definition: event_engine/iomgr_event_engine/timer_heap_test.cc:109
PyUpb_UpbToPy
PyObject * PyUpb_UpbToPy(upb_MessageValue val, const upb_FieldDef *f, PyObject *arena)
Definition: upb/python/convert.c:35
binary_size.new_size
def new_size
Definition: binary_size.py:124
error_ref_leak.err
err
Definition: error_ref_leak.py:35
PyUpb_RepeatedCompositeContainer_Append
static PyObject * PyUpb_RepeatedCompositeContainer_Append(PyObject *_self, PyObject *value)
Definition: repeated.c:599
PyUpb_ModuleState_GetFromModule
PyUpb_ModuleState * PyUpb_ModuleState_GetFromModule(PyObject *module)
Definition: upb/python/protobuf.c:82
PyUpb_RepeatedScalarContainer_Spec
static PyType_Spec PyUpb_RepeatedScalarContainer_Spec
Definition: repeated.c:773
PyUpb_RepeatedContainer_Item
static PyObject * PyUpb_RepeatedContainer_Item(PyObject *_self, Py_ssize_t index)
Definition: repeated.c:256
PyUpb_CMessage_SetConcreteSubobj
void PyUpb_CMessage_SetConcreteSubobj(PyObject *_self, const upb_FieldDef *f, upb_MessageValue subobj)
Definition: upb/python/message.c:713
PyUpb_RepeatedContainer_Extend
PyObject * PyUpb_RepeatedContainer_Extend(PyObject *_self, PyObject *value)
Definition: repeated.c:221
upb_Array_Get
upb_MessageValue upb_Array_Get(const upb_Array *arr, size_t i)
Definition: reflection.c:364
PyUpb_RepeatedContainer_DeleteSubscript
static int PyUpb_RepeatedContainer_DeleteSubscript(upb_Array *arr, Py_ssize_t idx, Py_ssize_t count, Py_ssize_t step)
Definition: repeated.c:398
upb_Array_Move
void upb_Array_Move(upb_Array *arr, size_t dst_idx, size_t src_idx, size_t count)
Definition: reflection.c:388
arena
grpc_core::ScopedArenaPtr arena
Definition: binder_transport_test.cc:237
upb_Message_New
upb_Message * upb_Message_New(const upb_MessageDef *m, upb_Arena *a)
Definition: reflection.c:95
upb_MessageValue
Definition: upb/upb/reflection.h:40
PyUpb_Repeated_Init
bool PyUpb_Repeated_Init(PyObject *m)
Definition: repeated.c:805
start
static uint64_t start
Definition: benchmark-pound.c:74
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
PyUpb_RepeatedCompositeContainer_AppendNew
static PyObject * PyUpb_RepeatedCompositeContainer_AppendNew(PyObject *_self)
Definition: repeated.c:573
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
upb_FieldDef_IsMap
bool upb_FieldDef_IsMap(const upb_FieldDef *f)
Definition: upb/upb/def.c:659
PyUpb_Dealloc
static void PyUpb_Dealloc(void *self)
Definition: upb/python/protobuf.h:208
PyUpb_RepeatedContainer_Reify
void PyUpb_RepeatedContainer_Reify(PyObject *_self, upb_Array *arr)
Definition: repeated.c:109
PyUpb_Repeated_RegisterAsSequence
static bool PyUpb_Repeated_RegisterAsSequence(PyUpb_ModuleState *state)
Definition: repeated.c:785
upb_Array
Definition: msg_internal.h:424
PyUpb_RepeatedScalarContainer_Methods
static PyMethodDef PyUpb_RepeatedScalarContainer_Methods[]
Definition: repeated.c:734
grpc::testing::val2
const char val2[]
Definition: client_context_test_peer_test.cc:35
PyUpb_RepeatedScalarContainer_Slots
static PyType_Slot PyUpb_RepeatedScalarContainer_Slots[]
Definition: repeated.c:758
PyUpb_RepeatedScalarContainer_Append
static PyObject * PyUpb_RepeatedScalarContainer_Append(PyObject *_self, PyObject *value)
Definition: repeated.c:700
half
Definition: passthru_endpoint.cc:53
PyUpb_AddClass
PyTypeObject * PyUpb_AddClass(PyObject *m, PyType_Spec *spec)
Definition: upb/python/protobuf.c:274
PyUpb_RepeatedContainer_Sort
static PyObject * PyUpb_RepeatedContainer_Sort(PyObject *pself, PyObject *args, PyObject *kwds)
Definition: repeated.c:515
PyUpb_RepeatedCompositeContainer_Methods
static PyMethodDef PyUpb_RepeatedCompositeContainer_Methods[]
Definition: repeated.c:651
PyUpb_FieldDescriptor_Get
PyObject * PyUpb_FieldDescriptor_Get(const upb_FieldDef *field)
Definition: descriptor.c:870
PyUpb_RepeatedContainer::field
uintptr_t field
Definition: repeated.c:80
upb_MessageValue::msg_val
const upb_Message * msg_val
Definition: upb/upb/reflection.h:49
upb_Array_Append
bool upb_Array_Append(upb_Array *arr, upb_MessageValue val, upb_Arena *arena)
Definition: reflection.c:380
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint-msvc2008.h:119
upb_FieldDef_CType
upb_CType upb_FieldDef_CType(const upb_FieldDef *f)
Definition: upb/upb/def.c:500
PyUpb_Forbidden_New
PyObject * PyUpb_Forbidden_New(PyObject *cls, PyObject *args, PyObject *kwds)
Definition: upb/python/protobuf.c:312
PyUpb_CMessage_CacheDelete
void PyUpb_CMessage_CacheDelete(PyObject *_self, const upb_FieldDef *f)
Definition: upb/python/message.c:708
PyUpb_RepeatedContainer_ToList
PyObject * PyUpb_RepeatedContainer_ToList(PyObject *_self)
Definition: repeated.c:269
protobuf.h
upb_Message
void upb_Message
Definition: msg.h:49
upb_FieldDef_MessageSubDef
const upb_MessageDef * upb_FieldDef_MessageSubDef(const upb_FieldDef *f)
Definition: upb/upb/def.c:619
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
PyUpb_FieldDescriptor_GetDef
const upb_FieldDef * PyUpb_FieldDescriptor_GetDef(PyObject *_self)
Definition: descriptor.c:864
setup.idx
idx
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:197
msg
std::string msg
Definition: client_interceptors_end2end_test.cc:372
IndexToRange
static bool IndexToRange(PyObject *index, Py_ssize_t size, Py_ssize_t *i, Py_ssize_t *count, Py_ssize_t *step)
Definition: repeated.c:44
upb_FieldDef
Definition: upb/upb/def.c:56
upb_Array_Size
size_t upb_Array_Size(const upb_Array *arr)
Definition: reflection.c:362
PyUpb_RepeatedContainer_Assign
static bool PyUpb_RepeatedContainer_Assign(PyObject *_self, PyObject *list)
Definition: repeated.c:494
PyUpb_RepeatedContainer_NewStub
PyObject * PyUpb_RepeatedContainer_NewStub(PyObject *parent, const upb_FieldDef *f, PyObject *arena)
Definition: repeated.c:165
upb_Array_Set
void upb_Array_Set(upb_Array *arr, size_t i, upb_MessageValue val)
Definition: reflection.c:373
PyUpb_RepeatedContainer_GetOrCreateWrapper
PyObject * PyUpb_RepeatedContainer_GetOrCreateWrapper(upb_Array *arr, const upb_FieldDef *f, PyObject *arena)
Definition: repeated.c:181
value
const char * value
Definition: hpack_parser_table.cc:165
PyUpb_ObjCache_Get
PyObject * PyUpb_ObjCache_Get(const void *key)
Definition: upb/python/protobuf.c:206
PyUpb_ModuleState_Get
PyUpb_ModuleState * PyUpb_ModuleState_Get(void)
Definition: upb/python/protobuf.c:89
message.h
PyUpb_RepeatedContainer_Insert
static PyObject * PyUpb_RepeatedContainer_Insert(PyObject *_self, PyObject *args)
Definition: repeated.c:613
PyUpb_Arena_Get
upb_Arena * PyUpb_Arena_Get(PyObject *arena)
Definition: upb/python/protobuf.c:231
PyUpb_RepeatedCompositeContainer_Spec
static PyType_Spec PyUpb_RepeatedCompositeContainer_Spec
Definition: repeated.c:688
absl::compare_internal::eq
eq
Definition: abseil-cpp/absl/types/compare.h:72
key
const char * key
Definition: hpack_parser_table.cc:164
PyUpb_Arena_New
PyObject * PyUpb_Arena_New(void)
Definition: upb/python/protobuf.c:219
PYUPB_MODULE_NAME
#define PYUPB_MODULE_NAME
Definition: upb/python/protobuf.h:43
PyUpb_RepeatedContainer_GetIfReified
static upb_Array * PyUpb_RepeatedContainer_GetIfReified(PyUpb_RepeatedContainer *self)
Definition: repeated.c:104
PyUpb_RepeatedContainer_DeepCopy
PyObject * PyUpb_RepeatedContainer_DeepCopy(PyObject *_self, PyObject *value)
Definition: repeated.c:201
count
int * count
Definition: bloaty/third_party/googletest/googlemock/test/gmock_stress_test.cc:96
upb_FieldDef_IsRepeated
bool upb_FieldDef_IsRepeated(const upb_FieldDef *f)
Definition: upb/upb/def.c:651
PyUpb_ModuleState
Definition: upb/python/protobuf.h:66
PyUpb_ObjCache_Add
void PyUpb_ObjCache_Add(const void *key, PyObject *py_obj)
Definition: upb/python/protobuf.c:190
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
PyUpb_RepeatedContainer_Subscript
static PyObject * PyUpb_RepeatedContainer_Subscript(PyObject *_self, PyObject *key)
Definition: repeated.c:316
PyUpb_RepeatedContainer_GetField
static const upb_FieldDef * PyUpb_RepeatedContainer_GetField(PyUpb_RepeatedContainer *self)
Definition: repeated.c:96
step
static int step
Definition: test-mutexes.c:31
PyUpb_RepeatedContainer_EnsureReified
upb_Array * PyUpb_RepeatedContainer_EnsureReified(PyObject *_self)
Definition: repeated.c:124
ok
bool ok
Definition: async_end2end_test.cc:197
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
PyUpb_RepeatedContainer::parent
PyObject * parent
Definition: repeated.c:82
PyUpb_CMessage_Get
PyObject * PyUpb_CMessage_Get(upb_Message *u_msg, const upb_MessageDef *m, PyObject *arena)
Definition: upb/python/message.c:751
upb_FieldDef_IsSubMessage
bool upb_FieldDef_IsSubMessage(const upb_FieldDef *f)
Definition: upb/upb/def.c:642
stop
static const char stop[]
Definition: benchmark-async-pummel.c:35
PyUpb_RepeatedContainer_Remove
static PyObject * PyUpb_RepeatedContainer_Remove(PyObject *_self, PyObject *value)
Definition: repeated.c:468
PyUpb_RepeatedContainer::arena
PyObject * arena
Definition: repeated.c:75
PyUpb_RepeatedContainer::ptr
union PyUpb_RepeatedContainer::@696 ptr
i2
int i2
Definition: abseil-cpp/absl/container/btree_test.cc:2773
Py_TYPE
#define Py_TYPE(ob)
Definition: bloaty/third_party/protobuf/python/google/protobuf/pyext/descriptor.cc:164
PyUpb_RepeatedCompositeContainer_Slots
static PyType_Slot PyUpb_RepeatedCompositeContainer_Slots[]
Definition: repeated.c:675
PyUpb_RepeatedContainer
Definition: repeated.c:73
PyUpb_RepeatedContainer_Length
static Py_ssize_t PyUpb_RepeatedContainer_Length(PyObject *self)
Definition: repeated.c:159
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
self
PHP_PROTO_OBJECT_FREE_END PHP_PROTO_OBJECT_DTOR_END intern self
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/map.c:543
regress.m
m
Definition: regress/regress.py:25
PyUpb_RepeatedScalarContainer_AssignItem
static int PyUpb_RepeatedScalarContainer_AssignItem(PyObject *_self, Py_ssize_t index, PyObject *item)
Definition: repeated.c:714
PyUpb_CMessage_InitAttributes
int PyUpb_CMessage_InitAttributes(PyObject *_self, PyObject *args, PyObject *kwargs)
Definition: upb/python/message.c:436
PyUpb_ObjCache_Delete
void PyUpb_ObjCache_Delete(const void *key)
Definition: upb/python/protobuf.c:194
upb_Array_Insert
bool upb_Array_Insert(upb_Array *arr, size_t i, size_t count, upb_Arena *arena)
Definition: reflection.c:395
PyUpb_CMessage_GetIfReified
upb_Message * PyUpb_CMessage_GetIfReified(PyObject *_self)
Definition: upb/python/message.c:246
PyUpb_RepeatedCompositeContainer_Add
PyObject * PyUpb_RepeatedCompositeContainer_Add(PyObject *_self, PyObject *args, PyObject *kwargs)
Definition: repeated.c:586
PyUpb_RepeatedContainer_Dealloc
static void PyUpb_RepeatedContainer_Dealloc(PyObject *_self)
Definition: repeated.c:138
upb_Arena
Definition: upb_internal.h:36
PyUpb_RepeatedContainer_Pop
static PyObject * PyUpb_RepeatedContainer_Pop(PyObject *_self, PyObject *args)
Definition: repeated.c:454
PyUpb_RepeatedContainer_Reverse
static PyObject * PyUpb_RepeatedContainer_Reverse(PyObject *_self)
Definition: repeated.c:550
repeated
static grpc_slice repeated(char c, size_t length)
Definition: message_compress_test.cc:109
PyUpb_RepeatedContainer_AssignSubscript
static int PyUpb_RepeatedContainer_AssignSubscript(PyObject *_self, PyObject *key, PyObject *value)
Definition: repeated.c:437
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
PyUpb_RepeatedContainer_Repr
static PyObject * PyUpb_RepeatedContainer_Repr(PyObject *_self)
Definition: repeated.c:288
repeated.h
PyUpb_RepeatedContainer_IsStub
static bool PyUpb_RepeatedContainer_IsStub(PyUpb_RepeatedContainer *self)
Definition: repeated.c:87
PyUpb_PyToUpb
bool PyUpb_PyToUpb(PyObject *obj, const upb_FieldDef *f, upb_MessageValue *val, upb_Arena *arena)
Definition: upb/python/convert.c:179


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:01:08