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 (at) google.com (Anuraag Agrawal) 32 // Author: tibell (at) google.com (Johan Tibell) 33 34 #include <google/protobuf/pyext/repeated_scalar_container.h> 35 36 #include <memory> 37 #ifndef _SHARED_PTR_H 38 #include <google/protobuf/stubs/shared_ptr.h> 39 #endif 40 41 #include <google/protobuf/stubs/common.h> 42 #include <google/protobuf/descriptor.h> 43 #include <google/protobuf/dynamic_message.h> 44 #include <google/protobuf/message.h> 45 #include <google/protobuf/pyext/descriptor.h> 46 #include <google/protobuf/pyext/message.h> 47 #include <google/protobuf/pyext/scoped_pyobject_ptr.h> 48 49 #if PY_MAJOR_VERSION >= 3 50 #define PyInt_FromLong PyLong_FromLong 51 #if PY_VERSION_HEX < 0x03030000 52 #error "Python 3.0 - 3.2 are not supported." 53 #else 54 #define PyString_AsString(ob) \ 55 (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob)) 56 #endif 57 #endif 58 59 namespace google { 60 namespace protobuf { 61 namespace python { 62 63 extern google::protobuf::DynamicMessageFactory* global_message_factory; 64 65 namespace repeated_scalar_container { 66 67 static int InternalAssignRepeatedField( 68 RepeatedScalarContainer* self, PyObject* list) { 69 self->message->GetReflection()->ClearField(self->message, 70 self->parent_field->descriptor); 71 for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) { 72 PyObject* value = PyList_GET_ITEM(list, i); 73 if (Append(self, value) == NULL) { 74 return -1; 75 } 76 } 77 return 0; 78 } 79 80 static Py_ssize_t Len(RepeatedScalarContainer* self) { 81 google::protobuf::Message* message = self->message; 82 return message->GetReflection()->FieldSize(*message, 83 self->parent_field->descriptor); 84 } 85 86 static int AssignItem(RepeatedScalarContainer* self, 87 Py_ssize_t index, 88 PyObject* arg) { 89 cmessage::AssureWritable(self->parent); 90 google::protobuf::Message* message = self->message; 91 const google::protobuf::FieldDescriptor* field_descriptor = 92 self->parent_field->descriptor; 93 if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) { 94 PyErr_SetString( 95 PyExc_KeyError, "Field does not belong to message!"); 96 return -1; 97 } 98 99 const google::protobuf::Reflection* reflection = message->GetReflection(); 100 int field_size = reflection->FieldSize(*message, field_descriptor); 101 if (index < 0) { 102 index = field_size + index; 103 } 104 if (index < 0 || index >= field_size) { 105 PyErr_Format(PyExc_IndexError, 106 "list assignment index (%d) out of range", 107 static_cast<int>(index)); 108 return -1; 109 } 110 111 if (arg == NULL) { 112 ScopedPyObjectPtr py_index(PyLong_FromLong(index)); 113 return cmessage::InternalDeleteRepeatedField(message, field_descriptor, 114 py_index, NULL); 115 } 116 117 if (PySequence_Check(arg) && !(PyBytes_Check(arg) || PyUnicode_Check(arg))) { 118 PyErr_SetString(PyExc_TypeError, "Value must be scalar"); 119 return -1; 120 } 121 122 switch (field_descriptor->cpp_type()) { 123 case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { 124 GOOGLE_CHECK_GET_INT32(arg, value, -1); 125 reflection->SetRepeatedInt32(message, field_descriptor, index, value); 126 break; 127 } 128 case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { 129 GOOGLE_CHECK_GET_INT64(arg, value, -1); 130 reflection->SetRepeatedInt64(message, field_descriptor, index, value); 131 break; 132 } 133 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { 134 GOOGLE_CHECK_GET_UINT32(arg, value, -1); 135 reflection->SetRepeatedUInt32(message, field_descriptor, index, value); 136 break; 137 } 138 case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { 139 GOOGLE_CHECK_GET_UINT64(arg, value, -1); 140 reflection->SetRepeatedUInt64(message, field_descriptor, index, value); 141 break; 142 } 143 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { 144 GOOGLE_CHECK_GET_FLOAT(arg, value, -1); 145 reflection->SetRepeatedFloat(message, field_descriptor, index, value); 146 break; 147 } 148 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { 149 GOOGLE_CHECK_GET_DOUBLE(arg, value, -1); 150 reflection->SetRepeatedDouble(message, field_descriptor, index, value); 151 break; 152 } 153 case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { 154 GOOGLE_CHECK_GET_BOOL(arg, value, -1); 155 reflection->SetRepeatedBool(message, field_descriptor, index, value); 156 break; 157 } 158 case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { 159 if (!CheckAndSetString( 160 arg, message, field_descriptor, reflection, false, index)) { 161 return -1; 162 } 163 break; 164 } 165 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { 166 GOOGLE_CHECK_GET_INT32(arg, value, -1); 167 const google::protobuf::EnumDescriptor* enum_descriptor = 168 field_descriptor->enum_type(); 169 const google::protobuf::EnumValueDescriptor* enum_value = 170 enum_descriptor->FindValueByNumber(value); 171 if (enum_value != NULL) { 172 reflection->SetRepeatedEnum(message, field_descriptor, index, 173 enum_value); 174 } else { 175 ScopedPyObjectPtr s(PyObject_Str(arg)); 176 if (s != NULL) { 177 PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", 178 PyString_AsString(s.get())); 179 } 180 return -1; 181 } 182 break; 183 } 184 default: 185 PyErr_Format( 186 PyExc_SystemError, "Adding value to a field of unknown type %d", 187 field_descriptor->cpp_type()); 188 return -1; 189 } 190 return 0; 191 } 192 193 static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { 194 google::protobuf::Message* message = self->message; 195 const google::protobuf::FieldDescriptor* field_descriptor = 196 self->parent_field->descriptor; 197 const google::protobuf::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 assignment index (%d) out of range", 206 static_cast<int>(index)); 207 return NULL; 208 } 209 210 PyObject* result = NULL; 211 switch (field_descriptor->cpp_type()) { 212 case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { 213 int32 value = reflection->GetRepeatedInt32( 214 *message, field_descriptor, index); 215 result = PyInt_FromLong(value); 216 break; 217 } 218 case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { 219 int64 value = reflection->GetRepeatedInt64( 220 *message, field_descriptor, index); 221 result = PyLong_FromLongLong(value); 222 break; 223 } 224 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { 225 uint32 value = reflection->GetRepeatedUInt32( 226 *message, field_descriptor, index); 227 result = PyLong_FromLongLong(value); 228 break; 229 } 230 case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { 231 uint64 value = reflection->GetRepeatedUInt64( 232 *message, field_descriptor, index); 233 result = PyLong_FromUnsignedLongLong(value); 234 break; 235 } 236 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { 237 float value = reflection->GetRepeatedFloat( 238 *message, field_descriptor, index); 239 result = PyFloat_FromDouble(value); 240 break; 241 } 242 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { 243 double value = reflection->GetRepeatedDouble( 244 *message, field_descriptor, index); 245 result = PyFloat_FromDouble(value); 246 break; 247 } 248 case google::protobuf::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 google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { 255 const google::protobuf::EnumValueDescriptor* enum_value = 256 message->GetReflection()->GetRepeatedEnum( 257 *message, field_descriptor, index); 258 result = PyInt_FromLong(enum_value->number()); 259 break; 260 } 261 case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { 262 string value = reflection->GetRepeatedString( 263 *message, field_descriptor, index); 264 result = ToStringObject(field_descriptor, value); 265 break; 266 } 267 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { 268 PyObject* py_cmsg = PyObject_CallObject(reinterpret_cast<PyObject*>( 269 &CMessage_Type), NULL); 270 if (py_cmsg == NULL) { 271 return NULL; 272 } 273 CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg); 274 const google::protobuf::Message& msg = reflection->GetRepeatedMessage( 275 *message, field_descriptor, index); 276 cmsg->owner = self->owner; 277 cmsg->parent = self->parent; 278 cmsg->message = const_cast<google::protobuf::Message*>(&msg); 279 cmsg->read_only = false; 280 result = reinterpret_cast<PyObject*>(py_cmsg); 281 break; 282 } 283 default: 284 PyErr_Format( 285 PyExc_SystemError, 286 "Getting value from a repeated field of unknown type %d", 287 field_descriptor->cpp_type()); 288 } 289 290 return result; 291 } 292 293 static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { 294 Py_ssize_t from; 295 Py_ssize_t to; 296 Py_ssize_t step; 297 Py_ssize_t length; 298 Py_ssize_t slicelength; 299 bool return_list = false; 300 #if PY_MAJOR_VERSION < 3 301 if (PyInt_Check(slice)) { 302 from = to = PyInt_AsLong(slice); 303 } else // NOLINT 304 #endif 305 if (PyLong_Check(slice)) { 306 from = to = PyLong_AsLong(slice); 307 } else if (PySlice_Check(slice)) { 308 length = Len(self); 309 #if PY_MAJOR_VERSION >= 3 310 if (PySlice_GetIndicesEx(slice, 311 #else 312 if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), 313 #endif 314 length, &from, &to, &step, &slicelength) == -1) { 315 return NULL; 316 } 317 return_list = true; 318 } else { 319 PyErr_SetString(PyExc_TypeError, "list indices must be integers"); 320 return NULL; 321 } 322 323 if (!return_list) { 324 return Item(self, from); 325 } 326 327 PyObject* list = PyList_New(0); 328 if (list == NULL) { 329 return NULL; 330 } 331 if (from <= to) { 332 if (step < 0) { 333 return list; 334 } 335 for (Py_ssize_t index = from; index < to; index += step) { 336 if (index < 0 || index >= length) { 337 break; 338 } 339 ScopedPyObjectPtr s(Item(self, index)); 340 PyList_Append(list, s); 341 } 342 } else { 343 if (step > 0) { 344 return list; 345 } 346 for (Py_ssize_t index = from; index > to; index += step) { 347 if (index < 0 || index >= length) { 348 break; 349 } 350 ScopedPyObjectPtr s(Item(self, index)); 351 PyList_Append(list, s); 352 } 353 } 354 return list; 355 } 356 357 PyObject* Append(RepeatedScalarContainer* self, PyObject* item) { 358 cmessage::AssureWritable(self->parent); 359 google::protobuf::Message* message = self->message; 360 const google::protobuf::FieldDescriptor* field_descriptor = 361 self->parent_field->descriptor; 362 363 if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) { 364 PyErr_SetString( 365 PyExc_KeyError, "Field does not belong to message!"); 366 return NULL; 367 } 368 369 const google::protobuf::Reflection* reflection = message->GetReflection(); 370 switch (field_descriptor->cpp_type()) { 371 case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { 372 GOOGLE_CHECK_GET_INT32(item, value, NULL); 373 reflection->AddInt32(message, field_descriptor, value); 374 break; 375 } 376 case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { 377 GOOGLE_CHECK_GET_INT64(item, value, NULL); 378 reflection->AddInt64(message, field_descriptor, value); 379 break; 380 } 381 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { 382 GOOGLE_CHECK_GET_UINT32(item, value, NULL); 383 reflection->AddUInt32(message, field_descriptor, value); 384 break; 385 } 386 case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { 387 GOOGLE_CHECK_GET_UINT64(item, value, NULL); 388 reflection->AddUInt64(message, field_descriptor, value); 389 break; 390 } 391 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { 392 GOOGLE_CHECK_GET_FLOAT(item, value, NULL); 393 reflection->AddFloat(message, field_descriptor, value); 394 break; 395 } 396 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { 397 GOOGLE_CHECK_GET_DOUBLE(item, value, NULL); 398 reflection->AddDouble(message, field_descriptor, value); 399 break; 400 } 401 case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { 402 GOOGLE_CHECK_GET_BOOL(item, value, NULL); 403 reflection->AddBool(message, field_descriptor, value); 404 break; 405 } 406 case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { 407 if (!CheckAndSetString( 408 item, message, field_descriptor, reflection, true, -1)) { 409 return NULL; 410 } 411 break; 412 } 413 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { 414 GOOGLE_CHECK_GET_INT32(item, value, NULL); 415 const google::protobuf::EnumDescriptor* enum_descriptor = 416 field_descriptor->enum_type(); 417 const google::protobuf::EnumValueDescriptor* enum_value = 418 enum_descriptor->FindValueByNumber(value); 419 if (enum_value != NULL) { 420 reflection->AddEnum(message, field_descriptor, enum_value); 421 } else { 422 ScopedPyObjectPtr s(PyObject_Str(item)); 423 if (s != NULL) { 424 PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", 425 PyString_AsString(s.get())); 426 } 427 return NULL; 428 } 429 break; 430 } 431 default: 432 PyErr_Format( 433 PyExc_SystemError, "Adding value to a field of unknown type %d", 434 field_descriptor->cpp_type()); 435 return NULL; 436 } 437 438 Py_RETURN_NONE; 439 } 440 441 static int AssSubscript(RepeatedScalarContainer* self, 442 PyObject* slice, 443 PyObject* value) { 444 Py_ssize_t from; 445 Py_ssize_t to; 446 Py_ssize_t step; 447 Py_ssize_t length; 448 Py_ssize_t slicelength; 449 bool create_list = false; 450 451 cmessage::AssureWritable(self->parent); 452 google::protobuf::Message* message = self->message; 453 const google::protobuf::FieldDescriptor* field_descriptor = 454 self->parent_field->descriptor; 455 456 #if PY_MAJOR_VERSION < 3 457 if (PyInt_Check(slice)) { 458 from = to = PyInt_AsLong(slice); 459 } else 460 #endif 461 if (PyLong_Check(slice)) { 462 from = to = PyLong_AsLong(slice); 463 } else if (PySlice_Check(slice)) { 464 const google::protobuf::Reflection* reflection = message->GetReflection(); 465 length = reflection->FieldSize(*message, field_descriptor); 466 #if PY_MAJOR_VERSION >= 3 467 if (PySlice_GetIndicesEx(slice, 468 #else 469 if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice), 470 #endif 471 length, &from, &to, &step, &slicelength) == -1) { 472 return -1; 473 } 474 create_list = true; 475 } else { 476 PyErr_SetString(PyExc_TypeError, "list indices must be integers"); 477 return -1; 478 } 479 480 if (value == NULL) { 481 return cmessage::InternalDeleteRepeatedField( 482 message, field_descriptor, slice, NULL); 483 } 484 485 if (!create_list) { 486 return AssignItem(self, from, value); 487 } 488 489 ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); 490 if (full_slice == NULL) { 491 return -1; 492 } 493 ScopedPyObjectPtr new_list(Subscript(self, full_slice)); 494 if (new_list == NULL) { 495 return -1; 496 } 497 if (PySequence_SetSlice(new_list, from, to, value) < 0) { 498 return -1; 499 } 500 501 return InternalAssignRepeatedField(self, new_list); 502 } 503 504 PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) { 505 cmessage::AssureWritable(self->parent); 506 if (PyObject_Not(value)) { 507 Py_RETURN_NONE; 508 } 509 ScopedPyObjectPtr iter(PyObject_GetIter(value)); 510 if (iter == NULL) { 511 PyErr_SetString(PyExc_TypeError, "Value must be iterable"); 512 return NULL; 513 } 514 ScopedPyObjectPtr next; 515 while ((next.reset(PyIter_Next(iter))) != NULL) { 516 if (Append(self, next) == NULL) { 517 return NULL; 518 } 519 } 520 if (PyErr_Occurred()) { 521 return NULL; 522 } 523 Py_RETURN_NONE; 524 } 525 526 static PyObject* Insert(RepeatedScalarContainer* self, PyObject* args) { 527 Py_ssize_t index; 528 PyObject* value; 529 if (!PyArg_ParseTuple(args, "lO", &index, &value)) { 530 return NULL; 531 } 532 ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); 533 ScopedPyObjectPtr new_list(Subscript(self, full_slice)); 534 if (PyList_Insert(new_list, index, value) < 0) { 535 return NULL; 536 } 537 int ret = InternalAssignRepeatedField(self, new_list); 538 if (ret < 0) { 539 return NULL; 540 } 541 Py_RETURN_NONE; 542 } 543 544 static PyObject* Remove(RepeatedScalarContainer* self, PyObject* value) { 545 Py_ssize_t match_index = -1; 546 for (Py_ssize_t i = 0; i < Len(self); ++i) { 547 ScopedPyObjectPtr elem(Item(self, i)); 548 if (PyObject_RichCompareBool(elem, value, Py_EQ)) { 549 match_index = i; 550 break; 551 } 552 } 553 if (match_index == -1) { 554 PyErr_SetString(PyExc_ValueError, "remove(x): x not in container"); 555 return NULL; 556 } 557 if (AssignItem(self, match_index, NULL) < 0) { 558 return NULL; 559 } 560 Py_RETURN_NONE; 561 } 562 563 static PyObject* RichCompare(RepeatedScalarContainer* self, 564 PyObject* other, 565 int opid) { 566 if (opid != Py_EQ && opid != Py_NE) { 567 Py_INCREF(Py_NotImplemented); 568 return Py_NotImplemented; 569 } 570 571 // Copy the contents of this repeated scalar container, and other if it is 572 // also a repeated scalar container, into Python lists so we can delegate 573 // to the list's compare method. 574 575 ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); 576 if (full_slice == NULL) { 577 return NULL; 578 } 579 580 ScopedPyObjectPtr other_list_deleter; 581 if (PyObject_TypeCheck(other, &RepeatedScalarContainer_Type)) { 582 other_list_deleter.reset(Subscript( 583 reinterpret_cast<RepeatedScalarContainer*>(other), full_slice)); 584 other = other_list_deleter.get(); 585 } 586 587 ScopedPyObjectPtr list(Subscript(self, full_slice)); 588 if (list == NULL) { 589 return NULL; 590 } 591 return PyObject_RichCompare(list, other, opid); 592 } 593 594 PyObject* Reduce(RepeatedScalarContainer* unused_self) { 595 PyErr_Format( 596 PickleError_class, 597 "can't pickle repeated message fields, convert to list first"); 598 return NULL; 599 } 600 601 static PyObject* Sort(RepeatedScalarContainer* self, 602 PyObject* args, 603 PyObject* kwds) { 604 // Support the old sort_function argument for backwards 605 // compatibility. 606 if (kwds != NULL) { 607 PyObject* sort_func = PyDict_GetItemString(kwds, "sort_function"); 608 if (sort_func != NULL) { 609 // Must set before deleting as sort_func is a borrowed reference 610 // and kwds might be the only thing keeping it alive. 611 if (PyDict_SetItemString(kwds, "cmp", sort_func) == -1) 612 return NULL; 613 if (PyDict_DelItemString(kwds, "sort_function") == -1) 614 return NULL; 615 } 616 } 617 618 ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); 619 if (full_slice == NULL) { 620 return NULL; 621 } 622 ScopedPyObjectPtr list(Subscript(self, full_slice)); 623 if (list == NULL) { 624 return NULL; 625 } 626 ScopedPyObjectPtr m(PyObject_GetAttrString(list, "sort")); 627 if (m == NULL) { 628 return NULL; 629 } 630 ScopedPyObjectPtr res(PyObject_Call(m, args, kwds)); 631 if (res == NULL) { 632 return NULL; 633 } 634 int ret = InternalAssignRepeatedField(self, list); 635 if (ret < 0) { 636 return NULL; 637 } 638 Py_RETURN_NONE; 639 } 640 641 static int Init(RepeatedScalarContainer* self, 642 PyObject* args, 643 PyObject* kwargs) { 644 PyObject* py_parent; 645 PyObject* py_parent_field; 646 if (!PyArg_UnpackTuple(args, "__init__()", 2, 2, &py_parent, 647 &py_parent_field)) { 648 return -1; 649 } 650 651 if (!PyObject_TypeCheck(py_parent, &CMessage_Type)) { 652 PyErr_Format(PyExc_TypeError, 653 "expect %s, but got %s", 654 CMessage_Type.tp_name, 655 Py_TYPE(py_parent)->tp_name); 656 return -1; 657 } 658 659 if (!PyObject_TypeCheck(py_parent_field, &CFieldDescriptor_Type)) { 660 PyErr_Format(PyExc_TypeError, 661 "expect %s, but got %s", 662 CFieldDescriptor_Type.tp_name, 663 Py_TYPE(py_parent_field)->tp_name); 664 return -1; 665 } 666 667 CMessage* cmessage = reinterpret_cast<CMessage*>(py_parent); 668 CFieldDescriptor* cdescriptor = reinterpret_cast<CFieldDescriptor*>( 669 py_parent_field); 670 671 if (!FIELD_BELONGS_TO_MESSAGE(cdescriptor->descriptor, cmessage->message)) { 672 PyErr_SetString( 673 PyExc_KeyError, "Field does not belong to message!"); 674 return -1; 675 } 676 677 self->message = cmessage->message; 678 self->parent = cmessage; 679 self->parent_field = cdescriptor; 680 self->owner = cmessage->owner; 681 return 0; 682 } 683 684 // Initializes the underlying Message object of "to" so it becomes a new parent 685 // repeated scalar, and copies all the values from "from" to it. A child scalar 686 // container can be released by passing it as both from and to (e.g. making it 687 // the recipient of the new parent message and copying the values from itself). 688 static int InitializeAndCopyToParentContainer( 689 RepeatedScalarContainer* from, 690 RepeatedScalarContainer* to) { 691 ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL)); 692 if (full_slice == NULL) { 693 return -1; 694 } 695 ScopedPyObjectPtr values(Subscript(from, full_slice)); 696 if (values == NULL) { 697 return -1; 698 } 699 google::protobuf::Message* new_message = global_message_factory->GetPrototype( 700 from->message->GetDescriptor())->New(); 701 to->parent = NULL; 702 // TODO(anuraag): Document why it's OK to hang on to parent_field, 703 // even though it's a weak reference. It ought to be enough to 704 // hold on to the FieldDescriptor only. 705 to->parent_field = from->parent_field; 706 to->message = new_message; 707 to->owner.reset(new_message); 708 if (InternalAssignRepeatedField(to, values) < 0) { 709 return -1; 710 } 711 return 0; 712 } 713 714 int Release(RepeatedScalarContainer* self) { 715 return InitializeAndCopyToParentContainer(self, self); 716 } 717 718 PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) { 719 ScopedPyObjectPtr init_args( 720 PyTuple_Pack(2, self->parent, self->parent_field)); 721 PyObject* clone = PyObject_CallObject( 722 reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type), init_args); 723 if (clone == NULL) { 724 return NULL; 725 } 726 if (!PyObject_TypeCheck(clone, &RepeatedScalarContainer_Type)) { 727 Py_DECREF(clone); 728 return NULL; 729 } 730 if (InitializeAndCopyToParentContainer( 731 self, reinterpret_cast<RepeatedScalarContainer*>(clone)) < 0) { 732 Py_DECREF(clone); 733 return NULL; 734 } 735 return clone; 736 } 737 738 static void Dealloc(RepeatedScalarContainer* self) { 739 self->owner.reset(); 740 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); 741 } 742 743 void SetOwner(RepeatedScalarContainer* self, 744 const shared_ptr<Message>& new_owner) { 745 self->owner = new_owner; 746 } 747 748 static PySequenceMethods SqMethods = { 749 (lenfunc)Len, /* sq_length */ 750 0, /* sq_concat */ 751 0, /* sq_repeat */ 752 (ssizeargfunc)Item, /* sq_item */ 753 0, /* sq_slice */ 754 (ssizeobjargproc)AssignItem /* sq_ass_item */ 755 }; 756 757 static PyMappingMethods MpMethods = { 758 (lenfunc)Len, /* mp_length */ 759 (binaryfunc)Subscript, /* mp_subscript */ 760 (objobjargproc)AssSubscript, /* mp_ass_subscript */ 761 }; 762 763 static PyMethodDef Methods[] = { 764 { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, 765 "Makes a deep copy of the class." }, 766 { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, 767 "Outputs picklable representation of the repeated field." }, 768 { "append", (PyCFunction)Append, METH_O, 769 "Appends an object to the repeated container." }, 770 { "extend", (PyCFunction)Extend, METH_O, 771 "Appends objects to the repeated container." }, 772 { "insert", (PyCFunction)Insert, METH_VARARGS, 773 "Appends objects to the repeated container." }, 774 { "remove", (PyCFunction)Remove, METH_O, 775 "Removes an object from the repeated container." }, 776 { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS, 777 "Sorts the repeated container."}, 778 { NULL, NULL } 779 }; 780 781 } // namespace repeated_scalar_container 782 783 PyTypeObject RepeatedScalarContainer_Type = { 784 PyVarObject_HEAD_INIT(&PyType_Type, 0) 785 "google.protobuf.internal." 786 "cpp._message.RepeatedScalarContainer", // tp_name 787 sizeof(RepeatedScalarContainer), // tp_basicsize 788 0, // tp_itemsize 789 (destructor)repeated_scalar_container::Dealloc, // tp_dealloc 790 0, // tp_print 791 0, // tp_getattr 792 0, // tp_setattr 793 0, // tp_compare 794 0, // tp_repr 795 0, // tp_as_number 796 &repeated_scalar_container::SqMethods, // tp_as_sequence 797 &repeated_scalar_container::MpMethods, // tp_as_mapping 798 0, // tp_hash 799 0, // tp_call 800 0, // tp_str 801 0, // tp_getattro 802 0, // tp_setattro 803 0, // tp_as_buffer 804 Py_TPFLAGS_DEFAULT, // tp_flags 805 "A Repeated scalar container", // tp_doc 806 0, // tp_traverse 807 0, // tp_clear 808 (richcmpfunc)repeated_scalar_container::RichCompare, // tp_richcompare 809 0, // tp_weaklistoffset 810 0, // tp_iter 811 0, // tp_iternext 812 repeated_scalar_container::Methods, // tp_methods 813 0, // tp_members 814 0, // tp_getset 815 0, // tp_base 816 0, // tp_dict 817 0, // tp_descr_get 818 0, // tp_descr_set 819 0, // tp_dictoffset 820 (initproc)repeated_scalar_container::Init, // tp_init 821 }; 822 823 } // namespace python 824 } // namespace protobuf 825 } // namespace google 826